From 93064ae1b8abb66d4e34be4b4bd050530781eb7b Mon Sep 17 00:00:00 2001 From: Shi Entong <144505619+setbit123@users.noreply.github.com> Date: Thu, 31 Oct 2024 21:24:07 +0800 Subject: [PATCH 1/8] Update fibonacci_fast.cpp Modify the fibonacci_fast.cpp to fit the project style requirements. --- math/fibonacci_fast.cpp | 152 ++++++++++++++++++++++++++++++++++------ 1 file changed, 129 insertions(+), 23 deletions(-) diff --git a/math/fibonacci_fast.cpp b/math/fibonacci_fast.cpp index 0948276a08a..2ad36298395 100644 --- a/math/fibonacci_fast.cpp +++ b/math/fibonacci_fast.cpp @@ -1,36 +1,41 @@ /** * @file - * @brief Faster computation of Fibonacci series + * @brief Faster computation of Fibonacci series. * + * @details * An efficient way to calculate nth fibonacci number faster and simpler than - * \f$O(n\log n)\f$ method of matrix exponentiation This works by using both - * recursion and dynamic programming. as 93rd fibonacci exceeds 19 digits, which + * \f$O(n\log n)\f$ method of matrix exponentiation. This works by using both + * recursion and dynamic programming. As 93rd fibonacci exceeds 19 digits, which * cannot be stored in a single long long variable, we can only use it till 92nd * fibonacci we can use it for 10000th fibonacci etc, if we implement * bigintegers. This algorithm works with the fact that nth fibonacci can easily - * found if we have already found n/2th or (n+1)/2th fibonacci It is a property + * found if we have already found \f$n/2\f$th or \f$(n+1)/2\f$th fibonacci. It is a property * of fibonacci similar to matrix exponentiation. * - * \author [Krishna Vedala](https://github.com/kvedala) + * @author [Krishna Vedala](https://github.com/kvedala) * @see fibonacci_large.cpp, fibonacci.cpp, string_fibonacci.cpp */ - -#include -#include -#include +#include /// for uint64_t +#include /// for standard IO +#include /// for IO operations /** - * maximum number that can be computed - The result after 93 cannot be stored - * in a `uint64_t` data type. + * @brief Maximum Fibonacci number that can be computed + * + * @details + * The result after 93 cannot be stored in a `uint64_t` data type. */ - #define MAX 93 -/** Algorithm */ +/** + * @brief Function to compute the nth Fibonacci number + * @param n The index of the Fibonacci number to compute + * @return uint64_t The nth Fibonacci number + */ uint64_t fib(uint64_t n) { - static uint64_t f1 = 1, - f2 = 1; // using static keyword will retain the values of - // f1 and f2 for the next function call. + // Using static keyword will retain the values of + // f1 and f2 for the next function call. + static uint64_t f1 = 1, f2 = 1; if (n <= 2) return f2; @@ -39,19 +44,120 @@ uint64_t fib(uint64_t n) { << "Cannot compute for n>93 due to limit of 64-bit integers\n"; return 0; } - - uint64_t temp = f2; // we do not need temp to be static + + // We do not need temp to be static. + uint64_t temp = f2; f2 += f1; f1 = temp; return f2; } -/** Main function */ +/** + * @brief Function to test the Fibonacci computation + * @returns void + */ +static void test() { + assert(fib(1) == 1); + assert(fib(2) == 1); + assert(fib(3) == 2); + assert(fib(4) == 3); + assert(fib(5) == 5); + assert(fib(6) == 8); + assert(fib(7) == 13); + assert(fib(8) == 21); + assert(fib(9) == 34); + assert(fib(10) == 55); + assert(fib(11) == 89); + assert(fib(12) == 144); + assert(fib(13) == 233); + assert(fib(14) == 377); + assert(fib(15) == 610); + assert(fib(16) == 987); + assert(fib(17) == 1597); + assert(fib(18) == 2584); + assert(fib(19) == 4181); + assert(fib(20) == 6765); + assert(fib(21) == 10946); + assert(fib(22) == 17711); + assert(fib(23) == 28657); + assert(fib(24) == 46368); + assert(fib(25) == 75025); + assert(fib(26) == 121393); + assert(fib(27) == 196418); + assert(fib(28) == 317811); + assert(fib(29) == 514229); + assert(fib(30) == 832040); + assert(fib(31) == 1346269); + assert(fib(32) == 2178309); + assert(fib(33) == 3524578); + assert(fib(34) == 5702887); + assert(fib(35) == 9227465); + assert(fib(36) == 14930352); + assert(fib(37) == 24157817); + assert(fib(38) == 39088169); + assert(fib(39) == 63245986); + assert(fib(40) == 102334155); + assert(fib(41) == 165580141); + assert(fib(42) == 267914296); + assert(fib(43) == 433494437); + assert(fib(44) == 701408733); + assert(fib(45) == 1134903170); + assert(fib(46) == 1836311903); + assert(fib(47) == 2971215073); + assert(fib(48) == 4807526976); + assert(fib(49) == 7778742049); + assert(fib(50) == 12586269025); + assert(fib(51) == 20365011074); + assert(fib(52) == 32951280099); + assert(fib(53) == 53316291173); + assert(fib(54) == 86267571272); + assert(fib(55) == 139583862445); + assert(fib(56) == 225851433717); + assert(fib(57) == 365435296162); + assert(fib(58) == 591286729879); + assert(fib(59) == 956722026041); + assert(fib(60) == 1548008755920); + assert(fib(61) == 2504730781961); + assert(fib(62) == 4052739537881); + assert(fib(63) == 6557470319842); + assert(fib(64) == 10610209857723); + assert(fib(65) == 17167680177565); + assert(fib(66) == 27777890035288); + assert(fib(67) == 44945570212853); + assert(fib(68) == 72723460248141); + assert(fib(69) == 117669030460994); + assert(fib(70) == 190392490709135); + assert(fib(71) == 308061521170129); + assert(fib(72) == 498454011879264); + assert(fib(73) == 806515533049393); + assert(fib(74) == 1304969544928657); + assert(fib(75) == 2111485077978050); + assert(fib(76) == 3416454622906707); + assert(fib(77) == 5527939700884757); + assert(fib(78) == 8944394323791464); + assert(fib(79) == 14472334024676221); + assert(fib(80) == 23416728348467685); + assert(fib(81) == 37889062373143906); + assert(fib(82) == 61305790721611591); + assert(fib(83) == 99194853094755497); + assert(fib(84) == 160500643816367088); + assert(fib(85) == 259695496911122585); + assert(fib(86) == 420196140727489673); + assert(fib(87) == 679891637638612258); + assert(fib(88) == 1100087778366101931); + assert(fib(89) == 1779979416004714189); + assert(fib(90) == 2880067194370816120); + assert(fib(91) == 4660046610375530309); + assert(fib(92) == 7540113804746346429); + std::cout << "All Fibonacci tests have successfully passed!\n"; +} + +/** + * @brief Main Function + * @returns 0 on exit + */ int main() { - // Main Function - for (uint64_t i = 1; i < 93; i++) { - std::cout << i << " th fibonacci number is " << fib(i) << std::endl; - } + test(); // run self-test implementations return 0; } From c85115fda7833eab9ceb297ad0d4d0eb98cb2e89 Mon Sep 17 00:00:00 2001 From: Shi Entong <144505619+setbit123@users.noreply.github.com> Date: Wed, 20 Nov 2024 21:37:41 +0800 Subject: [PATCH 2/8] Update fibonacci_fast.cpp to meet the revision suggestions. --- math/fibonacci_fast.cpp | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/math/fibonacci_fast.cpp b/math/fibonacci_fast.cpp index 2ad36298395..5111fffb694 100644 --- a/math/fibonacci_fast.cpp +++ b/math/fibonacci_fast.cpp @@ -18,6 +18,7 @@ #include /// for uint64_t #include /// for standard IO #include /// for IO operations +#include /// for assert /** * @brief Maximum Fibonacci number that can be computed @@ -25,7 +26,7 @@ * @details * The result after 93 cannot be stored in a `uint64_t` data type. */ -#define MAX 93 +constexpr uint64_t MAX = 93; /** * @brief Function to compute the nth Fibonacci number @@ -39,9 +40,9 @@ uint64_t fib(uint64_t n) { if (n <= 2) return f2; - if (n >= 93) { - std::cerr - << "Cannot compute for n>93 due to limit of 64-bit integers\n"; + if (n >= MAX) { + throw std::invalid_argument("Cannot compute for n>=" + std::to_string(MAX) + + " due to limit of 64-bit integers"); return 0; } @@ -58,6 +59,7 @@ uint64_t fib(uint64_t n) { * @returns void */ static void test() { + // Test for valid Fibonacci numbers assert(fib(1) == 1); assert(fib(2) == 1); assert(fib(3) == 2); @@ -150,6 +152,17 @@ static void test() { assert(fib(90) == 2880067194370816120); assert(fib(91) == 4660046610375530309); assert(fib(92) == 7540113804746346429); + + // Test for invalid Fibonacci numbers + try { + fib(MAX + 1); + assert(false && "Expected an invalid_argument exception to be thrown"); + } catch (const std::invalid_argument& e) { + const std::string expected_message = "Cannot compute for n>=" + std::to_string(MAX) + + " due to limit of 64-bit integers"; + assert(e.what() == expected_message); + } + std::cout << "All Fibonacci tests have successfully passed!\n"; } From cff62a1269766a5beb633a95707a4cf4aa48a9e6 Mon Sep 17 00:00:00 2001 From: Shi Entong <144505619+setbit123@users.noreply.github.com> Date: Sat, 23 Nov 2024 13:30:53 +0800 Subject: [PATCH 3/8] Update fibonacci_fast.cpp to try to pass some CI test --- math/fibonacci_fast.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/math/fibonacci_fast.cpp b/math/fibonacci_fast.cpp index 5111fffb694..e747145158f 100644 --- a/math/fibonacci_fast.cpp +++ b/math/fibonacci_fast.cpp @@ -19,6 +19,7 @@ #include /// for standard IO #include /// for IO operations #include /// for assert +#include /// for function about string /** * @brief Maximum Fibonacci number that can be computed From bf9ab628c80a00ab2b2b987927b2ad2a7ddb6004 Mon Sep 17 00:00:00 2001 From: Shi Entong <144505619+setbit123@users.noreply.github.com> Date: Sat, 23 Nov 2024 13:43:01 +0800 Subject: [PATCH 4/8] Update fibonacci_fast.cpp --- math/fibonacci_fast.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/math/fibonacci_fast.cpp b/math/fibonacci_fast.cpp index e747145158f..13fb8cb24ec 100644 --- a/math/fibonacci_fast.cpp +++ b/math/fibonacci_fast.cpp @@ -19,7 +19,8 @@ #include /// for standard IO #include /// for IO operations #include /// for assert -#include /// for function about string +#include /// for std::to_string +#include /// for std::invalid_argument /** * @brief Maximum Fibonacci number that can be computed From 0ac15089d725285001d42871b452f8b80b970e17 Mon Sep 17 00:00:00 2001 From: Shi Entong <144505619+setbit123@users.noreply.github.com> Date: Sun, 24 Nov 2024 16:40:31 +0800 Subject: [PATCH 5/8] Update fibonacci_fast.cpp to meet the coding style requirements --- math/fibonacci_fast.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/math/fibonacci_fast.cpp b/math/fibonacci_fast.cpp index 13fb8cb24ec..df03725aa13 100644 --- a/math/fibonacci_fast.cpp +++ b/math/fibonacci_fast.cpp @@ -40,9 +40,9 @@ uint64_t fib(uint64_t n) { // f1 and f2 for the next function call. static uint64_t f1 = 1, f2 = 1; - if (n <= 2) + if (n <= 2) { return f2; - if (n >= MAX) { + } if (n >= MAX) { throw std::invalid_argument("Cannot compute for n>=" + std::to_string(MAX) + " due to limit of 64-bit integers"); return 0; From 44b82daf6966df561fa6ce5e12e7f99006d46f03 Mon Sep 17 00:00:00 2001 From: Shi Entong <144505619+setbit123@users.noreply.github.com> Date: Sun, 24 Nov 2024 22:23:39 +0800 Subject: [PATCH 6/8] Update fibonacci_fast.cpp --- math/fibonacci_fast.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/math/fibonacci_fast.cpp b/math/fibonacci_fast.cpp index df03725aa13..6e5cdd77795 100644 --- a/math/fibonacci_fast.cpp +++ b/math/fibonacci_fast.cpp @@ -30,6 +30,7 @@ */ constexpr uint64_t MAX = 93; + /** * @brief Function to compute the nth Fibonacci number * @param n The index of the Fibonacci number to compute From 1755fb21dc45a88d7b325427a8986a0036dd8e24 Mon Sep 17 00:00:00 2001 From: Shi Entong <144505619+setbit123@users.noreply.github.com> Date: Sun, 24 Nov 2024 22:23:49 +0800 Subject: [PATCH 7/8] Update fibonacci_fast.cpp --- math/fibonacci_fast.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/math/fibonacci_fast.cpp b/math/fibonacci_fast.cpp index 6e5cdd77795..df03725aa13 100644 --- a/math/fibonacci_fast.cpp +++ b/math/fibonacci_fast.cpp @@ -30,7 +30,6 @@ */ constexpr uint64_t MAX = 93; - /** * @brief Function to compute the nth Fibonacci number * @param n The index of the Fibonacci number to compute From b9f019ee97954a5361db342bbc41389a14ddc798 Mon Sep 17 00:00:00 2001 From: Shi Entong <144505619+setbit123@users.noreply.github.com> Date: Wed, 4 Dec 2024 19:56:02 +0800 Subject: [PATCH 8/8] Fit fibonacci_fast.cpp to contributing guidelines --- math/fibonacci_large.cpp | 111 +++++++++++++++++++++------------------ 1 file changed, 59 insertions(+), 52 deletions(-) diff --git a/math/fibonacci_large.cpp b/math/fibonacci_large.cpp index e4f4e5eaf1b..42ca5a829ce 100644 --- a/math/fibonacci_large.cpp +++ b/math/fibonacci_large.cpp @@ -4,22 +4,27 @@ * input argument. Uses custom build arbitrary integers library * to perform additions and other operations. * + * @details * Took 0.608246 seconds to compute 50,000^th Fibonacci * number that contains 10450 digits! * - * \author [Krishna Vedala](https://github.com/kvedala) + * @author [Krishna Vedala](https://github.com/kvedala) * @see fibonacci.cpp, fibonacci_fast.cpp, string_fibonacci.cpp */ -#include -#include -#include +#include /// for uint64_t +#include /// for clock_t, std::clock, CLOCKS_PER_SEC +#include /// for IO operations +#include /// for std::invalid_argument +#include /// for assert -#include "./large_number.h" +#include "./large_number.h" /// for large_number class and related functions -/** Compute fibonacci numbers using the relation - * \f[f(n)=f(n-1)+f(n-2)\f] - * and returns the result as a large_number type. +/** + * @brief Function to compute the n-th Fibonacci number. + * @details \f[f(n)=f(n-1)+f(n-2)\f] + * @param n The position in the Fibonacci sequence. + * @return The n-th Fibonacci number. */ large_number fib(uint64_t n) { large_number f0(1); @@ -35,51 +40,53 @@ large_number fib(uint64_t n) { return f1; } -int main(int argc, char *argv[]) { - uint64_t N; - if (argc == 2) { - N = strtoull(argv[1], NULL, 10); - } else { - std::cout << "Enter N: "; - std::cin >> N; - } - - clock_t start_time = std::clock(); - large_number result = fib(N); - clock_t end_time = std::clock(); - double time_taken = static_cast(end_time - start_time) / - static_cast(CLOCKS_PER_SEC); - - std::cout << std::endl - << N << "^th Fibonacci number: " << result << std::endl - << "Number of digits: " << result.num_digits() << std::endl - << "Time taken: " << std::scientific << time_taken << " s" - << std::endl; +/** + * @brief Test function to validate the fib function. + * @details This function tests the fib function by comparing its result for a + * specific input (5000) with a precomputed expected result. + */ +void test() { + uint64_t N = 5000; + large_number expected_result( + "387896845438832563370191630832590531208212771464624510616059721489" + "555013904403709701082291646221066947929345285888297381348310200895" + "498294036143015691147893836421656394410691021450563413370655865623" + "825465670071252592990385493381392883637834751890876297071203333705" + "292310769300851809384980180384781399674888176555465378829164426891" + "298038461377896902150229308247566634622492307188332480328037503913" + "035290330450584270114763524227021093463769910400671417488329842289" + "149127310405432875329804427367682297724498774987455569190770388063" + "704683279481135897373999311010621930814901857081539785437919530561" + "751076105307568878376603366735544525884488624161921055345749367589" + "784902798823435102359984466393485325641195222185956306047536464547" + "076033090242080638258492915645287629157575914234380914230291749108" + "898415520985443248659407979357131684169286803954530954538869811466" + "508206686289742063932343848846524098874239587380197699382031717420" + "893226546887936400263079778005875912967138963421425257911687275560" + "0360311370547754724604639987588046985178408674382863125"); - N = 5000; - if (fib(N) == - large_number( - "387896845438832563370191630832590531208212771464624510616059721489" - "555013904403709701082291646221066947929345285888297381348310200895" - "498294036143015691147893836421656394410691021450563413370655865623" - "825465670071252592990385493381392883637834751890876297071203333705" - "292310769300851809384980180384781399674888176555465378829164426891" - "298038461377896902150229308247566634622492307188332480328037503913" - "035290330450584270114763524227021093463769910400671417488329842289" - "149127310405432875329804427367682297724498774987455569190770388063" - "704683279481135897373999311010621930814901857081539785437919530561" - "751076105307568878376603366735544525884488624161921055345749367589" - "784902798823435102359984466393485325641195222185956306047536464547" - "076033090242080638258492915645287629157575914234380914230291749108" - "898415520985443248659407979357131684169286803954530954538869811466" - "508206686289742063932343848846524098874239587380197699382031717420" - "893226546887936400263079778005875912967138963421425257911687275560" - "0360311370547754724604639987588046985178408674382863125")) - std::cout << "Test for " << N << "^th Fibonacci number passed!" - << std::endl; - else - std::cerr << "Test for " << N << "^th Fibonacci number failed!" - << std::endl; + try { + large_number result = fib(N); + if (result == expected_result) { + std::cout << "Test for " << N << "^th Fibonacci number passed!" + << std::endl; + } else { + throw std::invalid_argument("Test for " + std::to_string(N) + + "^th Fibonacci number failed"); + } + } catch (const std::invalid_argument& e) { + assert(e.what() == std::string("Test for " + std::to_string(N) + + "^th Fibonacci number failed")); + } +} +/** + * @brief Main function. + * @details This function is the entry point of the program. It calls the test + * function to validate the correctness of the fib function. + * @return 0 on successful program exit. + */ +int main() { + test(); return 0; }