Limit of the factorial function



Am Freitag, den 21.08.2009, 00:15 +0200 schrieb Dieter Kaiser:
> 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))))))

Dan Gildea has already committed the code above. Thanks.

I would like to suggest a further change. 

All simplifying functions for the limit have the same structure. But
there are called in a lot of different ways in the routine simplimit. 

I think it might be a good idea not to do the evaluation or
simplification in the calling routine simplimit, but to transfer the
necessary variables expr, var, and val to the simplifying function, e.g.
for the factorial function we have the call

(simplimfact expr var val)

The simplifying function then does the necessary extraction of the
argument and does all calculations which are needed, e.g.

(defun simplimfact (expr var val)
  (let* ((arglim (limit (cadr expr) var val 'think))
         (arglim2 arglim))
    ...

The advantages are

1. 
More readable code, because we have an identical scheme for the
simplifying functions.

2. 
Avoid the long cond-clause in simplimit, but put the simplifying
function on the property list and look it up.


The code to look up the simplifying function is already present in the
routine simplimit:

    ((setq op (safe-get (mop exp) 'simplim%function))
     ;; Lookup a simplim%function from the property list
     (funcall op exp var val))

Dieter Kaiser