Limit of the factorial function



I think we have at least four problems with the limit of the Factorial
function.

1. The limits from above and below for even negative integers are wrong:

This is the correct limit for an odd integer from above.

(%i4) limit(factorial(x),x,-1,plus);
(%o4) inf

For an even negative integer the answer is minf, but again we get inf:

(%i5) limit(factorial(x),x,-2,plus);
(%o5) inf

The same problem for the limit from below:

(%i8) limit(factorial(x),x,-1,minus);
(%o8) minf

The sign of the infinity does not change:

(%i9) limit(factorial(x),x,-2,minus);
(%o9) minf


2. Lisp error when the value is a symbol declared to be an integer.

(%i10) declare(n,integer)$

(%i11) limit(factorial(x),x,n,plus);
Maxima encountered a Lisp error:
MINUSP: $N is not a real number
Automatically continuing.
To reenable the Lisp debugger set *debugger-hook* to nil.


3. No limit when the value is a floating point number representing 
   a negative integer.

(%i14) limit(factorial(x),x,-1.0,plus);
factorial: factorial of negative integer -1.0 not defined.
 -- an error.  To debug this try debugmode(true);

But for a bigfloat number it works.

(%i15) limit(factorial(x),x,-1.0b0,plus);
`rat' replaced -1.0B0 by -1/1 = -1.0B0
`rat' replaced -1.0B0 by -1/1 = -1.0B0
`rat' replaced -1.0B0 by -1/1 = -1.0B0
(%o15) inf


4. Arguments with infinities do not simplify correctly.

(%i1) limit(factorial(x+inf),x,a);
(%o1) (a + inf)!
(%i2) limit(factorial(x+minf),x,a);
(%o2) (a + minf)!
(%i3) limit(factorial(x+infinity),x,a);
(%o3) (a + infinity)!


The code of the routine simplimfact in limit.lisp is responsible for
these problems. The following code already includes the necessary
corrections.

(defun simplimfact (expr var val arg)
  (let* ((arg (limit arg var val 'think)) ; Limit of the argument.
         (arg2 arg))
    (cond ((eq arg '$inf) '$inf)
          ((member arg '($minf $infinity $und $ind) :test #'eq) '$und)
          ((and (or (maxima-integerp arg)
                    (setq arg2 (integer-representation-p arg)))
;                (> 0 arg)       ; arg can be a symbol or an expression.
                (eq ($sign arg2) '$neg))
           ;; A negative integer or float or bigfloat representation.
           (let ((dir (limit (add expr (mul -1 arg2)) var val 'think))
;                 evenp is always nil!!! This code is wrong.
;                 (evenp (maxima-integerp (quotient arg 2.0)))
                 (even (mevenp arg2)))
             (cond ((or (and even
                             (eq dir '$zeroa))
                        (and (not even)
                             (eq dir '$zerob)))
                    '$minf)
                   ((or (and even
                             (eq dir '$zerob))
                        (and (not even)
                             (eq dir '$zeroa)))
                    '$inf)
                   (t (throw 'limit nil)))))
          (t
           (simplify (list '(mfactorial) arg))))))


These are the results with the corrections:

(%i22) limit(factorial(x),x,-1,plus);
(%o22) inf
(%i23) limit(factorial(x),x,-2,plus);
(%o23) minf
(%i24) limit(factorial(x),x,-3,plus);
(%o24) inf
(%i25) limit(factorial(x),x,-4,plus);
(%o25) minf

(%i26) declare(n,integer)$
(%i27) assume(n<0)$

n is declared to be a negative integer:

(%i29) limit(factorial(x),x,2*n-1,plus);
(%o29) inf
(%i30) limit(factorial(x),x,2*n-2,plus);
(%o30) minf
(%i31) limit(factorial(x),x,2*n-3,plus);
(%o31) inf

limit of the factorial functions works for float numbers:

(%i32) limit(factorial(x),x,-1.0,plus);
(%o32) inf
(%i33) limit(factorial(x),x,-2.0,plus);
(%o33) minf

Correct limits when infinities are involved.

(%i48) limit(factorial(x+inf),x,a);
(%o48) inf
(%i49) limit(factorial(x+infinity),x,a);
(%o49) und
(%i50) limit(factorial(x+inf),x,a);
(%o50) inf
(%i51) limit(factorial(x+minf),x,a);
(%o51) und
(%i52) limit(factorial(x+infinity),x,a);
(%o52) und

Dieter Kaiser