...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
Fibonacci numbers (Fn) follows the linear recurrence Fn=Fn-1+Fn-2 starting with F0=0, F1=1.
#include <boost/math/special_functions/fibonacci.hpp>
namespace boost { namespace math { template <class T, class Policy> constexpr T fibonacci(unsigned long long n) // Checked version (default policy) template <class T, class Policy> constexpr T fibonacci(unsigned long long n, const Policy &pol) // Checked version (policy for errors etc.) template <typename T> constexpr T unchecked_fibonacci(unsigned long long n) noexcept(std::is_fundamental<T>::value); { // Unchecked version (no policy). }} // namespaces
The functions return Fn for a given input n
having type
T
.
The checked versions checks for the overflow before starting the computation.
If n
is so large that the result can not be represented
in type T
, it then calls overflow_error.
The overflow check is susceptible to off-by-one errors around the overflow
limit. See Binet's Formula below for more details on the check.
These functions are all constexpr
from C++14 onwards, and in addition unchecked_fibonacci
is noexcept
when T is a fundamental
type.
The final Policy argument is optional and can be used to control the behaviour of the function: how it handles errors, what level of precision to use etc. Refer to the policy documentation for more details.
If in the checked version, the overflow check succeeds then the unchecked version is called which computes the desired Fn. Checked version is slower because of the overhead involved in overflow check.
#include <boost/math/special_functions/fibonacci.hpp>
template <typename T> class fibonacci_generator { // returns consecutive fibonacci number starting from 0, 1, 1, 2, ... T operator()(); // reset the generator to start from nth fibonacci number void set(unsigned long long n); }
The generator returns consecutive fibonacci numbers starting with 0, 1, 1, 2...
The state of the generator can be modified using set()
which makes generator return consecutive fibonacci numbers starting from
n
[sup th] fibonacci number.
boost::math::fibonacci_generator<int> gen; int x = gen(); // x is 0 int y = gen(); // y is 1 for(int i = 0; i < 5; ++i) // this loop is same as gen.set(7); gen(); int z = gen(); // z is 13
Generator is non-throwing for all fundamental types and will not check for overflows.
The type must be an arithmetic type supporting +, -, * and can be initialized from trivial integral types.
The file reciprocal_fibonacci_constant.cpp
uses fibonacci_generator
to calculate the reciprocal fibonacci constant to 1000 digit precision like
so:
#include <boost/math/special_functions/fibonacci.hpp> #include <boost/multiprecision/mpfr.hpp> #include <iomanip> #include <iostream> int main() { using Real = boost::multiprecision::mpfr_float_1000; boost::math::fibonacci_generator<Real> gen; gen.set(1); // start producing values from 1st fibonacci number Real ans = 0; const int ITR = 1000; for (int i = 0; i < ITR; ++i) { ans += 1.0 / gen(); } std::cout << std::setprecision(1000) << "Reciprocal fibonacci constant after " << ITR << " iterations is: " << ans << std::endl; }
The time complexity for computing fibonacci number is O(log n), without considering
the time complexities of multiplication and addition (where n
is the input parameter). The implementation is iterative version of Dijkstra's identities
and which simply walks down the bits of n
.
There is a closed form expression for computing fibonacci numbers but since it suffers from imprecision issues (using floating point computation), it is not implemented.
However an approximate formula is used for the overflow checking in the checked version.