I had a look on the open bug report SF[1093138] "double factorial defn incorrect
for noninteger operand".
The Double factorial is implemented with an algorithm which works only for
positive integers. Unfortunatley, the implementation give results for positive
real arguments too (float and bigfloat). The results for float and bigfloat
arguments are wrong.
In a first attempt I tried to generalize the algorithm of simpgfact. But because
the operator !! is simplified to the function genfact(n,n/2,2) which needs three
arguments we get some problems.
So I tried to specialize the function even more to be sure that Maxima does the
calculation only for positive integers.
I added a test to detect a fixnum as the first argument and some code to give an
Maxima Error for numbes which are not positive integers including a test against
$factlim.
With this extensions we get the following results:
(%i8) 0!!; /* Correct results for positve integers */
(%o8) 1
(%i9) 1!!;
(%o9) 1
(%i10) 2!!;
(%o10) 2
(%i11) 3!!;
(%o11) 3
(%i12) 4!!;
(%o12) 8
(%i13) 5!!;
(%o13) 15
(%i14) (-1)!!; /* Maxima Error for all other numbers */
Bad argument to `genfact': -1
-- an error. To debug this try debugmode(true);
(%i15) (-2)!!;
Bad argument to `genfact': -2
-- an error. To debug this try debugmode(true);
(%i16) (2.5)!!;
Bad argument to `genfact': 2.5
-- an error. To debug this try debugmode(true);
(%i17) (2.5b0)!!;
Bad argument to `genfact': 2.5b0
-- an error. To debug this try debugmode(true);
(%i18) (3/2)!!;
Bad argument to `genfact': 3/2
-- an error. To debug this try debugmode(true);
(%i19) (2/3)!!;
Bad argument to `genfact': 2/3
-- an error. To debug this try debugmode(true);
I think it is the best to write a complete new function factorial_double(z)
which is generalized to real and even complex arguments. This function can call
genfact() for positive integers. Perhaps we can later change the code of the
parser to connect the operator !! to the function factorial_double().
This has the advantage that we do not have to change old code which uses the
function genfact() and the noun %genfact.
The testsuite has no problems with the specialization of simpgfact. So we have
no tests which depend on wrong results for real arguments.
What do you think? Should we correct the routine simpgfact and write a new
function factorial_double()?
Here are the changes to simpgfact:
Index: asum.lisp
===================================================================
RCS file: /cvsroot/maxima/maxima/src/asum.lisp,v
retrieving revision 1.28
diff -u -r1.28 asum.lisp
--- asum.lisp 28 Aug 2008 09:06:45 -0000 1.28
+++ asum.lisp 15 Sep 2008 20:53:16 -0000
@@ -296,8 +297,14 @@
(if (not (= (length x) 4)) (wna-err '$genfact))
(setq z (mapcar #'(lambda (q) (simpcheck q z)) (cdr x)))
(let ((a (car z)) (b (take '($floor) (cadr z))) (c (caddr z)))
- (cond ((and (fixnump b) (> b -1)) (gfact a b c))
- ((integerp b) (merror "Bad second argument to `genfact': ~:M" b))
+ (cond ((and (fixnump a) ; Test in addition the first argument
+ (or (minusp $factlim) (< a $factlim))
+ (fixnump b)
+ (> b -1))
+ (gfact a b c))
+ ((and (integerp b) (not (and (fixnump a) (> a $factlim))))
+ ;; We have a number as argument which is not a valid integer
+ (merror "Bad argument to `genfact': ~:M" a))
(t (eqtest (list '(%genfact) a
(if (and (not (atom b))
(eq (caar b) '$floor))
Success, CVS operation completed
Dieter Kaiser