diff options
| -rw-r--r-- | .gitignore | 2 | ||||
| -rw-r--r-- | CMakeLists.txt | 17 | ||||
| -rwxr-xr-x | build.sh | 3 | ||||
| -rw-r--r-- | src/config.c | 0 | ||||
| -rw-r--r-- | src/config.h | 4 | ||||
| -rw-r--r-- | src/main.c | 189 | ||||
| -rwxr-xr-x | tpi | bin | 0 -> 16272 bytes |
7 files changed, 215 insertions, 0 deletions
@@ -53,3 +53,5 @@ dkms.conf # debug information files *.dwo +releases/ + diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..a2d0046 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,17 @@ +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3 -Wall -Wextra -Werror -v") + +project(termpi) + +set(CMAKE_C_STANDART 99) +set(CC clang) + +find_package(PkgConfig REQUIRED) +pkg_check_modules(MPFR REQUIRED mpfr) + +set(SOURCES + main.c + config.c +) + +add_executable(${PROJECT_NAME} ${MPFR_LIBRARIES}) + diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..093eefd --- /dev/null +++ b/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +gcc -v -Wall -Wextra -Werror -lm -lmpfr -lgmp -I/usr/local/include -L/usr/local/lib src/main.c -o tpi-v2 diff --git a/src/config.c b/src/config.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/config.c diff --git a/src/config.h b/src/config.h new file mode 100644 index 0000000..cafea73 --- /dev/null +++ b/src/config.h @@ -0,0 +1,4 @@ +#include <stdio.h> + +void parse_config(char path[]); + diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..c089223 --- /dev/null +++ b/src/main.c @@ -0,0 +1,189 @@ +#include <stdio.h> +#include <stdlib.h> +#include <mpfr.h> +#include <math.h> +#include <stdbool.h> +#include <unistd.h> +#include <time.h> + +// -lmpfr -lgmp -lm -Wall -Wextra -Werror + +// Gauss-Legendre method +int calculate_pi(int len, bool infinite_mode, int delay_ms) { + mp_bitcnt_t precision = (mp_bitcnt_t)(len * 3.321928094 + 100); // Увеличил запас точности + + mpfr_t a, b, t, p, a_next, t_tmp, p_tmp, pi; + mpfr_inits2(precision, a, b, t, p, a_next, t_tmp, p_tmp, pi, (mpfr_ptr)0); + + + mpfr_set_d(a, 1.0, MPFR_RNDN); + mpfr_sqrt_ui(b, 2, MPFR_RNDN); // b = sqrt(2) + mpfr_ui_div(b, 1, b, MPFR_RNDN); // b = 1/sqrt(2) + mpfr_set_d(t, 0.25, MPFR_RNDN); + mpfr_set_d(p, 1.0, MPFR_RNDN); + + int iterations = (int)(log2(len)) + 3; + + for (int i = 0; i < iterations; i++) { + // a_next = (a + b)/2 + mpfr_add(a_next, a, b, MPFR_RNDN); + mpfr_div_2ui(a_next, a_next, 1, MPFR_RNDN); + + // b = sqrt(a * b) + mpfr_mul(b, a, b, MPFR_RNDN); + mpfr_sqrt(b, b, MPFR_RNDN); + + // t_tmp = t - p * (a - a_next)^2 + mpfr_sub(t_tmp, a, a_next, MPFR_RNDN); + mpfr_sqr(t_tmp, t_tmp, MPFR_RNDN); + mpfr_mul(t_tmp, p, t_tmp, MPFR_RNDN); + mpfr_sub(t, t, t_tmp, MPFR_RNDN); + + // p = 2 * p + mpfr_mul_2ui(p, p, 1, MPFR_RNDN); + + // a = a_next + mpfr_set(a, a_next, MPFR_RNDN); + } + + // π = (a + b)^2 / (4 * t) + mpfr_add(pi, a, b, MPFR_RNDN); + mpfr_sqr(pi, pi, MPFR_RNDN); + mpfr_mul_ui(t, t, 4, MPFR_RNDN); + mpfr_div(pi, pi, t, MPFR_RNDN); + + if (!infinite_mode) { + + printf("π = "); + mpfr_out_str(stdout, 10, len, pi, MPFR_RNDN); + printf("\n"); + } else { + + mpfr_exp_t exp; + char *pi_str; + + pi_str = mpfr_get_str(NULL, &exp, 10, 0, pi, MPFR_RNDN); + + if (pi_str == NULL) { + fprintf(stderr, "Error occurred while translating pi to char\n"); + mpfr_clears(a, b, t, p, a_next, t_tmp, p_tmp, pi, (mpfr_ptr)0); + return 1; + } + + + if (exp == 1) { + + printf("π = %c", pi_str[0]); + fflush(stdout); + if (delay_ms > 0) { + struct timespec ts; + ts.tv_sec = delay_ms / 1000; + ts.tv_nsec = (delay_ms % 1000) * 1000000L; + nanosleep(&ts, NULL); + } + + printf("."); + fflush(stdout); + if (delay_ms > 0) { + struct timespec ts; + ts.tv_sec = delay_ms / 1000; + ts.tv_nsec = (delay_ms % 1000) * 1000000L; + nanosleep(&ts, NULL); + } + + + for (int i = 1; pi_str[i] != '\0'; i++) { + printf("%c", pi_str[i]); + fflush(stdout); + if (delay_ms > 0) { + struct timespec ts; + ts.tv_sec = delay_ms / 1000; + ts.tv_nsec = (delay_ms % 1000) * 1000000L; + nanosleep(&ts, NULL); + } + } + printf("\n"); + } else { + + printf("π = 0.%se%ld\n", pi_str, (long)exp); + } + + mpfr_free_str(pi_str); + } + + mpfr_clears(a, b, t, p, a_next, t_tmp, p_tmp, pi, (mpfr_ptr)0); + return 0; +} + +int main(int argc, char *argv[]) { + int delay_ms = 500; + int count = 0; + bool infinite_mode = false; + bool help = false; + int opt; + + + while ((opt = getopt(argc, argv, "ihc:t:")) != -1) { + switch (opt) { + case 'i': + infinite_mode = true; + break; + case 'h': + help = true; + break; + case 'c': + count = atoi(optarg); + if(count <= 0) { + fprintf(stderr, "Invalid value for -c. Must be a positive integer.\n"); + return 1; + } + break; + case 't': + delay_ms = atoi(optarg); + if(delay_ms < 0) { + fprintf(stderr, "Invalid value for -t. Must be a non-negative integer.\n"); + return 1; + } + break; + case '?': + + if (optopt == 'c' || optopt == 't') { + fprintf(stderr, "Option -%c requires an argument.\n", optopt); + } else { + fprintf(stderr, "Unknown option: -%c\n", optopt); + } + return 1; + default: + abort(); + } + } + + if (help) { + printf("tpi - C-written, MPFR-based CLI program for calculating π\n"); + printf("ARGS:\n"); + printf(" -h - Showing this message.\n"); + printf(" -i - Infinitely outputs the digits of pi one at a time.\n"); + printf(" -c=int - Outputs the number of digits of pi passed to the argument.\n"); + printf(" -t=int - Setting the output speed in -i mode (milliseconds). The default value is 500.\n"); + return 0; + } + + + if (infinite_mode) { + + int internal_precision = 1000000; + if(count > 0 && count < internal_precision) { + internal_precision = count; + } + + calculate_pi(internal_precision, true, delay_ms); + } else if (count > 0) { + + calculate_pi(count, false, 0); + } else { + + calculate_pi(500, false, 0); + } + + return 0; +} Binary files differ |
