aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorjustanothercatgirl <sotov2070@gmail.com>2024-10-04 17:37:14 +0300
committerjustanothercatgirl <sotov2070@gmail.com>2024-10-04 18:07:56 +0300
commitaa0d37540f5bc4bb6327b43c7213b46d0e261cf0 (patch)
treefa9d43d364f3a6d72d7a84c911aabc43658a2998 /src
parenta9bd52226fbcac98bddec9cffcef1ded8b75b5df (diff)
Пока не закончил логику выбора программы, но готовы все алгоритмы
Diffstat (limited to 'src')
-rw-r--r--src/integral.c38
-rw-r--r--src/main.c99
-rw-r--r--src/roots.c94
3 files changed, 231 insertions, 0 deletions
diff --git a/src/integral.c b/src/integral.c
new file mode 100644
index 0000000..d2ae11f
--- /dev/null
+++ b/src/integral.c
@@ -0,0 +1,38 @@
+#include "integral.h"
+
+// эта переменная позволяет контролировать точность интегрирования
+// и может быть установлена в файле main
+double accrc = 10000.0;
+
+// интеграл прямоугольниками
+double int_rect(f_t f, double a, double b) {
+ // f(x + dx/2) * dx
+ const double dx = (b-a) / accrc;
+ const double dx_2 = dx / 2.0;
+ double sum = 0.0;
+ for (double i = a + dx; i < b; i += dx)
+ sum += f(i - dx_2) * dx;
+ return sum;
+}
+
+// интеграл трапециями
+double int_trap(f_t f, double a, double b) {
+ // ( f(x) + f(x+dx) )/2 * dx
+ const double dx = (b-a) / accrc;
+ double sum = 0.0;
+ for (double i = a; i < b; i += dx)
+ sum += dx * (f(i) + f(i+dx))/2 ;
+ return sum;
+}
+
+// интегрирование параболами
+double int_simp(f_t f, double a, double b) {
+ const double dx = (b-a) / accrc;
+ const double dx_2 = dx / 2;
+ const double dx_6 = dx / 6;
+ double sum = 0.0;
+ for(double i = a; i < b; i += dx) {
+ sum += dx_6 * (f(i) + 4 * f(i + dx_2) + f(i + dx));
+ }
+ return sum;
+}
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..c3844f0
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,99 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include <unistd.h>
+#include <sys/fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <dlfcn.h>
+
+#include "integral.h"
+#include "roots.h"
+
+#define BLINK_TERM "\x1b[5m"
+#define RESET_TERM "\x1b[0m"
+#define FIFO_NAME "/tmp/compiler.fifo"
+#define SYMNAME "f"
+#define RDCHUNK 1024
+
+void *sohandle;
+
+// This will be the type of the function
+typedef double(*f_t)(double);
+
+enum optype {
+ // решение уравнений
+ SOL_BINSR, // дихтомии
+ SOL_HORDE, // хорды
+ SOL_NEWTN, // касательные
+ SOL_ITERN, // итерации
+ // численное интегрирование
+ INT_RECT, // прямоугольники
+ INT_TRAP, // трапеции
+ INT_SIMP, // симпсон
+};
+
+// Function that reads Your function, compiles and loads it.
+f_t input_and_compile(void) {
+ puts("Напечатайте функцию от x используя синтаксис С и функции библиотеки cmath: \n"
+ "(например, 'atan(x) / (1-exp(2*x))').\n"
+ "Закончите ввод, нажав enter." BLINK_TERM);
+
+ // input the function
+ size_t blen = 1024;
+ char *buffer = malloc(sizeof (char) * blen);
+ blen = read(STDIN_FILENO, buffer, 1024);
+ buffer[--blen] = '\0';
+ if (blen <= 0) return NULL;
+
+ // format the source
+ const char *fmt =
+ "#include <math.h>\n"
+ "double " SYMNAME "(double x) { return %s; }\n";
+ size_t sourcelen = strlen(fmt) - strlen("%s") + blen + 1;
+ char *source = malloc(sizeof (char) * sourcelen);
+ snprintf(source, sourcelen, fmt, buffer);
+
+ // spawn the compiler process
+ FILE *cc = popen("cc -shared -fPIE -fPIC -o " FIFO_NAME " -xc - -lm", "w");
+ fwrite(source, sizeof (char), sourcelen - 1, cc);
+ fflush(cc);
+ if (ferror(cc)) return NULL;
+ if (pclose(cc) != 0) return NULL;
+
+ // load dynamic library
+ sohandle = dlopen(FIFO_NAME, RTLD_NOW);
+ if (!sohandle) return NULL;
+ f_t ret = dlsym(sohandle, SYMNAME);
+
+ // free resources and return
+ free(buffer);
+ free(source);
+ return ret;
+}
+
+// Prompts user to choose input method
+enum optype get_optype(void) {
+ return INT_SIMP;
+}
+
+int main(int argc, char *argv[]) {
+ (void)argc; (void)argv;
+ f_t f = input_and_compile();
+ if (!f) goto exit;
+ double sln = sol_binsr(f, 0, 10, 0.001, 0.001);
+ printf("%lf\n", sln);
+ sln = sol_binsr(f, 0, 10, 0.001, 0.001);
+ printf("%lf\n", sln);
+ sln = sol_newtn(f, 5, 0.001, 0.001);
+ printf("%lf\n", sln);
+ sln = sol_itern(f, 0, 0.001, 0.001);
+ printf("%lf\n", sln);
+
+exit:
+ dlclose(sohandle);
+ return 0;
+}
diff --git a/src/roots.c b/src/roots.c
new file mode 100644
index 0000000..0aef762
--- /dev/null
+++ b/src/roots.c
@@ -0,0 +1,94 @@
+#include "roots.h"
+#include <math.h>
+#include <stdio.h>
+
+char root_ok = 1;
+
+// функция для проверки того, успешно ли выполнилась последняя функция
+char is_root_ok(void) {
+ return root_ok;
+}
+
+// метод дихтомии
+double sol_binsr(f_t f, double a, double b, double ex, double ey) {
+ if (copysign(1.0, f(a)) == copysign(1.0, f(b))) {
+ root_ok = 0;
+ return NAN;
+ }
+
+ double mid;
+ do {
+ mid = (a + b) / 2;
+ if (copysign(1.0, f(a)) != copysign(1.0, f(mid))) b = mid;
+ else a = mid;
+ } while (f(mid) > ey || (b-a) > ex);
+ root_ok = 1;
+ return mid;
+}
+
+// метод хорд
+double sol_chord(f_t f, double a, double b, double ex, double ey) {
+ if (copysign(1.0, f(a)) == copysign(1.0, f(b))) {
+ root_ok = 0;
+ return NAN;
+ }
+ double mid = a + fabs( f(a) / (f(b)-f(a)) ) * (b-a);
+ double diff = mid;
+ while (f(mid) > ey || fabs(diff - mid) > ex) {
+ diff = mid;
+ mid = a + fabs( f(a) / (f(b)-f(a)) ) * (b-a);
+ if (copysign(1.0, f(a)) != copysign(1.0, f(mid))) b = mid;
+ else a = mid;
+ }
+ root_ok = 1;
+ return mid;
+
+}
+
+// метод касательных (Ньютона)
+double sol_newtn(f_t f, double x0, double ex, double ey) {
+ const double dx = 1e-6;
+ double diff = x0+2*ex;
+
+ // check for divergence
+ double d2x0 = (f(x0 + 2*dx) - 2*f(x0 + dx) + f(x0))/(dx*dx);
+ if (copysign(1.0, d2x0) != copysign(1.0, f(x0))) {
+ root_ok = 0;
+ return NAN;
+ }
+ while ((fabs(diff - x0) > ex || f(x0) > ey)) {
+ double fx0 = f(x0);
+ double dx0 = (f(x0+dx) - fx0) / dx;
+ diff = x0;
+ x0 -= fx0/dx0;
+ if (isinf(x0) || isnan(x0)) {
+ root_ok = 0;
+ return NAN;
+ }
+ }
+ root_ok = 1;
+ return x0;
+}
+
+// метод итераций
+double sol_itern(f_t f, double x0, double ex, double ey) {
+ const double dx = 1e-6;
+ double diff = x0 + 2*ex;
+
+ do {
+ double dx0 = (f(x0+dx) - f(x0))/dx;
+ if (fabs(dx0) > 1.0) {
+ root_ok = 0;
+ return NAN;
+ }
+ diff = x0;
+ x0 = f(x0);
+ printf("x0=%lf, f(x0)=%lf\n", x0, f(x0));
+ getchar();
+ } while (fabs(diff - x0) > ex || fabs(f(x0) - x0) > ey);
+ root_ok = 1;
+ return x0;
+}
+
+
+