diff options
author | justanothercatgirl <sotov2070@gmail.com> | 2024-09-25 14:44:31 +0300 |
---|---|---|
committer | justanothercatgirl <sotov2070@gmail.com> | 2024-09-25 14:44:31 +0300 |
commit | c6ad098a80adc3250d3f08d0c2b884135d98b0a7 (patch) | |
tree | 895f3af92322973703b43cbb236c5a10eb48e827 | |
parent | 49b2b840c668c64089936e681192c75a8de2c81c (diff) |
initial commit
-rw-r--r-- | Makefile | 32 | ||||
-rw-r--r-- | main.c | 23 | ||||
-rw-r--r-- | main_1.c | 89 | ||||
-rw-r--r-- | main_2.c | 134 | ||||
-rw-r--r-- | test_f.c | 5 |
5 files changed, 258 insertions, 25 deletions
@@ -1,2 +1,30 @@ -sin: main.c - cc -o sin main.c + +all: t1_a t1_b t2 test.so + +T2FLAGS := -Wall + +ifneq ($(OS),Windows_NT) + T2FLAGS += -DDYNAMIC_LOAD + T2LINKS = -lm -ldl + ifneq (, $(shell which gnuplot)) + T2FLAGS += -DPIPE_GNUPLOT + endif +endif + +t1_a: main_1.c + $(CC) -DPROG_SINUS_SUM $^ -o $@ + +t1_b: main_1.c + $(CC) -DPROG_MONTE_CARLO $^ -o $@ + +t2: main_2.c + $(CC) $(T2FLAGS) $^ -o $@ $(T2LINKS) + +test.so: test_f.c + $(CC) -fPIC -fPIE -shared $^ -o $@ + +.PHONY: clean + +clean: + rm -rf t1_a t1_b t2 test.so + @@ -1,23 +0,0 @@ -#include <stdio.h> - -#define EPSILON 0.001*0.001 -#define MAX_ITERATIONS 100 - -int main(void) { - double x; - double result; - double last_elem; - int i; - - printf("Input a number\n"); - scanf("%lf", &x); - last_elem = result = x; - - for (i = 1; i < MAX_ITERATIONS; ++i) { - last_elem = last_elem * x * x / (2*i * (2*i+1)); - if (last_elem*last_elem <= EPSILON) break; - result += last_elem * ( (i%2 * -2) + 1 ); - } - printf("result = %lf; iterations = %i; last_elem = %lf\n", result, i, last_elem); - return 0; -} diff --git a/main_1.c b/main_1.c new file mode 100644 index 0000000..cd84b67 --- /dev/null +++ b/main_1.c @@ -0,0 +1,89 @@ +#include <stdio.h> + +#if defined(PROG_SINUS_SUM) + +#define EPSILON 0.001*0.001 +#define MAX_ITERATIONS 100 + +int main(void) { + puts("defined macro PROG_SINUS_SUM"); + double x; + double result; + double last_elem; + int i; + + printf("Input a number\n"); + scanf("%lf", &x); + last_elem = result = x; + + for (i = 1; i < MAX_ITERATIONS; ++i) { + last_elem = last_elem * x * x / (2*i * (2*i+1)); + if (last_elem*last_elem <= EPSILON) break; + result += last_elem * ( (i%2 * -2) + 1 ); + } + printf("result = %lf; iterations = %i; last_elem = %lf\n", result, i, last_elem); + return 0; +} + +#elif defined(PROG_MONTE_CARLO) + +#include <stdlib.h> +#include <time.h> + +#define _USE_MATH_DEFINES +#include <math.h> + +struct point { + float x, y; +}; + +struct circle { + // center not needed for this task + /*struct point center;*/ + float rad; +}; + +char in_circle(const struct circle *c, const struct point p) { + /*p.x -= c->x;*/ + /*p.y -= c->y;*/ + return p.x * p.x + p.y * p.y < c->rad*c->rad; +} + +float calculate_pi(int iterations) { + int in = 0, out = 0; + int *arr[2] = {&out, &in}; + const struct circle c = {.rad = 1.0f}; + for (int i = 0; i < iterations; ++i) { + struct point p = { + .x = rand() % 2000000u / 1e6f - 1, + .y = rand() % 2000000u / 1e6f - 1 + }; + ++*arr[in_circle(&c, p)]; + } + return (float)in/iterations * 4; +} + +int main(int argc, char *argv[]) { + puts("defined macro PROG_MONTE_CARLO"); + srand(time(NULL)); + int iters; + if (argc == 2) { + iters = atoi(argv[1]); + } else { + fputs("Iterations: ", stdout); + if (!scanf("%i", &iters)) { + fputs("Input a valid number\n", stderr); + return EXIT_FAILURE; + } + } + float pi = calculate_pi(iters); + float err = fabs(M_PI-pi)/M_PI; + printf( "calculated pi: %.4f, actual pi: %.4f\n" + "error: %.2f%%\n", + pi, M_PI, err * 100); + return EXIT_SUCCESS; +} + +#else + #error "define macro PROG_SINUS_SUM or PROG_MONTE_CARLO in compilation flags" +#endif diff --git a/main_2.c b/main_2.c new file mode 100644 index 0000000..8f6fb71 --- /dev/null +++ b/main_2.c @@ -0,0 +1,134 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> + +#ifdef PIPE_GNUPLOT + #include <unistd.h> + #include <fcntl.h> +#endif // PIPE_GNUPLOT + +#ifdef DYNAMIC_LOAD + #include <dlfcn.h> +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; +} + +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); +} + +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; + 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_table(stdout, table, table_len); + FILE *f = fopen(out, "w+"); + if (f) { + print_table(f, table, table_len); + fflush(f); + } + else perror(out); + +#ifdef PIPE_GNUPLOT + FILE* gp = popen("gnuplot", "w"); + if (!gp) goto exit; + fputs("plot '-' with lines\n", gp); + print_table(gp, table, table_len); + fputs("e\n", gp); + fflush(gp); + + getchar(); + pclose(gp); +#endif // PIPE_GNUPLOT + +exit: + fclose(f); + free(table); +#ifdef DYNAMIC_LOAD + if (handle) dlclose(handle); +#endif // DYNAMIC_LOAD + exit(EXIT_SUCCESS); +} + diff --git a/test_f.c b/test_f.c new file mode 100644 index 0000000..8811f1e --- /dev/null +++ b/test_f.c @@ -0,0 +1,5 @@ +double f(double x) { + static int counter = 0; + ++counter; + return counter * x; +} |