Bug report ID 2123651 "min and max of imaginary and real numbers"



Hi, Dieter,

Thanks for your work.

One thing: I'd think that any comparisons involving imaginary quantities
should give errors, not nounforms or unknown.  It is not that %i < 3 is
unknown, it is actually not defined.  True, a*%i < 3 for a=0, so a nounform
might be sensible there, but I'd rather catch the anomaly. (Robert may
disagree with me on this...)

             -s

On Sun, Sep 5, 2010 at 14:41, Dieter Kaiser <drdieterkaiser at web.de> wrote:

> I had a look at the open bug report ID 2123651 "min and max of imaginary
> and real numbers". To correct the behavior I have tried the following
> changes:
>
> 1. In $compare
>   Check for infinities, infinitesimal, indeterminate.
>   Take the limit for this case. This simplifies -minf to minf
>   or 7+inf to inf.
>
> 2. In $compare
>   First, do the check lenient-extended-realp.
>   We do not try to do the test meqp for complex expressions.
>
> 3. In simp-max
>   In the final clause, do not remove a minf, when issue-warning is T.
>   Do not simplify to inf, when issue-warning is T.
>
> With these changes we get a noun form for expression like max(%i*inf,
> minf).
>
> We will get 5 changes in the testsuite (3 different results and 2
> correct results for expected failures):
>
> Running tests in rtest_allnummod:
> ********************** Problem 127 ***************
> Input:
> is(compare(%i, %i) = =)
>
>
> Result:
> false
>
> This differed from the expected result:
> true
>
> ********************** Problem 128 ***************
> Input:
> is(compare(a < b, a < b) = =)
>
>
> Result:
> false
>
> This differed from the expected result:
> true
>
> ********************** Problem 132 ***************
> Input:
> is(compare(infinity, infinity) = =)
>
>
> Result:
> false
>
> This differed from the expected result:
> true
>
> ********************** Problem 135 ***************
> Input:
> is(compare(inf, - minf) = =)
>
>
> Result:
> true
>
> ... Which was correct, but was expected to be wrong due to a known bug
> in
>  Maxima.
>
> ********************** Problem 136 ***************
> Input:
> is(compare(inf, 7 + inf) = =)
>
>
> Result:
> true
>
> ... Which was correct, but was expected to be wrong due to a known bug
> in
>  Maxima.
>
> This is the complete code with the changes:
>
> (defun $compare (a b)
>  (when (amongl '($ind $und $inf $minf $infinity $zeroa $zerob) a)
>    (setq a ($limit a)))
>  (when (amongl '($ind $und $inf $minf $infinity $zeroa $zerob) b)
>    (setq b ($limit b)))
>  (cond ((or (not (lenient-extended-realp a))
>             (not (lenient-extended-realp b)))
>         '$notcomparable)
>        ((eq t (meqp a b)) "=")
>        (t
>         (let ((sgn (csign (specrepcheck (sub a b)))))
>           (cond ((eq sgn '$neg) "<")
>                 ((eq sgn '$nz) "<=")
>                 ((eq sgn '$zero) "=")
>                 ((eq sgn '$pz) ">=")
>                 ((eq sgn '$pos) ">")
>                 ((eq sgn '$pn) "#")
>                 ((eq sgn '$pnz) '$unknown)
>                 (t '$unknown))))))
>
> (defun simp-max (l tmp z)
>  (let ((acc nil) (sgn) (num-max nil) (issue-warning))
>    (setq l (margs (specrepcheck l)))
>    (dolist (li l)
>      (if (op-equalp li '$max)
>          (setq acc (append acc (mapcar #'(lambda (s) (simplifya s z))
> (margs li))))
>          (push (simplifya li z) acc)))
>
>    ;; First, delete duplicate members of l.
>
>    (setq l (sorted-remove-duplicates (sort acc '$orderlessp)))
>    (setq acc nil)
>
>    ;; Second, find the largest real number in l. Since (mnump '$%i) -->
> false,
>    ;; we don't have to worry that num-max is complex.
>
>    (dolist (li l)
>      (if (mnump li)
>          (setq num-max (if (or (null num-max) (mgrp li num-max)) li
> num-max))
>          (push li acc)))
>    (setq l acc)
>    (setq acc (if (null num-max) num-max (list num-max)))
>
>    ;; Third, accumulate the maximum in the list acc. For each x in l,
> do:
>
>    ;; (a) if x is > or >= every member of acc, set acc to (x),
>    ;; (b) if x is < or <= to some member of acc, do nothing,
>    ;; (c) if neither 'a' or 'b', push x into acc,
>    ;; (d) if x cannot be compared to some member of acc, set
> issue-warning to true.
>
>    (dolist (x l)
>      (catch 'done
>        (dolist (ai acc)
>          (setq sgn ($compare x ai))
>          (cond ((member sgn '(">" ">=") :test #'equal)
>                 (setq acc (delete ai acc :test #'eq)))
>                ((eq sgn '$notcomparable) (setq issue-warning t))
>                ((member sgn '("<" "=" "<=") :test #'equal)
>                 (throw 'done t))))
>             (push x acc)))
>
>    ;; Fourth, when when trylevel is 2 or higher e and -e are members of
> acc,
>    ;; replace e by |e|.
>
>    (cond ((eq t (mgrp ($get '$trylevel '$maxmin) 1))
>           (setq sgn nil)
>           (dolist (ai acc)
>             (setq tmp (if (lenient-realp ai)
>                           (member-if #'(lambda (s) (add-inversep ai s))
> sgn)
>                           nil))
>             (if tmp
>                 (setf (car tmp) (take '(mabs) ai))
>                 (push ai sgn)))
>           (setq acc sgn)))
>
>    ;; Fifth, when trylevel is 3 or higher and issue-warning is false,
> try the
>    ;; betweenp simplification.
>
>    (cond ((and (not issue-warning) (eq t (mgrp ($get '$trylevel
> '$maxmin) 2)))
>           (setq l nil)
>           (setq sgn (cdr acc))
>           (dolist (ai acc)
>             (if (not (betweenp ai sgn sgn)) (push ai l))
>             (setq sgn `(,@(cdr sgn) ,ai)))
>           (setq acc l)))
>
>    ;; Finally, do a few clean ups:
>
>    (setq acc (if (not issue-warning) (delete '$minf acc) acc))
>    (cond ((null acc) '$minf)
>          ((and (not issue-warning) (member '$inf acc :test #'eq))
> '$inf)
>          ((null (cdr acc)) (car acc))
>          (t  `(($max simp) ,@(sort acc '$orderlessp))))))
>
> Comments? Should I commit the code?
>
> Dieter Kaiser
>
>
> _______________________________________________
> Maxima mailing list
> Maxima at math.utexas.edu
> http://www.math.utexas.edu/mailman/listinfo/maxima
>