The well known bug in the factorial function of Maple7 can be fixed as shown below. The local procedures '_factorial' and 'fact' in the original module definition are flawed and may be corrected as indicated. Note that in ’fact’ the difference N-n may also be negative.
> test:=module() local _factorial,cacheN,cacheF,fact; _factorial:=proc(n::algebraic) local i; if type(n,'integer') then if n<0 then NumericEvent( 'real_to_complex', NumericEvent( 'division_by_zero', infinity+infinity*I ) ) elif n=0 or n=1 then 1 elif n<50 then mul(i,i=2..n) elif n=cacheN then cacheF elif n>cacheN then cacheF:=cacheF*fact(1+cacheN,n); cacheN:=n; cacheF # elif 49*cacheN<50*n then <=== deleted === # cacheF:=iquo(cacheF,fact(1+n,n)); <=== deleted === # cacheN:=n; <=== deleted === # cacheF <=== deleted === else cacheF:=fact(2,n); cacheN:=n; cacheF end if elif type(n,'complex(float)') then if n=0. then n+1.0 else evalf(evalf[Digits+2](n*GAMMA(n))) end if else ':-factorial(args)' end if end proc; cacheN,cacheF:=1000,1000!; fact:=proc(n,N) local q; if n=N then # <=== corrected === n # <=== corrected === elif N>n and N-n<=32 then # <=== corrected === mul(q,q=n..N) # <=== corrected === elif n>N and n-N<=32 then # <=== corrected === mul(q,q=N..n) # <=== corrected === else q:=iquo(N+n,2); fact(n,q)*fact(1+q,N) end if end proc end module:
> unprotect('Factorial'); > Factorial:=op(3,eval(test))[1]; Factorial := _factorial > protect('Factorial'); > testlib:="./test/lib": > mkdir("./test"); > mkdir(testlib); > march('create',testlib,100); > savelibname:=testlib: > restart; > savelib('Factorial');
We now restart the Maple7 session and demonstrate the bug in the original factorial function.
> restart; > libname; "C:\\Programme\\Maple7/lib" > 1001!/1000!,1002!/1000!,1002!/1001!,1003!/1000!,1003!/1001!,1003!/1002!; 1, 1, 1, 1, 1, 1
We now restart the Maple7 session again and appropriately extend ’libname’. The factorial function seems to give correct results now:
> restart; > libname:="./test/lib",libname: libname; "./test/lib", "C:\\Programme\\Maple7/lib" > 1001!/1000!,1002!/1000!,1002!/1001!,1003!/1000!,1003!/1001!,1003!/1002!; 1001, 1003002, 1002, 1006011006, 1005006, 1003
It is corrected with Maple 8 (U. Klein)