aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile32
-rw-r--r--main.c23
-rw-r--r--main_1.c89
-rw-r--r--main_2.c134
-rw-r--r--test_f.c5
5 files changed, 258 insertions, 25 deletions
diff --git a/Makefile b/Makefile
index 79b383d..aca0f03 100644
--- a/Makefile
+++ b/Makefile
@@ -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
+
diff --git a/main.c b/main.c
deleted file mode 100644
index 74277f0..0000000
--- a/main.c
+++ /dev/null
@@ -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;
+}