Bug in simpplog



[I posted this in July, but it got lost in the moderator queue]

I noticed recently that plog's simplifier knows less than atan2's:

(%i1) display2d:false;
(%o1) false
(%i2) plog( (%i + sqrt(3))/2 );
(%o2) plog((%i+sqrt(3))/2)
(%i3) atan2( 1/2, sqrt(3)/2 );
(%o3) %pi/6

After some investigation, I found that simpplog contains the necessary
logic to simplify the example above, but is failing due to a bug.

simpplog (in csimp2.lisp) calls newvar (in rat3e.lisp) to find the
variables in plog's argument.  In the case of complex numbers which
are neither real nor purely imaginary, it only attempts simplification
if the FIRST variable found by newvar is %i, and the rest are all
non-atoms:

     (cond
       ((and (eq '$%i (car varlist)) (not (some #'atom (cdr varlist))))

In the example above, newvar reports two "variables": sqrt(3) and %i,
in that order.  Since the the %i doesn't come first, simpplog refuses
to simplify it.

The patch below changes the test as follows, so that %i needn't come
first.

     (cond
       ((and (member '$%i varlist)
	     (not (some #'(lambda (v)
			    (and (atom v) (not (eq v '$%i))))
			varlist)))

With this change, plog now handles the above case properly:

(%i2) plog( (%i + sqrt(3))/2 );
(%o2) %i*%pi/6

However, I also wonder about the rationale of requiring that other
"variables" (other than %i) be non-atomic.  Is this test really
relevant to decide whether to perform this simplification?

     Mark


diff -u -F defmfun src/csimp2{-orig,}.lisp
--- src/csimp2-orig.lisp	2010-09-24 15:42:04.000000000 -0400
+++ src/csimp2.lisp	2011-01-06 12:52:48.000000000 -0500
@@ -38,7 +38,10 @@ (defmfun simpplog (x vestigial z)
 	    (return (eqtest (list '(%plog) x) check))))
      (newvar x)
      (cond
-       ((and (eq '$%i (car varlist)) (not (some #'atom (cdr varlist))))
+       ((and (member '$%i varlist)
+	     (not (some #'(lambda (v)
+			    (and (atom v) (not (eq v '$%i))))
+			varlist)))
 	(setq dd (trisplit x))
 	(cond ((setq z (patan (car dd) (cdr dd)))
 	       (return (add2* (simpln (list '(%log)