I wonder if anybody can beat that; I would expect a more modern M4 Mac Mini to be even faster. The program is compatible with BBC BASIC for SDL 2.0 or BBC BASIC for Windows, although in the latter case it would need the bigint.bbc library to be copied across.
In principle the program is compatible with the BBC BASIC Console Mode editions as well, but version 0.48 has a bug in the array slicing implementation which probably prevents it running. I hope to publish an update to fix this in the near future.
Code: Select all
INSTALL @lib$ + "bigint"
PROCbiginit
fibo%% = FNbignew(1000000)
start = TIME
PROCfibo(4784969, fibo%%)
finish = TIME
PRINT (finish-start)/100 " seconds"
END
REM Fibonacci calculation using the doubling algorithm:
DEF PROCfibo(N%, f%%)
LOCAL S%, a%%, b%%, c%%
IF N% N% -= 1 ELSE PROCbigval(f%%, "0") : ENDPROC
S% = N% * LOG((SQR(5) + 1) / 2) + 1
a%% = FNbignew(S%) : b%% = FNbignew(S%)
PROCfibo2(N% DIV 2, a%%, b%%)
c%% = FNbignew(S%)
IF (N% AND 1) = 0 THEN
REM f = b*(2*b-a)-(-1)^k
PROCbiguadd(f%%, b%%, b%%)
PROCbigusub(c%%, f%%, a%%)
PROCbigumul(f%%, b%%, c%%)
IF N% MOD 4=0 THEN PROCbigudec(f%%) ELSE PROCbiguinc(f%%)
ELSE
REM f = b*(2*a+b)
PROCbiguadd(f%%, a%%, a%%)
PROCbiguadd(c%%, f%%, b%%)
PROCbigumul(f%%, b%%, c%%)
ENDIF
ENDPROC
DEF PROCfibo2(N%, f%%, g%%)
LOCAL S%, a%%, b%%, c%%, d%%
S% = N% * LOG((SQR(5) + 1) / 2) + 1
IF N% = 0 THEN
PROCbigval(f%%, "0") : REM f = 0
PROCbigval(g%%, "1") : REM g = 1
ENDPROC
ENDIF
a%% = FNbignew(S%) : b%% = FNbignew(S%)
PROCfibo2(N% DIV 2, a%%, b%%)
c%% = FNbignew(S%) : d%% = FNbignew(S%)
IF N% AND 1 THEN
REM f = a*(2*a+b)+(-1)^k
REM g = b*(2*a+b)
PROCbiguadd(c%%, a%%, a%%)
PROCbiguadd(d%%, c%%, b%%)
PROCbigumul(g%%, b%%, d%%)
PROCbigumul(f%%, a%%, d%%)
IF N% MOD 4 = 1 THEN PROCbiguinc(f%%) ELSE PROCbigudec(f%%)
ELSE
REM f = a*(2*b-a)
REM g = b*(2*b-a)-(-1)^k
PROCbiguadd(c%%, b%%, b%%)
PROCbigusub(d%%, c%%, a%%)
PROCbigumul(f%%, a%%, d%%)
PROCbigumul(g%%, b%%, d%%)
IF N% MOD 4 = 0 THEN PROCbigudec(g%%) ELSE PROCbiguinc(g%%)
ENDIF
ENDPROC