From e7ccbdde7766927af3a475b88b1d6c91514c1523 Mon Sep 17 00:00:00 2001 From: justanothercatgirl Date: Wed, 25 Sep 2024 16:20:21 +0300 Subject: Added task 3 to task 2 executable --- Makefile | 6 +-- README.md | 15 ++++++ main_2.c | 139 ------------------------------------------------ main_23.c | 178 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 196 insertions(+), 142 deletions(-) create mode 100644 README.md delete mode 100644 main_2.c create mode 100644 main_23.c diff --git a/Makefile b/Makefile index aca0f03..0894ce2 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ -all: t1_a t1_b t2 test.so +all: t1_a t1_b t23 test.so T2FLAGS := -Wall @@ -17,7 +17,7 @@ t1_a: main_1.c t1_b: main_1.c $(CC) -DPROG_MONTE_CARLO $^ -o $@ -t2: main_2.c +t23: main_23.c $(CC) $(T2FLAGS) $^ -o $@ $(T2LINKS) test.so: test_f.c @@ -26,5 +26,5 @@ test.so: test_f.c .PHONY: clean clean: - rm -rf t1_a t1_b t2 test.so + rm -rf t1_a t1_b t23 test.so diff --git a/README.md b/README.md new file mode 100644 index 0000000..b39a043 --- /dev/null +++ b/README.md @@ -0,0 +1,15 @@ +# сборка +1. `make` +2. готово. +# запуск +## задание 1: +`./t1_a` и `./t1_b`. Это старые задания с рядом тейлора синуса и с методом монте-карло. +Аргументы командной строки не требуются +## задание 2: +`./t23 -h` выведет помощь. необходимые флаги: `-o`, `-f`. +Если на компе есть программа gnuplot (в переменной PATH), программа построит в ней график. +Если gnuplot нет на компе, то в Makegfile найдите флаг `-DPIPE_GNUPLOT` и удалите его. +## задание 3: +`./t23 -h` выведет помощь. флаг `-d` (differentiate) активирует 3 задание. необходимые +для 3 задания флаги: `-o`, `-f`, `-x`. +про gnuplot то же самое, что и для 2 задания diff --git a/main_2.c b/main_2.c deleted file mode 100644 index 154afe5..0000000 --- a/main_2.c +++ /dev/null @@ -1,139 +0,0 @@ -#include -#include -#include -#include - -#ifdef PIPE_GNUPLOT - #include - #include -#endif // PIPE_GNUPLOT - -#ifdef DYNAMIC_LOAD - #include - void* handle = NULL; -#endif // DYNAMIC_LOAD - -struct dval { double x, y; }; - -typedef double (*func_t)(double); - -double sin2(double x) { - double y = sin(x); - return y*y; -} - -double cos2(double x) { - double y = cos(x); - return y*y; -} - -double __sincos(double x) { - // sin(x)cos(x) = sin(2x)/2 - return sin(2*x)/2; -} - -/// generates the table as asked in the task. -/// The core function of this file. -struct dval* get_table(func_t f, double start, double end, double step, long *length) { - long tlength = lround((end-start)/step); - struct dval* vals = calloc(tlength, sizeof(struct dval)); - for (long i = 0; i < tlength; ++i) { - double x = start + step * i; - // Not accumulative because if step is too small, - // start will never increment - vals[i] = (struct dval){.x = x, .y = f(x)}; - } - *length = tlength; - return vals; -} - -void print_help(int status) { - const char *help = - "Usage: ./task2 -f func_name -o output_file [-h]\n" - "\t-h: this help\n" - "\t-f: function: either 'sin2', 'cos2' or 'sincos'.\n" - "\t\tif compiled with -DDYNAMIC_LOAD, file name with dynamic function.\n" - "\t-o: output file.\n\n" - "NOTE: the function in dynamic library must be named 'f'.\n" - "NOTE 2: with flag -DPIPE_GNUPLOT output will be piped in gnuplot\n."; - puts(help); - exit(status); -} - -/// Get the function based on the command line flags - either use -/// existing or load one from dynamic library -func_t get_function(const char* name) { - if (!strcmp(name, "cos2")) - return &cos2; - if (!strcmp(name, "sin2")) - return &sin2; - if (!strcmp(name, "sincos")) - return &__sincos; -#ifndef DYNAMIC_LOAD - fputs("ERROR: unknown function. To use dynamic loading, compile with `-DDYNAMIC_LOAD`.\n", stderr); - exit(EXIT_FAILURE); -#else // DYNAMIC_LOAD - handle = dlopen(name, RTLD_NOW); - if (!handle) goto fail; - func_t f = dlsym(handle, "f"); - if (!f) goto fail; - return f; -fail: - fputs(dlerror(), stderr); - exit(EXIT_FAILURE); -#endif // DYNAMIC_LOAD -} - -void print_table(FILE* stream, const struct dval *table, long size) { - for (long i = 0; i < size; ++i) { - fprintf(stream, "%lg %lg\n", table[i].x, table[i].y); - } -} - -int main(int argc, char *argv[]) { - func_t function = NULL; - const char *out = NULL; - // casual argument loop - for (int i = 1; i < argc; ++i) { - if (!strcmp(argv[i], "-h")) - print_help(EXIT_SUCCESS); - else if (!strcmp(argv[i], "-f")) - function = get_function(argv[++i]); - else if (!strcmp(argv[i], "-o")) - out = argv[++i]; - else print_help(EXIT_FAILURE); - } - if (!function || !out) print_help(EXIT_SUCCESS); - - long table_len; - struct dval *table = get_table(function, 0, 3, 0.01, &table_len); - - // print data to stdout and to file - print_table(stdout, table, table_len); - FILE *f = fopen(out, "w+"); - if (f) print_table(f, table, table_len); - else perror(out); - - // This section is creating a 'gnuplot' pipe - // and writing data to it to be plotted -#ifdef PIPE_GNUPLOT - FILE* gp = popen("gnuplot", "w"); - if (!gp) goto cleanup; - fputs("plot '-' with lines\n", gp); - print_table(gp, table, table_len); - fputs("e\n", gp); - fflush(gp); - - getchar(); - pclose(gp); -#endif // PIPE_GNUPLOT - -cleanup: - fclose(f); - free(table); -#ifdef DYNAMIC_LOAD - if (handle) dlclose(handle); -#endif // DYNAMIC_LOAD - exit(EXIT_SUCCESS); -} - diff --git a/main_23.c b/main_23.c new file mode 100644 index 0000000..7675501 --- /dev/null +++ b/main_23.c @@ -0,0 +1,178 @@ +#include +#include +#include +#include + +#ifdef PIPE_GNUPLOT + #include + #include +#endif // PIPE_GNUPLOT + +#ifdef DYNAMIC_LOAD + #include + void* handle = NULL; +#endif // DYNAMIC_LOAD + +struct dval { double x, y; }; + +typedef double (*func_t)(double); + +double sin2(double x) { + double y = sin(x); + return y*y; +} + +double cos2(double x) { + double y = cos(x); + return y*y; +} + +double __sincos(double x) { + // sin(x)cos(x) = sin(2x)/2 + return sin(2*x)/2; +} + +double sin2x(double x) { + return sin(2*x); +} + +/// generates the table as asked in the task. +/// The core function for task 2 +struct dval *get_table(func_t f, double start, double end, double step, long *length) { + long tlength = lround((end-start)/step); + struct dval *vals = calloc(tlength, sizeof(struct dval)); + for (long i = 0; i < tlength; ++i) { + double x = start + step * i; + // Not accumulative because if step is too small, + // start will never increment + vals[i] = (struct dval){.x = x, .y = f(x)}; + } + *length = tlength; + return vals; +} + +/// generates the table for derivative of function f. +/// The core function for task 3 +struct dval *differentiate(func_t f, double start, double end, double step, long *length) { + long tlength = lround((end-start)/step); + struct dval *vals = calloc(tlength, sizeof(struct dval)); + for (long i = 0; i < tlength; ++i) { + double x = start + step * i; + double xi = start + step * (1+i); + double y = (f(xi) - f(x))/step; + vals[i] = (struct dval){.x = x, .y = y}; + } + *length = tlength; + return vals; +} + +void print_help(int status) { + const char *help = + "This program is Licensed under 'the unlicense license'\n\n" + "Usage: ./t23 -f func_name -o output_file [-x number -h -d]\n" + "\t-h: this help\n" + "\t-d: differentiate function (do task 3)\n" + "\t-f: function: either 'sin2', 'cos2', 'sincos', 'tg' or 'sin2x' .\n" + "\t\tif compiled with -DDYNAMIC_LOAD, file name with dynamic function.\n" + "\t-o: output file.\n" + "\t-x: only needed with -d flag - differentiation step (the dx)\n\n" + "NOTE: the function in dynamic library must be named 'f'.\n" + "NOTE 2: with flag -DPIPE_GNUPLOT output will be piped in gnuplot\n"; + puts(help); + exit(status); +} + +/// Get the function based on the command line flags - either use +/// existing or load one from dynamic library +func_t get_function(const char* name) { + if (!strcmp(name, "cos2")) + return &cos2; + if (!strcmp(name, "sin2")) + return &sin2; + if (!strcmp(name, "sincos")) + return &__sincos; + if (!strcmp(name, "tg")) + return &tan; + if (!strcmp(name, "sin2x")) + return &sin2x; +#ifndef DYNAMIC_LOAD + fputs("ERROR: unknown function. To use dynamic loading, compile with `-DDYNAMIC_LOAD`.\n", stderr); + exit(EXIT_FAILURE); +#else // DYNAMIC_LOAD + handle = dlopen(name, RTLD_NOW); + if (!handle) goto fail; + func_t f = dlsym(handle, "f"); + if (!f) goto fail; + return f; +fail: + fputs(dlerror(), stderr); + exit(EXIT_FAILURE); +#endif // DYNAMIC_LOAD +} + +void print_table(FILE* stream, const struct dval *table, long size) { + for (long i = 0; i < size; ++i) { + fprintf(stream, "%lg %lg\n", table[i].x, table[i].y); + } +} + +int main(int argc, char *argv[]) { + func_t function = NULL; + const char *out = NULL; + char task2 = 1; + float dx = 0.0; + // casual argument loop + for (int i = 1; i < argc; ++i) { + if (!strcmp(argv[i], "-h")) + print_help(EXIT_SUCCESS); + else if (!strcmp(argv[i], "-f")) + function = get_function(argv[++i]); + else if (!strcmp(argv[i], "-o")) + out = argv[++i]; + else if (!strcmp(argv[i], "-d")) + task2 = 0; + else if (!strcmp(argv[i], "-x")) + dx = atof(argv[++i]); + else print_help(EXIT_FAILURE); + } + // if function or output file is not set, or if dx is not set for task3, + // then exit with failure + if ((!function || !out) || (!task2 && dx == 0.0)) + print_help(EXIT_FAILURE); + + long table_len; + struct dval *table = NULL; + if (task2) + table = get_table(function, 0, 3, 0.01, &table_len); + else // task 3 + table = differentiate(function, -3, 3, dx, &table_len); + + // print data to stdout and to file + print_table(stdout, table, table_len); + FILE *f = fopen(out, "w+"); + if (f) print_table(f, table, table_len); + else perror(out); + + // This section is creating a 'gnuplot' pipe + // and writing data to it to be plotted +#ifdef PIPE_GNUPLOT + FILE* gp = popen("gnuplot", "w"); + if (!gp) goto cleanup; + fputs("plot '-' with lines\n", gp); + print_table(gp, table, table_len); + fputs("e\n", gp); + fflush(gp); + + getchar(); + pclose(gp); +#endif // PIPE_GNUPLOT + +cleanup: + fclose(f); + free(table); +#ifdef DYNAMIC_LOAD + if (handle) dlclose(handle); +#endif // DYNAMIC_LOAD + exit(EXIT_SUCCESS); +} + -- cgit v1.2.3-70-g09d2