-
-
Notifications
You must be signed in to change notification settings - Fork 7.3k
/
fibonacci_sum.cpp
140 lines (125 loc) · 3.73 KB
/
fibonacci_sum.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
/**
* @file
* @brief An algorithm to calculate the sum of [Fibonacci
* Sequence](https://en.wikipedia.org/wiki/Fibonacci_number): \f$\mathrm{F}(n) +
* \mathrm{F}(n+1) + .. + \mathrm{F}(m)\f$
* @details An algorithm to calculate the sum of Fibonacci Sequence:
* \f$\mathrm{F}(n) + \mathrm{F}(n+1) + .. + \mathrm{F}(m)\f$ where
* \f$\mathrm{F}(i)\f$ denotes the i-th Fibonacci Number . Note that F(0) = 0
* and F(1) = 1. The value of the sum is calculated using matrix exponentiation.
* Reference source:
* https://stackoverflow.com/questions/4357223/finding-the-sum-of-fibonacci-numbers
* @author [Sarthak Sahu](https://github.com/SarthakSahu1009)
*/
#include <cassert> /// for assert
#include <cstdint>
#include <iostream> /// for std::cin and std::cout
#include <vector> /// for std::vector
/**
* @namespace math
* @brief Mathematical algorithms
*/
namespace math {
/**
* @namespace fibonacci_sum
* @brief Functions for the sum of the Fibonacci Sequence: \f$\mathrm{F}(n) +
* \mathrm{F}(n+1) + .. + \mathrm{F}(m)\f$
*/
namespace fibonacci_sum {
using matrix = std::vector<std::vector<uint64_t> >;
/**
* Function to multiply two matrices
* @param T matrix 1
* @param A martix 2
* @returns resultant matrix
*/
math::fibonacci_sum::matrix multiply(const math::fibonacci_sum::matrix &T,
const math::fibonacci_sum::matrix &A) {
math::fibonacci_sum::matrix result(2, std::vector<uint64_t>(2, 0));
// multiplying matrices
result[0][0] = T[0][0] * A[0][0] + T[0][1] * A[1][0];
result[0][1] = T[0][0] * A[0][1] + T[0][1] * A[1][1];
result[1][0] = T[1][0] * A[0][0] + T[1][1] * A[1][0];
result[1][1] = T[1][0] * A[0][1] + T[1][1] * A[1][1];
return result;
}
/**
* Function to compute A^n where A is a matrix.
* @param T matrix
* @param ex power
* @returns resultant matrix
*/
math::fibonacci_sum::matrix power(math::fibonacci_sum::matrix T, uint64_t ex) {
math::fibonacci_sum::matrix A{{1, 1}, {1, 0}};
if (ex == 0 || ex == 1) {
return T;
}
T = power(T, ex / 2);
T = multiply(T, T);
if (ex & 1) {
T = multiply(T, A);
}
return T;
}
/**
* Function to compute sum of fibonacci sequence from 0 to n.
* @param n number
* @returns uint64_t ans, the sum of sequence
*/
uint64_t result(uint64_t n) {
math::fibonacci_sum::matrix T{{1, 1}, {1, 0}};
T = power(T, n);
uint64_t ans = T[0][1];
ans = (ans - 1);
return ans;
}
/**
* Function to compute sum of fibonacci sequence from n to m.
* @param n start of sequence
* @param m end of sequence
* @returns uint64_t the sum of sequence
*/
uint64_t fiboSum(uint64_t n, uint64_t m) {
return (result(m + 2) - result(n + 1));
}
} // namespace fibonacci_sum
} // namespace math
/**
* Function for testing fiboSum function.
* test cases and assert statement.
* @returns `void`
*/
static void test() {
uint64_t n = 0, m = 3;
uint64_t test_1 = math::fibonacci_sum::fiboSum(n, m);
assert(test_1 == 4);
std::cout << "Passed Test 1!" << std::endl;
n = 3;
m = 5;
uint64_t test_2 = math::fibonacci_sum::fiboSum(n, m);
assert(test_2 == 10);
std::cout << "Passed Test 2!" << std::endl;
n = 5;
m = 7;
uint64_t test_3 = math::fibonacci_sum::fiboSum(n, m);
assert(test_3 == 26);
std::cout << "Passed Test 3!" << std::endl;
n = 7;
m = 10;
uint64_t test_4 = math::fibonacci_sum::fiboSum(n, m);
assert(test_4 == 123);
std::cout << "Passed Test 4!" << std::endl;
n = 9;
m = 12;
uint64_t test_5 = math::fibonacci_sum::fiboSum(n, m);
assert(test_5 == 322);
std::cout << "Passed Test 5!" << std::endl;
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test(); // execute the tests
return 0;
}