RosettaCodeData/Task/Fibonacci-sequence/M2000-Interpreter/fibonacci-sequence-2.m2000

78 lines
2.5 KiB
Plaintext

Class BigNum {
a=stack
Function Digits {
=len(.a)*14-(14-len(str$(stackitem(.a,len(.a)) ,"")))
}
Operator "+" (n) {
\\ we get a copy, but .a is pointer
\\ we make a copy, and get a new pointer
.a<=stack(.a)
acc=0
carry=0
const d=100000000000000@
k=min.data(Len(.a), len(n.a))
i=each(.a, 1,k )
j=each(n.a, 1,k)
while i, j {
acc=stackitem(i)+stackitem(j)+carry
carry= acc div d
return .a, i^+1:=acc mod d
}
if len(.a)<len(n.a) Then {
i=each(n.a, k+1, -1)
while i {
acc=stackitem(i)+carry
carry= acc div d
stack .a {data acc mod d}
}
} ELse.if len(.a)>len(n.a) Then {
i=each(.a, k+1, -1)
while i {
acc=stackitem(i)+carry
carry= acc div d
Return .a, i^+1:=acc mod d
if carry else exit
}
}
if carry then stack .a { data carry}
}
Function tostring$ {
if len(.a)=0 then ="0" : Exit
if len(.a)=1 then =str$(Stackitem(.a),"") : Exit
document buf$=str$(Stackitem(.a, len(.a)),"")
for i=len(.a)-1 to 1 {
Stack .a {
buf$=str$(StackItem(i), "00000000000000")
}
}
=buf$
}
class:
Module BigNum (s$) {
s$=filter$(s$,"+-.,")
if s$<>"" Then {
repeat {
If len(s$)<14 then Stack .a { Data val(s$) }: Exit
Stack .a { Data val(Right$(s$, 14)) }
S$=Left$(S$, len(S$)-14)
} Until S$=""
}
}
}
Inventory K=0:=BigNum("0"),1:=BigNum("1")
fib=Lambda K (x as decimal)-> {
If Exist(K, x) Then =Eval(K) :Exit
Ret=If(x>1->Lambda(x-1)+Lambda(x-2), bignum(str$(x,"")))
Append K, x:=Ret
=Ret
}
\\ Using this to handle form refresh by code
Set Fast!
For i=1 to 4000 {
N=Fib(i)
Print i
Print N.tostring$()
Refresh
}