diff options
author | justanothercatgirl <sotov2070@gmail.com> | 2024-10-04 17:37:14 +0300 |
---|---|---|
committer | justanothercatgirl <sotov2070@gmail.com> | 2024-10-04 18:07:56 +0300 |
commit | aa0d37540f5bc4bb6327b43c7213b46d0e261cf0 (patch) | |
tree | fa9d43d364f3a6d72d7a84c911aabc43658a2998 /src | |
parent | a9bd52226fbcac98bddec9cffcef1ded8b75b5df (diff) |
Пока не закончил логику выбора программы, но готовы все алгоритмы
Diffstat (limited to 'src')
-rw-r--r-- | src/integral.c | 38 | ||||
-rw-r--r-- | src/main.c | 99 | ||||
-rw-r--r-- | src/roots.c | 94 |
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; +} + + + |