aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjustanothercatgirl <sotov2070@gmail.com>2024-10-13 19:28:57 +0300
committerjustanothercatgirl <sotov2070@gmail.com>2024-10-13 19:28:57 +0300
commitf5e0076a8455eec5b4a515b39202217f8a8b9e71 (patch)
treef5cd306d8eb2a516e2d3a83a9276d5aa60b658c0
parent1fe251abc83ee3a38d9faea5be947c90d162c6ae (diff)
Initial committask5
-rw-r--r--5_1.c80
-rw-r--r--5_2.c44
-rw-r--r--5_3.c39
-rw-r--r--Makefile24
-rw-r--r--README.md42
-rw-r--r--compile_flags.txt2
-rw-r--r--hof_example.c33
-rw-r--r--include/integral.h12
-rw-r--r--include/roots.h15
-rw-r--r--matrix.c116
-rw-r--r--matrix.h69
-rw-r--r--src/integral.c36
-rw-r--r--src/main.c186
-rw-r--r--src/roots.c94
14 files changed, 366 insertions, 426 deletions
diff --git a/5_1.c b/5_1.c
new file mode 100644
index 0000000..131d7bb
--- /dev/null
+++ b/5_1.c
@@ -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;
+}
diff --git a/5_2.c b/5_2.c
new file mode 100644
index 0000000..00152e6
--- /dev/null
+++ b/5_2.c
@@ -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;
+}
diff --git a/5_3.c b/5_3.c
new file mode 100644
index 0000000..bc91e08
--- /dev/null
+++ b/5_3.c
@@ -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;
+}
diff --git a/Makefile b/Makefile
index 36c6b05..397b412 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/README.md b/README.md
index 4d78a11..c9b6f08 100644
--- a/README.md
+++ b/README.md
@@ -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;
-}
-
-
-