Subject: Work on the complex components: abs, carg, ...
From: Dieter Kaiser
Date: Thu, 23 Apr 2009 22:59:01 +0200
Again I have done some work on the functions for the complex components.
At first I would like to suggest 6 changes to improve the functions for
the complex components. My first aim was to extend abs to handle complex
expressions more carefully and to get more consistent results for
realpart, imagpart and carg.
(1)
Limit knows the following limits for atan2:
(%i10) limit(atan2(y,x),x,inf);
(%o10) 0
(%i17) assume(y1>0,y2<0)$
(%i18) limit(atan2(y1,x),x,minf);
(%o18) %pi
(%i19) limit(atan2(y2,x),x,minf);
(%o19) -%pi
But does not simplify expressions with infinities accordingly. When we
add code to simplify infinities as arguments Maxima would get:
(%i22) atan2(y,inf);
(%o22) 0
(%i23) assume(y1<0,y2>0);
(%i1) assume(y1>0,y2<0)$
(%i2) atan2(y1,-inf);
(%o2) %pi
(%i3) atan2(y2,-inf);
(%o3) -%pi
This would be the extension for atan2 to handle the infinities:
;; We add the simplification for infinities.
((or (eq x '$inf)
(alike1 x '((mtimes) -1 $minf)))
;; The argument x is inf.
0)
((or (eq x '$minf)
(alike1 x '((mtimes) -1 $inf)))
;; The argument x is -inf. We determine the sign of y.
;; If we can not, we return a noun form.
(setq signy ($sign y))
(cond ((eq signy '$pos) '$%pi)
((eq signy '$neg) (mul -1 '$%pi))
(t (eqtest (list '($atan2) y x) e))))
(2)
When the argument y is zero and x a positive real value, atan2 has the
value zero. For a negative argument x we get %pi.
(%i5) assume(x>0)$
(%i6) atan2(0,x);
(%o6) 0
(%i8) atan2(0,-x);
(%o8) %pi
atan2 does not recognize that abs(x) is a positive (or zero) value. This
prevents simplifications for the function carg, e.g. carg(abs(x)) should
be zero.
We can add a test for $PZ to the function atan2posp to check this case,
too.
HINT: It might be possible, that we simplify an expression carg(abs(x))
to zero for an argument abs(x)=0. This is not correct but the standard
behavior of carg at this time, because carg(0) simplifies to zero.
With this change we would get:
(%i1) carg(abs(x));
(%o1) 0
And with a further change (see 6) we get for complex symbols too:
(%i2) declare(z,complex)$
(%i3) carg(abs(z));
(%o3) 0;
This would be the change in the code:
;;; We include the case '$pz for this check. With this change
;;; we can detect something like abs(z) to be positive.
(defun atan2posp (e) (member ($sign e) '($pos $pz)))
(3)
Remove rectform from function $cabs
When we remove $rectform from the call to the function cabs we get much
more simple results, e.g.
(%i12) cabs(%e^z);
(%o12) %e^realpart(z)
There a lot of examples, which would be much more simple.
This is the change:
(defmfun $cabs (xx) (cabs xx))
(4)
Do not use the function asksign, but $sign and return a general noun
form if the sign is not known.
In the function absarg the function asksign is called to determine the
sign of a symbol, which represents a real value. When we avoid the use
of asksign, but use $sign the algorithm will not stop and returns a
general noun form.
/* Maxima returns a noun form without asking a sign */
(%i1) carg(x);
(%o1) atan2(0,x)
/* Now the sign is known and we get more simple results */
(%i2) assume(x>0)$
(%i3) carg(x);
(%o3) 0
(%i4) carg(-x);
(%o4) %pi
(%i5)
This change gives much more consistent simplifications of carg.
This would be the code in the routine absarg:
;; At this point we have a symbol, which represents
;; a real value. We have to determine the sign, but
;; we do not ask the sign. If we do not know the sign,
;; we return a more general expression with atan2.
(let ((gs (if (eq rischp l) '$positive ($sign l))))
(cond ((member gs '($pos $pz)) (cons l 0))
((eq gs '$zero) (cons 0 0))
((eq gs '$neg)
(cons (neg l) (simplify '$%pi)))
(t (cons (take '(mabs) l) (genatan 0 l))))))))
(5)
The function abs calls cabs for expressions which looks like complex
expressions. But the test with csign is very weak. If we add a test with
$csign much more results would be correct for complex expressions, e.g.
(%i1) declare(z,complex)$
(%i2) abs(%e^z);
(%o2) %e^realpart(z)
There a lot of complex expressions which would give correct results with
this extension to abs.
HINT: We have one problem with the function $limit. There is one example
which depends on the wrong answer that an expression is not complex, but
it is. Because of the more correct answer of abs the limit routine fails
to get the known limit. To avoid problems with limit and defint the call
to $csign is not done when we are in $limit. This is a hack which
preserve the compatibility with existing code.
This is the additional call to $csign in the routine simpabs:
((and (not limitp)
(member (setq z ($csign y)) '($complex $imaginary)))
(cabs y))
(6)
We do not return an expression with $cabs in absarg, but use the noun
form of the simplifying function abs. Because $cabs is a verb function
it is much more consistent to return the noun form of abs. The results
are more consistent and can further simplify.
This is the change:
((kindp l '$complex)
;; We have complex symbol. We return a noun form.
(cons (list '(mabs) l) ; mabs and not $cabs
(list '($carg) l)))
With the above changes we get more consistent results for a lot of
complex expressions.
These are the changes to the existing testsuite. For the following two
results we now get a result in terms of abs:
********************** Problem 87 ***************
Input:
rectform(log(u))
Result:
log(abs(u)) + %i carg(u)
This differed from the expected result:
%i carg(u) + log(cabs(u))
********************** Problem 88 ***************
Input:
cabs(u)
Result:
abs(u)
This differed from the expected result:
2 2
sqrt(imagpart (u) + realpart (u))
-----------------------------------------------------------
The following two results are now correct:
********************** Problem 42 ***************
Input:
abs(exp(z))
Result:
realpart(z)
%e
... Which was correct, but was expected to be wrong due to a known bug
in
Maxima.
********************** Problem 43 ***************
Input:
! 2!
subst(z = %i, !z !)
Result:
1
... Which was correct, but was expected to be wrong due to a known bug
in
Maxima.
---------------------------------------------------------------------------
Further, I had to change the examples in the file rtest_integrate.mac
which contain a sqrt(z). I had declared z to be complex. Because complex
expressions are now handled more carefully, the results change a bit.
For this examples I have changed z to a real symbol x. After this
changes we have no more problems with the testsuite.
So what do you think. Should we do the improvements of the functions for
the complex components.
In a next step further work to improve simplifications of carg,
realpart, imagpart and a generalization of signum to complex expressions
can be done.
Dieter Kaiser