diff options
author | justanothercatgirl <sotov2070@gmail.com> | 2024-10-13 19:28:57 +0300 |
---|---|---|
committer | justanothercatgirl <sotov2070@gmail.com> | 2024-10-13 19:28:57 +0300 |
commit | f5e0076a8455eec5b4a515b39202217f8a8b9e71 (patch) | |
tree | f5cd306d8eb2a516e2d3a83a9276d5aa60b658c0 /src | |
parent | 1fe251abc83ee3a38d9faea5be947c90d162c6ae (diff) |
Initial committask5
Diffstat (limited to 'src')
-rw-r--r-- | src/integral.c | 36 | ||||
-rw-r--r-- | src/main.c | 186 | ||||
-rw-r--r-- | src/roots.c | 94 |
3 files changed, 0 insertions, 316 deletions
diff --git a/src/integral.c b/src/integral.c deleted file mode 100644 index f791803..0000000 --- a/src/integral.c +++ /dev/null @@ -1,36 +0,0 @@ -#include "integral.h" - -// эта переменная позволяет контролировать точность интегрирования -// и может быть установлена в файле main -double accrc = 10000.0; - -// интеграл прямоугольниками -double int_rect(func_t f, double a, double b) { - 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(func_t f, double a, double b) { - 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(func_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 deleted file mode 100644 index ff1a59e..0000000 --- a/src/main.c +++ /dev/null @@ -1,186 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <ctype.h> - -#include <unistd.h> -#include <termios.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.tmp" -#define SYMNAME "f" -#define RDCHUNK 1024 - -void *sohandle = NULL; - -#define defer(val) do {ret = val; goto exit;} while(0) - -// This will be the type of the function -typedef double(*func_t)(double); - -typedef double(*calc2_t)(func_t, double, double); -typedef double(*calc3_t)(func_t, double, double, double); -typedef double(*calc4_t)(func_t, double, double, double, double); - -// для выбора того, что делать с функцией -enum optype { - // решение уравнений - SOL_BINSR, // дихтомии - SOL_CHORD, // хорды - SOL_NEWTN, // касательные - SOL_ITERN, // итерации - // численное интегрирование - INT_RECT, // прямоугольники - INT_TRAP, // трапеции - INT_SIMP, // симпсон -}; - -struct funcdescr { - void *f; - int argc; - const char *descr; -}; - -#define DESCR2 "начало и конец области интегрирования\n" -#define DESCR3 "начальное приближение, допустимую погрешность корня и невязку\n" -#define DESCR4 "левую и правую границы поиска, допустимую погрешность корня и невязку\n" - -static struct funcdescr functions[] = { - [SOL_BINSR] = {&sol_binsr, 4, DESCR4}, - [SOL_CHORD] = {&sol_chord, 4, DESCR4}, - [SOL_NEWTN] = {&sol_newtn, 3, DESCR3}, - [SOL_ITERN] = {&sol_itern, 3, DESCR3}, - [INT_RECT] = {&int_rect, 2, DESCR2}, - [INT_TRAP] = {&int_trap, 2, DESCR2}, - [INT_SIMP] = {&int_simp, 2, DESCR2}, -}; - -// Function that reads Your function, compiles and loads it. -func_t input_and_compile(void) { - puts("Напечатайте функцию от x используя синтаксис С и функции библиотеки cmath: \n" - "(например, 'atan(x) / (1-exp(2*x))').\n" - "Закончите ввод, нажав enter." BLINK_TERM); - func_t ret; - char *buffer = NULL, *source = NULL; - - // input the function - size_t blen = 1024; - buffer = malloc(sizeof (char) * blen); - blen = read(STDIN_FILENO, buffer, 1024); - buffer[--blen] = '\0'; - if (blen <= 0) defer(NULL); - puts(RESET_TERM); - - // 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; - 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); - if (ferror(cc)) { pclose(cc); defer(NULL); } - if (pclose(cc) != 0) defer(NULL); - - // load dynamic library - sohandle = dlopen(FIFO_NAME, RTLD_NOW); - if (!sohandle) defer(NULL); - ret = dlsym(sohandle, SYMNAME); - - // free resources and return -exit: - free(buffer); - free(source); - return ret; -} - -char _getchar(void) { - char ret; - while (isspace(ret = getchar())); - return ret; -} - -// Prompts user to choose input method -enum optype get_optype(void) { -prompt_init: - fputs("Что вы хотите сделать с функцией?\n" - "\t1: решить уравнение f(x) = x\n" - "\t2: решить уравнение f(x) = 0\n" - "\t3: численно вычислить интеграл f(x)\n" - "Введите число: ", stdout); - char c; - switch (_getchar()-'0') { - case 1: return SOL_ITERN; - - case 2: - prompt_sol: - fputs("\nКаким методом?\n" - "\t1: дихтомии (двоичный поиск)\n" - "\t2: хорд\n" - "\t3: касательных (Ньютона)\n" - "Введите число:", stdout); - c = _getchar() - '0'; - if (c <= 0 || c > 3) goto prompt_sol; - return SOL_BINSR + c - 1; - - case 3: - prompt_int: - fputs("\nКаким методом?\n" - "\t1: прямоугольников\n" - "\t2: трапеций\n" - "\t3: Симпсона (парабол)\n" - "Введите число: ", stdout); - c = _getchar() - '0'; - if (c <= 0 || c > 3) goto prompt_int; - return INT_RECT + c - 1; - - default: - puts("\nОшибка: ведите число от 1 до 3"); - goto prompt_init; - } -} - -int main(void) { - func_t f = input_and_compile(); - if (!f) goto exit; - struct funcdescr descr = functions[get_optype()]; - double a, b, c, d; - printf("Введите %i аргумента через пробел:\n\t%s\n", descr.argc, descr.descr); - double res; - switch (descr.argc) { - case 2: - scanf("%lf %lf", &a, &b); - res = ((calc2_t)descr.f)(f, a, b); - break; - case 3: - scanf("%lf %lf %lf", &a, &b, &c); - res = ((calc3_t)descr.f)(f, a, b, c); - break; - case 4: - scanf("%lf %lf %lf %lf", &a, &b, &c, &d); - res = ((calc4_t)descr.f)(f, a, b, c, d); - break; - default: __builtin_unreachable(); - } - if (!is_root_ok()) { - fputs("Корень не посчитан из-за ограничений метода\n", stderr); - goto exit; - } - printf("Результат: %lf\n", res); -exit: - if (sohandle) dlclose(sohandle); - remove(FIFO_NAME); - return 0; -} diff --git a/src/roots.c b/src/roots.c deleted file mode 100644 index f07240e..0000000 --- a/src/roots.c +++ /dev/null @@ -1,94 +0,0 @@ -#include "roots.h" -#include <math.h> -#include <stdio.h> - -char root_ok = 1; - -// функция для проверки того, успешно ли выполнилась последняя функция -char is_root_ok(void) { - return root_ok; -} - -// метод дихтомии -double sol_binsr(func_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(func_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(func_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(func_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; -} - - - |