Math::NumSeq::Fibonacci -- Fibonacci numbers
use Math::NumSeq::Fibonacci; my $seq = Math::NumSeq::Fibonacci->new; my ($i, $value) = $seq->next;
The Fibonacci numbers F(i) = F(i-1) + F(i-2) starting from 0,1,
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ... starting i=0
See "FUNCTIONS" in Math::NumSeq for behaviour common to all sequence classes.
$seq = Math::NumSeq::Fibonacci->new ()
Create and return a new sequence object.
($i, $value) = $seq->next()
Return the next index and value in the sequence.
$value exceeds the range of a Perl unsigned integer the return is a
Math::BigInt to preserve precision.
Move the current sequence position to
$i. The next call to
next() will return
$i and corresponding value.
$value = $seq->ith($i)
$i'th Fibonacci number.
$bool = $seq->pred($value)
Return true if
$value is a Fibonacci number.
$i = $seq->value_to_i_estimate($value)
Return an estimate of the i corresponding to
$value. See "Value to i Estimate" below.
Fibonacci F[i] can be calculated by a powering procedure with two squares per step. A pair of values F[k] and F[k-1] are maintained and advanced according to bits of i from high to low
start k=1, F[k]=1, F[k-1]=0 add = -2 # 2*(-1)^k loop F[2k+1] = 4*F[k]^2 - F[k-1]^2 + add F[2k-1] = F[k]^2 + F[k-1]^2 F[2k] = F[2k+1] - F[2k-1] bit = next bit of i, high to low, skip high 1 bit if bit == 1 take F[2k+1], F[2k] as new F[k],F[k-1] add = -2 (for next loop) else bit == 0 take F[2k], F[2k-1] as new F[k],F[k-1] add = 2 (for next loop)
For the last (least significant) bit of i an optimization can be made with a single multiple for that last step, instead of two squares.
bit = least significant bit of i if bit == 1 F[2k+1] = (2F[k]+F[k-1])*(2F[k]-F[k-1]) + add else F[2k] = F[k]*(F[k]+2F[k-1])
The "add" amount is 2*(-1)^k which means +2 or -2 according to k odd or even, which in turn means whether the previous bit taken from i was 1 or 0. That can be easily noted from each bit, to be used in the following loop iteration or the final step F[2k+1] formula.
For small i it's usually faster to just successively add F[k+1]=F[k]+F[k-1], but when in bignums the doubling k->2k by two squares is faster than doing k many individual additions for the same thing.
F[i] increases as a power of phi, the golden ratio. The exact value is
F[i] = (phi^i - beta^i) / (phi - beta) # exactly phi = (1+sqrt(5))/2 = 1.618 beta = -1/phi = -0.618
Since abs(beta)<1 the beta^i term quickly becomes small. So taking a log (natural logarithm) to get i,
log(F[i]) ~= i*log(phi) - log(phi-beta) i ~= (log(F[i]) + log(phi-beta)) / log(phi)
Or the same using log base 2 which can be estimated from the highest bit position of a bignum,
log2(F[i]) ~= i*log2(phi) - log2(phi-beta) i ~= (log2(F[i]) + log2(phi-beta)) / log2(phi)
Copyright 2010, 2011, 2012, 2013, 2014 Kevin Ryde
Math-NumSeq is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version.
Math-NumSeq is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with Math-NumSeq. If not, see <http://www.gnu.org/licenses/>.