diff options
-rw-r--r-- | 5_1.c | 80 | ||||
-rw-r--r-- | 5_2.c | 44 | ||||
-rw-r--r-- | 5_3.c | 39 | ||||
-rw-r--r-- | Makefile | 24 | ||||
-rw-r--r-- | README.md | 42 | ||||
-rw-r--r-- | compile_flags.txt | 2 | ||||
-rw-r--r-- | hof_example.c | 33 | ||||
-rw-r--r-- | include/integral.h | 12 | ||||
-rw-r--r-- | include/roots.h | 15 | ||||
-rw-r--r-- | matrix.c | 116 | ||||
-rw-r--r-- | matrix.h | 69 | ||||
-rw-r--r-- | src/integral.c | 36 | ||||
-rw-r--r-- | src/main.c | 186 | ||||
-rw-r--r-- | src/roots.c | 94 |
14 files changed, 366 insertions, 426 deletions
@@ -0,0 +1,80 @@ +#include <stdio.h> +#include <time.h> + +#include "matrix.h" + +#define RAND_CHUNK = 0x7FFFFFFF; + +enum optype { ADD, SUB, MUL, DIV, POW, NOP }; + +// #pragma - просто способ заткнуть компилятор, чтобы он не выдавал предупреждений +// делает lookup table для операции, основываясь на символе +// по сути выполняет роль dict() в питоне или std::unordered_map в C++ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Winitializer-overrides" +enum optype op_lookup[255] = { + [0 ... 254] = NOP, + ['+'] = ADD, + ['-'] = SUB, + ['*'] = MUL, + ['/'] = DIV, + ['^'] = POW, +}; +#pragma GCC diagnostic pop + +// исполняет операцию над матрицами +void inplace_matrix_op(struct matrix *restrict a, struct matrix const *b, const enum optype t) { + if (a->rows != b->rows || a->columns != b->columns) return; + for(usz i = 0; i < b->rows; ++i) { + for (usz j = 0; j < b->columns; ++j) { + switch (t) { + case ADD: a->data[i][j] += b->data[i][j]; break; + case SUB: a->data[i][j] -= b->data[i][j]; break; + case MUL: a->data[i][j] *= b->data[i][j]; break; + case DIV: a->data[i][j] /= b->data[i][j]; break; + case POW: a->data[i][j] = pow(a->data[i][j], b->data[i][j]); break; + case NOP: return; + } + } + } +} + +int main(void) { + srand(time(NULL)); + // выбираем размер матрицы +size_selection: + printf("Input the size of the matrixes (rows, columns) separated by a whitespace:\n"); + isz row, col; + scanf("%zu %zu", &row, &col); + if (row < 0 || col < 0) { + SKIP_INPUT; + goto size_selection; + } + // выбираем интервал для генерации случайных чисел +interval_selection: + SKIP_INPUT; + printf("Input the borders of the interval for generated values, separated by a whitespace:\n"); + double a, b; + if (scanf("%lf %lf", &a, &b) != 2) goto interval_selection; + // создаём матрицы + struct matrix A = matrix_new(row, col), B = matrix_new(row, col); + matrix_fill(&A, a, b); + matrix_fill(&B, a, b); + puts("A = "); matrix_print(&A); + puts("B = "); matrix_print(&B); + // выбираем, что с матрицами делать +op_selection: + SKIP_INPUT; + printf("Input the operation ( + - * / ^ ): "); + enum optype op = op_lookup[getchar()]; + if (op == NOP) goto op_selection; + // выполняем операцию + inplace_matrix_op(&A, &B, op); + puts("result:"); + matrix_print(&A); + // освобождаем память + matrix_free(A); + matrix_free(B); + // ;) + return 0; +} @@ -0,0 +1,44 @@ +#include <stdio.h> +#include <time.h> +#include "matrix.h" + +#define MRX_SZ 6 +#define add_func(name, func) \ + double name (double x){ \ + return func; \ + } + +add_func(x2, x*x) +add_func(x2_sinx, x2(sin(x))) +add_func(sqrtx_x2, sqrt(x) * x2(x)) +add_func(sqrt_sin_x2, sqrt(sin(x2(x)))) + +const func_t funcs[MRX_SZ] = { + x2, sin, sqrt, x2_sinx, sqrtx_x2, sqrt_sin_x2 +}; + +int main(void) { + srand(time(NULL)); + // выбираем интервал для генерации случайных чисел +interval_selection: + printf("Input the borders of the interval for generated values, separated by a whitespace:\n"); + double a, b; + if (scanf("%lf %lf", &a, &b) != 2) { + SKIP_INPUT; + goto interval_selection; + } + // создаём матрицы + struct matrix m = matrix_new(1, MRX_SZ); + matrix_fill(&m, a, b); + struct matrix f_mem = matrix_new(1, MRX_SZ); + struct fmatrix f = *(struct fmatrix*)&f_mem; + for (usz i = 0; i < f.columns; ++i) f.funcs[0][i] = funcs[i]; + // делаем грязную работу + puts("A = "); matrix_print(&m); + matrix_apply(&m, &f); + puts("f(A) = "); matrix_print(&m); + // очищаем память + matrix_free(m); + matrix_free(f_mem); + return 0; +} @@ -0,0 +1,39 @@ +#include <stdio.h> +#include <time.h> + +#include "matrix.h" + +int main(void) { + srand(time(NULL)); + // выбираем размер матрицы +size_selection: + printf("Input the size of the matrixes:\n"); + isz size; + scanf("%zu", &size); + if (size < 0) { + SKIP_INPUT; + goto size_selection; + } + // выбираем интервал для генерации случайных чисел +interval_selection: + SKIP_INPUT; + printf("Input the borders of the interval for generated values, separated by a whitespace:\n"); + double a, b; + if (scanf("%lf %lf", &a, &b) != 2) goto interval_selection; + // создаём матрицы + struct tumatrix A = tumatrix_new(size); + struct tumatrix B = tumatrix_new(size); + tumatrix_fill(&A, a, b); + tumatrix_fill(&B, a, b); + puts("A = "); tumatrix_print(&A); + puts("B = "); tumatrix_print(&B); + printf("det A = %lf\n", tumatrix_det(&A)); + printf("det B = %lf\n", tumatrix_det(&B)); + struct tumatrix C = tumatrix_mul(&A, &B); + puts("C = A*B = "); tumatrix_print(&C); + printf("det C = %lf\n", tumatrix_det(&C)); + tumatrix_free(A); + tumatrix_free(B); + tumatrix_free(C); + return 0; +} @@ -1,24 +1,16 @@ -CFLAGS = -O2 -Wall -Wextra -Werror -Iinclude +all: 5_1 5_2 5_3 -all: task4 +5_1: 5_1.c matrix.c + cc -o $@ $^ -lm -build: - mkdir -p build +5_2: 5_2.c matrix.c + cc -o $@ $^ -lm -build/roots.o: src/roots.c build - $(CC) $(CFLAGS) -c -o $@ $< - -build/integral.o: src/integral.c build - $(CC) $(CFLAGS) -c -o $@ $< - -task4: build/roots.o build/integral.o src/main.c - $(CC) $(CFLAGS) -o $@ $^ -lm -ldl +5_3: 5_3.c matrix.c + cc -o $@ $^ -lm .PHONY: clean -run: - ./task4 - clean: - rm -f build/*.o task4 + rm -f 5_1 5_2 5_3 @@ -1,35 +1,13 @@ -# ВАЖНО -## Запуск -Файл `main.c` РАБОТАЕТ ТОЛЬКО НА ЛИНУКСЕ. Все алгоритмы работают на любой платформе, но в функции main есть вещи (например, ввод функции на языке С), не осуществимые на винде. -Поэтому, если вы хотите ЗАПУСТИТЬ программу целиком - либо берите линукс, либо пишите свою функцию main, которая будет использовать алгоритмы из файлов `roots.c` или `integrals.c` -## А что такое `func_t f` в аргументах? -Я передаю интегрируемую функцию как аргумент в свою функцию. Да, вы можете передавать функции в функции. Это называется функции высшего порядка, пример использования есть в `hof_example.c`. -файл `hof_example.c` запустится на любой ОС без изменений -# Задание 4 -## Описание программы -* Вы вводите с клавиатуры функцию от переменной x, используя синтаксис Си -* Потом вы выбираете, какое задание выполнить: решение уравнения (приравнять функцию к нулю) или выполнить численное интегрирование. -* После этого вы выбираете способ проведения операции и вводите нужные для способа числа (интервал, начальное число и т.п.) -* Ответ выводится на экран. -## Файлы -Директория `include/`: Заголовочные файлы +# файлы +`5_1.c`, `5_2.c`, `5_3.c` - файлы для заданий 1, 2, 3 cоответственно -Директория `src/`: Файлы имплементации (с кодом) +`matrix.c`, `matrix.h` - файлы со всеми алгоритмами и логикой -`Makefile`: система сборки - -`src/main.c`: логика по вводу функции и по взаимодействию с пользователем - -`src/roots.c`: Все алгоритмы поиска корней - -`src/integral.c`: Все алгоритмы вычисления интеграла -## Как пользоваться? -ВСЕ ИНСТРУКЦИИ ДАЮТСЯ ПРИ ЗАПУСКЕ ПРОГРАММЫ - -Флагов командной строки нет -1. вводите функцию -2. вводите, что с ней делать (искать корни? интегрировать?) -3. вводите способ (трапеции, симпсон и т.п...) -4. вводите параметры (интервал или начальное приближение, допустимые погрешности...) -5. получаете результат +# структура +каждый файл `5_*` содержит в себе только main и, может быть, вспомогательную функцию, и отвечает только за ввод/вывод. +Эти файлы имеют строчку `#include "matrix.h"`, и вызывают функции оттуда. Чтобы разобраться, что есть что в файле matrix.h, +есть 1: комментарии, 2: исходники для заданий (можно посмотреть, какое задание вызывает какие функции). +# запуск +программы работают на любой платформе под компиляторами gcc и clang. MSVC (компилятор в visual studio) не проверял, он может +пожаловаться на `5_1.c`. Остальное должно работать без проблем. diff --git a/compile_flags.txt b/compile_flags.txt deleted file mode 100644 index 1919e8f..0000000 --- a/compile_flags.txt +++ /dev/null @@ -1,2 +0,0 @@ - -Iinclude - diff --git a/hof_example.c b/hof_example.c deleted file mode 100644 index d8fee90..0000000 --- a/hof_example.c +++ /dev/null @@ -1,33 +0,0 @@ -// Это пример использования функций высшего порядка -#include <stdio.h> -#include <math.h> - -// Синтаксис непонятный, но так я создаю "синоним" -// к указателю на функцию, принимающую 2 double и возвращающую double -typedef double(*func_t)(double, double); - - -// Эта функция "передаёт" аргументы в функцию и выводит результат -void calculate_and_print(func_t function, double arg1, double arg2) { - printf("F(%lf, %lf) = %lf\n", arg1, arg2, function(arg1, arg2)); -} - -// считает сумму x и y -double sum(double x, double y) { - return x + y; -} - -// считает произведение x и y -double prod(double x, double y) { - return x * y; -} - -int main(void) { - // передаёшь функцию в функцию по имени, - // как самый обычный аргумент - calculate_and_print(sum, 420, 69); - calculate_and_print(prod, 420, 69); - // fmax - функция стандартной библиотеки - // возвращает максимальное из двух чисел - calculate_and_print(fmax, 420, 69); -} diff --git a/include/integral.h b/include/integral.h deleted file mode 100644 index 3eb6ff7..0000000 --- a/include/integral.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef JUSTANOTHERCATGIRL_TASK4_INTEGRAL -#define JUSTANOTHERCATGIRL_TASK4_INTEGRAL - -typedef double(*func_t)(double); - -extern double accrc; - -double int_rect(func_t f, double a, double b); -double int_trap(func_t f, double a, double b); -double int_simp(func_t f, double a, double b); - -#endif //JUSTANOTHERCATGIRL_TASK4_INTEGRAL diff --git a/include/roots.h b/include/roots.h deleted file mode 100644 index 138382b..0000000 --- a/include/roots.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef JUSTANOTHERCATGIRL_TASK4_ROOTS -#define JUSTANOTHERCATGIRL_TASK4_ROOTS - -typedef double(*func_t)(double); - -extern char root_ok; - -char is_root_ok(void); -double sol_binsr(func_t f, double a, double b, double ex, double ey); -double sol_chord(func_t f, double a, double b, double ex, double ey); -double sol_newtn(func_t f, double x0, double ex, double ey); -double sol_itern(func_t f, double x0, double ex, double ey); - - -#endif // JUSTANOTHERCATGIRL_TASK4_ROOTS diff --git a/matrix.c b/matrix.c new file mode 100644 index 0000000..29c4457 --- /dev/null +++ b/matrix.c @@ -0,0 +1,116 @@ +#include "matrix.h" + +// Почему так? Числа более рандомные получаются. А ещё это быстро. +double frand(double min, double max) { + double ret = 0; + unsigned long *ret_mem = (unsigned long*)&ret; + *ret_mem = ( ((unsigned long)rand() << 21) + ^ (unsigned long)rand() + ) & ~(1UL << 63); + int expa, expb; + frexp(min, &expa); + frexp(max, &expb); + int _exp = rand() % (expb-expa + 2) + expa - 1 ; + *ret_mem |= ((unsigned long)abs(_exp) << 52) | + (_exp < 0 ? 0UL << 62 : 1UL << 62); + return fmod(ret, max-min) + min; +} + +struct matrix matrix_new(usz rows, usz columns) { + double ** data = malloc(rows * sizeof (double*)); + for (usz i = 0; i < rows; ++i) + data[i] = malloc(columns * sizeof (double)); + return (struct matrix) { + .data = data, + .rows = rows, + .columns = columns, + }; +} + +void matrix_free(struct matrix m) { + for (usz i = 0; i < m.rows; ++i) + free(m.data[i]); + free(m.data); +} + +void matrix_print(struct matrix *m) { + for (usz i = 0; i < m->rows; ++i) { + printf("| "); + for (usz j = 0; j < m->columns; ++j) { + printf("%10.3g ", m->data[i][j]); + } + printf("|\n"); + } +} + +void matrix_fill(struct matrix *m, double min, double max) { + for (usz i = 0; i < m->rows; ++i) + for (usz j = 0; j < m->columns; ++j) + m->data[i][j] = frand(min, max); +} + +void matrix_apply(struct matrix *m, const struct fmatrix *fm) { + if (m->rows != fm->rows || m->columns != fm->columns) return; + for (usz i = 0; i < fm->rows; ++i) + for (usz j = 0; j < fm->columns; ++j) + m->data[i][j] = (fm->funcs[i][j])(m->data[i][j]); +} + + +struct tumatrix tumatrix_new(usz size) { + double **data = malloc(sizeof (double*) * size); + for (usz i = 0; i < size; ++i) + data[i] = malloc(sizeof (double) * (size - i)); + return (struct tumatrix){.data = data, .size = size}; +} + +void tumatrix_free(struct tumatrix m) { + for (usz i = 0; i < m.size; ++i) + free(m.data[i]); + free(m.data); +} + +double tumatrix_at(const struct tumatrix *m, usz row, usz column) { + if (row > column) return 0.0; + return m->data[row][column - row]; +} + +struct tumatrix tumatrix_mul(const struct tumatrix *a, const struct tumatrix *b) { + if (a->size != b->size) return (struct tumatrix){0}; + struct tumatrix c = tumatrix_new(a->size); + for (usz i = 0; i < a->size; ++i) { + for(usz j = i; j < a->size; ++j) { + double psum = 0; + // maybe r should go from i to j instead, will see + for (usz r = 0; r < a->size; ++r) + psum += tumatrix_at(a, i, r) * tumatrix_at(b, r, j); + c.data[i][j-i] = psum; + } + } + return c; +} + +// Определитель треугольной матрицы равен произведению элементов её главной диагонали +// [https://ru.wikipedia.org/wiki/Треугольная_матрица] +double tumatrix_det(const struct tumatrix *m) { + double prod = 1.0; + for (usz i = 0; i < m->size; ++i) + prod *= tumatrix_at(m, i, i); + return prod; +} + +void tumatrix_fill(struct tumatrix *m, double min, double max) { + for (usz i = 0; i < m->size; ++i) + for (usz j = 0; j < m->size - i; ++j) + m->data[i][j] = frand(min, max); +} + +void tumatrix_print(const struct tumatrix *m) { + for (usz i = 0; i < m->size; ++i) { + printf("| "); + for (usz j = 0; j < m->size; ++j) { + printf("%10.3g ", tumatrix_at(m, i, j)); + } + printf("|\n"); + } +} diff --git a/matrix.h b/matrix.h new file mode 100644 index 0000000..32f7da5 --- /dev/null +++ b/matrix.h @@ -0,0 +1,69 @@ +#ifndef JAC_MATRIX_H +#define JAC_MATRIX_H + +#include <stdio.h> +#include <stddef.h> +#include <stdlib.h> +#include <math.h> + +// Черная магия, чтобы сделать ввод более безопасным +#define SKIP_INPUT do { \ + int c; \ + do { c = getchar(); } \ + while (c != '\n' && c != EOF); \ +} while(0) + + +typedef size_t usz; +typedef ssize_t isz; + +typedef double(*func_t)(double); + +// матрица +struct matrix { + double **data; + usz rows, columns; +}; + +// матрица функций (Function MATRIX) +struct fmatrix { + func_t **funcs; + usz rows, columns; +}; + +// треугольная верхняя матрица. (Triangle Up MATRIX) +struct tumatrix { + double **data; + usz size; +}; + +// генерирует случайное число в диапазоне, используя внутреннее представление типа double в памяти +double frand(double min, double max); + +// создаёт матрицу +struct matrix matrix_new(usz rows, usz columns); +// удаляет матрицу +void matrix_free(struct matrix m); +// выводит матрицу +void matrix_print(struct matrix *m); +// заполняет матрицу случайными числами +void matrix_fill(struct matrix *m, double min, double max); +// поэлементно применяет функцию из fm на m +void matrix_apply(struct matrix *m, const struct fmatrix *fm); + +// создаёт новую треугольную матрицу +struct tumatrix tumatrix_new(usz size); +// удаляет треугольную матрицу +void tumatrix_free(struct tumatrix m); +// берёт i,j-ый элемент треугольной матрицы +double tumatrix_at(const struct tumatrix *m, usz row, usz column); +// умножает треугольные матрицы +struct tumatrix tumatrix_mul(const struct tumatrix *a, const struct tumatrix *b); +// определитель треугольной матрицы +double tumatrix_det(const struct tumatrix *m); +// заполняет треугольную матрицу +void tumatrix_fill(struct tumatrix *m, double min, double max); +// выводит треугольную матрицу на экран +void tumatrix_print(const struct tumatrix *m); + +#endif // JAC_MATRIX_H 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; -} - - - |