-
-
Notifications
You must be signed in to change notification settings - Fork 7.3k
/
fibonacci_fast.cpp
178 lines (169 loc) · 5.77 KB
/
fibonacci_fast.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
/**
* @file
* @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
* 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 \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)
* @see fibonacci_large.cpp, fibonacci.cpp, string_fibonacci.cpp
*/
#include <cinttypes> /// for uint64_t
#include <cstdio> /// for standard IO
#include <iostream> /// for IO operations
#include <cassert> /// for assert
#include <string> /// for std::to_string
#include <stdexcept> /// for std::invalid_argument
/**
* @brief Maximum Fibonacci number that can be computed
*
* @details
* The result after 93 cannot be stored in a `uint64_t` data type.
*/
constexpr uint64_t MAX = 93;
/**
* @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) {
// 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;
} if (n >= MAX) {
throw std::invalid_argument("Cannot compute for n>=" + std::to_string(MAX) +
" due to limit of 64-bit integers");
return 0;
}
// We do not need temp to be static.
uint64_t temp = f2;
f2 += f1;
f1 = temp;
return f2;
}
/**
* @brief Function to test the Fibonacci computation
* @returns void
*/
static void test() {
// Test for valid Fibonacci numbers
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);
// 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";
}
/**
* @brief Main Function
* @returns 0 on exit
*/
int main() {
test(); // run self-test implementations
return 0;
}