Last active
March 27, 2024 23:44
-
-
Save NoahTheBaker/be9dc1162c11fd87780126c396c01444 to your computer and use it in GitHub Desktop.
Francesco146's Fibonacci Prog (Edited)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Calculate Fibonacci Numbers | |
// Public Domain | |
// https://creativecommons.org/publicdomain/zero/1.0/ | |
#include <ctype.h> | |
#include <stdio.h> | |
#include <gmp.h> | |
#include <stdint.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include <stdlib.h> | |
#include <time.h> | |
/* * | |
* Here's some time I got: | |
* fib(1): 0.000009 seconds | |
* fib(10): 0.000009 seconds | |
* fib(100): 0.000009 seconds | |
* fib(1 000): 0.000011 seconds | |
* fib(10 000): 0.000030 seconds | |
* fib(100 000): 0.000193 seconds | |
* fib(1 000 000): 0.004409 seconds | |
* fib(10 000 000): 0.047819 seconds | |
* fib(100 000 000): 0.704643 seconds | |
* fib(1 000 000 000): 8.852119 seconds | |
*/ | |
int main(int argc, char *argv[]) | |
{ | |
_Bool need_result = 0; | |
// Get User Input | |
if (argc < 2 || argc > 3) | |
{ | |
fprintf(stderr, "Usage: %s <number> [--need-result]\n", argv[0]); | |
return EXIT_FAILURE; | |
} | |
if (argc == 3 && strcmp(argv[2], "--need-result") == 0) | |
need_result = 1; | |
long count = strtol(argv[1], NULL, 10); | |
// Setup GMP | |
mpz_t a, b, p, q; | |
mpz_init_set_ui(a, 1); | |
mpz_init_set_ui(b, 0); | |
mpz_init_set_ui(p, 0); | |
mpz_init_set_ui(q, 1); | |
mpz_t tmp; | |
mpz_init(tmp); | |
// Start timing | |
const clock_t start_time = clock(); | |
while (count > 0) | |
{ | |
if (count & 1) | |
{ | |
mpz_mul(tmp, q, q); | |
mpz_mul(q, q, p); | |
mpz_mul_2exp(q, q, 1); | |
mpz_add(q, q, tmp); | |
mpz_mul(p, p, p); | |
mpz_add(p, p, tmp); | |
count >>= 1; | |
} | |
else | |
{ | |
mpz_mul(tmp, a, q); | |
mpz_mul(a, a, p); | |
mpz_addmul(a, b, q); | |
mpz_add(a, a, tmp); | |
mpz_mul(b, b, p); | |
mpz_add(b, b, tmp); | |
count -= 1; | |
} | |
} | |
// End timing | |
const clock_t end_time = clock(); | |
if (end_time == (clock_t){-1}) | |
{ | |
fprintf(stderr, "Error end_time clock()\n"); | |
return EXIT_FAILURE; | |
} | |
// Print time taken | |
const double time_taken = ((double) (end_time - start_time)) / (double) CLOCKS_PER_SEC; | |
char buffer[100]; | |
int len = sprintf(buffer, "fib(%s): %f seconds\n", argv[1], time_taken); | |
if (write(STDOUT_FILENO, buffer, len) == -1) | |
{ | |
fprintf(stderr, "Error write()\n"); | |
return EXIT_FAILURE; | |
} | |
if (fflush(stdout) == EOF) | |
return EXIT_FAILURE; | |
// Check if --need-result option is provided | |
if (need_result) | |
{ | |
// open file to write the result (out.txt) | |
FILE *fp; | |
fp = fopen("out.txt", "w"); | |
if (fp == NULL) | |
{ | |
fprintf(stderr, "Error opening file\n"); | |
return EXIT_FAILURE; | |
} | |
mpz_out_str(fp, 10, b); | |
} | |
//NTB | |
mpz_out_str(stdout, 10, b); | |
//NTB | |
// Cleanup | |
mpz_clear(a); | |
mpz_clear(b); | |
mpz_clear(p); | |
mpz_clear(q); | |
mpz_clear(tmp); | |
return EXIT_SUCCESS; | |
} |
@NoahTheBaker I had a lot of fun! I ended up translating this algorithm to fortran (mostly to learn more about the language) and that program ended up being slower, but I did learn a lot more about the gnu compiler collection as well as managing libraries from doing this. :3
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@g1rly-c0d3r Looks great! Much faster output now.

Only difference is yours shows n-1 instead of n shown characters (the character right after the . . . . . ) but that was a problem with an earlier version of mine as well :). awesome work cleaning stuff up!