-
Notifications
You must be signed in to change notification settings - Fork 34
/
fibonacci_k-th_order_fast.pl
executable file
·53 lines (40 loc) · 1.35 KB
/
fibonacci_k-th_order_fast.pl
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
#!/usr/bin/perl
# Daniel "Trizen" Șuteu
# Date: 25 April 2018
# https://github.com/trizen
# Efficient algorithm for computing the k-th order Fibonacci numbers.
# See also:
# https://oeis.org/A000045 (2-nd order: Fibonacci numbers)
# https://oeis.org/A000073 (3-rd order: Tribonacci numbers)
# https://oeis.org/A000078 (4-th order: Tetranacci numbers)
# https://oeis.org/A001591 (5-th order: Pentanacci numbers)
use 5.020;
use strict;
use warnings;
use Math::GMPz;
use experimental qw(signatures);
sub kth_order_fibonacci ($n, $k = 2) {
# Algorithm due to M. F. Hasler
# See: https://oeis.org/A302990
if ($n < $k - 1) {
return 0;
}
my @f = map {
$_ < $k
? do {
my $z = Math::GMPz::Rmpz_init();
Math::GMPz::Rmpz_setbit($z, $_);
$z;
}
: Math::GMPz::Rmpz_init_set_ui(1)
} 1 .. ($k + 1);
my $t = Math::GMPz::Rmpz_init();
foreach my $i (2 * ++$k - 2 .. $n) {
Math::GMPz::Rmpz_mul_2exp($t, $f[($i - 1) % $k], 1);
Math::GMPz::Rmpz_sub($f[$i % $k], $t, $f[$i % $k]);
}
return $f[$n % $k];
}
say "Tribonacci: ", join(' ', map { kth_order_fibonacci($_, 3) } 0 .. 15);
say "Tetranacci: ", join(' ', map { kth_order_fibonacci($_, 4) } 0 .. 15);
say "Pentanacci: ", join(' ', map { kth_order_fibonacci($_, 5) } 0 .. 15);