The whole idea of computing fibonaci number using 'linear' equation
is not nice;-) This is only an exercise.
> To be useful, the map should probably store only values for selected
> points, like each fib(2^n), fib(2^n+1). Again, depends on the usage
> pattern.
http://mathworld.wolfram.com/FibonacciNumber.html
equations 26 and 60.
But if you use 29 instaad of 26, the whole memorization
is almost useless.
>> return M[x];
>> }
>> }
>> };
>>
>>
>> int main(){
>> fib<uint64_t> f;
>> for (int i=0;i<50;i++)
>> cout<<f(i)<<endl;
>> return 0;
>> }
>>
>> For a general function, but for Fibonacci sequence is a poor idea.
>>
>> template <typename bignum>
>> class sane_fib
>> {
>> private:
>> vector <bignum> M;
>> public:
>> sane_fib()
>> {
>> M.push_back(0);
>> M.push_back(1);
>> }
>> bignum operator () (uint64_t x)
>> {
>> while (x >= M.size())
>> M.push_back( M[M.size()-1] + M[M.size()-2] );
>> return M[x];
>> }
>> };
>
> This is much better than the first example in terms of memory
> allocations, but still suffering from the memory explosion.
In rare cases you need (almost) all values for n<N.
I'm still not sure if this would be faster than O(log(n))
direct computation compared to random access to the array
(cache).
At least in this version wider index do not expand memory usage.
I do not see how to add memoization to if even if someone want to.
The 'trajectory' is too sparse for memoization to do anything important.
But it is still far for the best way.
The symatric matrix use 6 multiplication, but this is not a any
general matrix. One can use the relation d1 = d2+c
and get 4 multiplication per level.
If I really want, I can extract the equations (or loot to the wolfram
page) and write it with 3 bignum-bignum multiplications per level:
template <class bignum>
pair<bignum,bignum> fibf_pair ( uint64_t x )
{
//retrun fib{ x+1} and fib{x}
if (x==0)
return make_pair<bignum,bignum> (1,0);
bignum F2n1, F2n, Fn, Fn1;
tie(Fn1,Fn) = fibf_pair<bignum>(x/2); //n=x/2
F2n1 = Fn1*Fn1 + Fn*Fn;
F2n = Fn* (2* Fn1 - Fn );
if (x%2==0) // x == 2n; x+1 == 2n+1
return make_pair(F2n1,F2n);
else // x == 2n+1; x+1 == 2n+2
return make_pair(F2n1+F2n,F2n1);
}
template <class bignum>
bignum fibf ( uint64_t x )
{
return fibf_pair<bignum>(x).second;
}
But the matrix version is, paradoxically, easer to write.
Additionally the matrix framework give us a way to
compute F( a + b k ) for many k easily.
I used it for another exercise:
http://zimpha.github.io/2015/09/22/pa-2015-translate/#Fibonacci_(fib)_[A]
Best
Bartek