|
From: willisbl <wil...@us...> - 2025-10-07 19:25:00
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Maxima CAS".
The branch, master has been updated
via d00e008a586c58f5b0dfbf7694f031ba53462a19 (commit)
from 5f931d9be7f7f34a9526feee56f3eeb86fac0bf8 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit d00e008a586c58f5b0dfbf7694f031ba53462a19
Author: Barton Willis <wi...@un...>
Date: Tue Oct 7 14:24:38 2025 -0500
Fixes for \#4615, \#4609, and \#4613
- Fix for \# 4615 carg range is not in (-pi, pi]
The fix for the specific bug mentioned involves fixes to the atan2 simplifier. The tests for this are in rtest15. There might be other cases where the range of
carg is not in (-pi,pi].
- Fix for \# 4609 atan2(inf,inf) -> 0
There is a new scheme in the atan2 simplifier that catches atan2(X,Y), where
X and Y are extended real numbers. Regression tests are in rtest_atan2.
- Fix for \# 4613 integrate(atan2(sin(x), cos(x)), x, 0, 9*%pi);
The fix is all in the atan2 simplifier. Regression tests are in rtest_atan2.
New functions
- cosp (similar to sinp)
- reduce-angle-mod-2pi
- nonvanishing-common-factor
- polar-angle-if-sinusoids
- initialize-atan2-hashtable
New testfile
-rtest_atan2
Includes tests for \#4615, \#4609, \#4613, and \#3750 (was fixed some time ago).
Tested with Clozure 1.13 and sbcl 2.4.7. No unexpected testsuite or share testsuite failures.
diff --git a/src/comm2.lisp b/src/comm2.lisp
index e4ed1f629..2af9828f3 100644
--- a/src/comm2.lisp
+++ b/src/comm2.lisp
@@ -487,6 +487,93 @@
;;;; ATAN2
+;; The function sinp is defined in `limit.lisp'. Here we define `cosp`.
+(defun cosp (e)
+"Return true iff the expression `e` is in general form and its operator is `%cos`."
+ (and (consp e) (eq '%cos (caar e))))
+
+;; Checks:
+;; (i) pi - 2 pi ceiling((pi - pi)/(2 pi)) = pi - 0 = pi, and
+;; (ii) -pi - 2 pi ceiling((-pi - pi)/(2 pi)) = -pi - 2 pi ceiling(-1) = -pi + 2pi = pi, as required.
+(defun reduce-angle-mod-2pi (theta)
+ "Reduce the input `mod 2 pi` to a value in the interval `(-pi, pi]`.
+ Thus -pi reduces to pi, and pi reduces to pi."
+ (cond
+ ;; The range of both atan2 and carg is `(-pi,pi]`, so give a free pass for such expressions.
+ ((and (consp theta) (or (eq (caar theta) '%atan2) (eq (caar theta) '%carg)))
+ theta)
+ (t
+ (let ((n (ftake '$ceiling (div (sub theta '$%pi) (mul 2 '$%pi)))))
+ ;; If you want to do the reduction only when `n` is an explicit integer,
+ ;; put in a conditional and return nil when `n` is not an explicit integer.
+ (sub theta (mul 2 '$%pi n))))))
+
+(defun nonvanishing-common-factor (p q)
+ "Return the product of the absolute values of the nonvanishing factors that are common to p and q. This code
+ doesn't factor p or q, so it only considers factors that are explict. When there are no
+ such factors, return one, that is, the empty product."
+ (let* ((pp (fapply '$set (if (mtimesp p) (cdr p) (list p))))
+ (qq (fapply '$set (if (mtimesp q) (cdr q) (list q))))
+ (ss (cdr ($intersection pp qq)))
+ (ll nil))
+ (dolist (sx ss)
+ (when (eq t (mnqp sx 0))
+ (push (ftake 'mabs sx) ll)))
+ (fapply 'mtimes ll)))
+
+;; Outside the one call to this function in the atan2 simplifier, this code likely isn't particulary useful.
+(defun polar-angle-if-sinusoids (x y)
+ "When both `x` and `y` have the form `(+/-) sin(X)` or `(+/-) cos(X)` and the point (x,y) is on the unit circle,
+ return the principal polar angle of the point `(x,y)`. Otherwise, return nil. The principal polar angle is a
+ member of the interval `(-pi,pi]`."
+ (flet ((sinusoid-p (x)
+ (or (cosp x) (cosp (neg x)) (sinp x) (sinp (neg x)))))
+ (when (and (sinusoid-p x) (sinusoid-p y))
+ (let ((z ($expand ($exponentialize (add x (mul '$%i y))))))
+ (flet ((fn (x)
+ (cond ((eql x -1) '$%pi)
+ ((eq x '$%i) (div '$%pi 2))
+ ((and (mexptp x) (eq (cadr x) '$%e)) (div (caddr x) '$%i))
+ (t nil))))
+ ;; When `(x,y)` isn't on the unit circle (say `x = sin(p)` and `y = cos(q)`) `z` will not
+ ;; be a product of terms that are on the unit circle, and the `every` check will fail.
+ (let ((theta (mapcar #'fn (if (mtimesp z) (cdr z) (list z)))))
+ (if (every #'identity theta)
+ (reduce-angle-mod-2pi (fapply 'mplus theta))
+ nil)))))))
+
+(defvar *atan2-extended-real-hashtable* (make-hash-table :test #'equal)
+"Hashtable giving the value of atan2(extended real, extended real) when the value
+is unambiguous. Ambiguous cases, for example atan2(inf,inf), are not included in
+the hashtable.")
+
+;; At compile time, the functions `div` and `mul` are not available, so we
+;; cannot build `atan2-extended-real-hashtable*` here. To workaround this, we define
+;; a function `initialize-atan2-hashtable` that hash table *atan2-extended-real-hashtable*,
+;; we and call this function in `init-cl.lisp`.
+(defun initialize-atan2-hashtable ()
+ (let ((pi-over-two (div '$%pi 2)) (neg-pi-over-two (div '$%pi -2)) (minus-pi (mul -1 '$%pi)))
+ (mapcar #'(lambda (z) (setf (gethash (list (first z) (second z)) *atan2-extended-real-hashtable*) (third z)))
+ (list
+ (list '$minf '$zerob neg-pi-over-two)
+ (list '$minf '$zeroa neg-pi-over-two)
+ (list '$minf '$ind neg-pi-over-two)
+
+ (list '$zerob '$minf minus-pi)
+ (list '$zerob '$inf 0)
+
+ (list '$zeroa '$minf '$%pi)
+ (list '$zeroa '$inf 0)
+
+ (list '$ind '$inf 0)
+
+ (list '$inf '$zerob pi-over-two)
+ (list '$inf '$zeroa pi-over-two)
+ (list '$inf '$ind pi-over-two)))))
+
+(defvar *extended-reals* '($minf $zerob $zeroa $ind $und $inf $infinity)
+"Common Lisp list of all of Maxima's extended real numbers")
+
;; atan2 distributes over lists, matrices, and equations
(defprop %atan2 (mlist $matrix mequal) distribute_over)
@@ -496,7 +583,26 @@
;; `block([radexpand: false], limit(atan2(x^2 - 2, x^3 - 3*x), x, sqrt(2), minus))`.
;; Arguably, this fix is inelegant and should be revisited. (Barton Willis, April 2025)
(def-simplifier atan2 (y x)
- (let (signy signx)
+ ;; for both x & y, convert -inf to minf.
+ (when (alike1 y (mul -1 '$inf))
+ (setq y '$minf))
+ (when (alike1 x (mul -1 '$inf))
+ (setq x '$minf))
+ ;; for both x & y, convert -minf to inf.
+ (when (alike1 y (mul -1 '$minf))
+ (setq y '$inf))
+ (when (alike1 x (mul -1 '$minf))
+ (setq x '$inf))
+
+ ;; Divide both x & y by the absolute value of common factors that are
+ ;; nonvanishing. Skip this when either x or y depend on an extended real.
+ (when (and (freeofl y *extended-reals*) (freeofl x *extended-reals*))
+ (let ((w (nonvanishing-common-factor y x)))
+ (setq y (div y w))
+ (setq x (div x w))))
+
+ (let ((signy) (signx))
+
(cond ((and (zerop1 y) (zerop1 x))
(merror (intl:gettext "atan2: atan2(0,0) is undefined.")))
(;; float contagion
@@ -511,39 +617,49 @@
(setq x ($bfloat x)
y ($bfloat y))
(*fpatan y (list x)))
- ;; Simplifify infinities
- ((or (eq x '$inf)
- (alike1 x '((mtimes) -1 $minf)))
+ ;; Look up atan(extended real, extended real) in a hashtable. When the value
+ ;; isn't found in the hashtable, return a nounform.
+ ((and (member x *extended-reals*) (member y *extended-reals*))
+ (gethash (list y x) *atan2-extended-real-hashtable* (give-up)))
+
+ ;;When either `x` or `y` is in ($und infinity $ind), give up
+ ((or (member x '($und $infinity $ind)) (member y '($und $infinity $ind)))
+ (give-up))
+
+ ;; Simplify infinities--the hashtable lookup catches atan2(inf,inf),atan2(minf,inf), ..., so
+ ;; we should be able to safely do atan2(y,inf) = 0 here.
+ ((eq x '$inf)
;; Simplify atan2(y,inf) -> 0
0)
- ((or (eq x '$minf)
- (alike1 x '((mtimes) -1 $inf)))
+ ((eq x '$minf)
;; Simplify atan2(y,minf) -> %pi for realpart(y)>=0 or -%pi
- ;; for realpart(y)<0. When sign of y unknwon, return noun
+ ;; for realpart(y)<0. When sign of y unknown, return noun
;; form. We are basically making atan2 on the branch cut
;; be continuous with quadrant II.
- (cond ((member (setq signy ($sign ($realpart y))) '($pos $pz $zero))
- '$%pi)
- ((eq signy '$neg) (mul -1 '$%pi))
- (t (give-up))))
- ((or (eq y '$inf)
- (alike1 y '((mtimes) -1 $minf)))
- ;; Simplify atan2(inf,x) -> %pi/2
- (div '$%pi 2))
- ((or (eq y '$minf)
- (alike1 y '((mtimes -1 $inf))))
- ;; Simplify atan2(minf,x) -> -%pi/2
+ (let ((sgn ($sign ($realpart y))))
+ (cond ((member sgn '($pos $pz $zero))
+ '$%pi)
+ ((eq sgn '$neg) (mul -1 '$%pi))
+ (t (give-up)))))
+ ;; We have already taken care of atan2(extended real, extended real), so we can
+ ;; safely simplify atan2(inf, X) to %pi/2 and atan2(minf, X) to -%pi/2. The case
+ ;; atan2(inf, %i) = %pi/2 is likely OK.
+ ((eq y '$inf)
+ (div '$%pi 2))
+ ((eq y '$minf)
(div '$%pi -2))
((and (free x '$%i) (setq signx (let ((limitp nil)) ($sign x)))
(free y '$%i) (setq signy (let ((limitp nil)) ($sign y)))
- (cond ((zerop1 y)
+ (cond ((eq signy '$zero)
;; Handle atan2(0, x) which is %pi or -%pi
;; depending on the sign of x. We assume that
;; x is never actually zero since atan2(0,0) is
;; undefined.
(cond ((member signx '($neg $nz)) '$%pi)
- ((member signx '($pos $pz)) 0)))
- ((zerop1 x)
+ ((member signx '($pos $pz)) 0)
+ ((eq signx '$zero) (merror (intl:gettext "atan2: atan2(0,0) is undefined.")))))
+
+ ((eq signx '$zero)
;; Handle atan2(y, 0) which is %pi/2 or -%pi/2,
;; depending on the sign of y.
(cond ((eq signy '$neg) (div '$%pi -2))
@@ -558,23 +674,29 @@
;; -%pi/4 depending on the sign of x.
(cond ((eq signx '$neg) (mul 3 (div '$%pi 4)))
((member signx '($pos $pz)) (div '$%pi -4)))))))
+
+ ;; atan2((+/-)sin(angle),(+/-)cos(angle)) = angle reduced to (-pi,pi] mod 2 pi.
+ ;; and similarly for atan2((+/-)cos(angle),(+/-)sin(angle))
+ ((polar-angle-if-sinusoids x y))
($logarc
(logarc '%atan2 (list ($logarc y) ($logarc x))))
- ((and $trigsign (eq t (mminusp y)))
- ;; atan2(-y,x) = -atan2(y,x) if trigsign is true.
- (neg (take '(%atan2) (neg y) x)))
- ;; atan2(y,x) = atan(y/x) + pi sign(y) (1-sign(x))/2
+ ;; atan2(-y,x) = -atan2(y,x) provided (a) trigsign is true, (b) (great (neg y) y), and
+ ;; (c) (x,y) is off the negative real axis. The test for (x,y) off the negative
+ ;; real axis should be (or (eq t (mnqp y 0)) (eq t (mgrp x 0))), but that causes
+ ;; one testsuite failure, so we'll test using (or (not (eql y 0)) (eq signx '$pos)))
+ ((and $trigsign
+ (eq t (mminusp y))
+ (or (not (eql y 0)) (eq signx '$pos)))
+ (neg (ftake '%atan2 (neg y) x)))
((eq signx '$pos)
;; atan2(y,x) = atan(y/x) when x is positive.
(take '(%atan) (div y x)))
- ((and (eq signx '$neg)
- (member (setq signy ($csign y)) '($pos $neg) :test #'eq))
- (add (take '(%atan) (div y x))
- (porm (eq signy '$pos) '$%pi)))
- ((and (eq signx '$zero) (eq signy '$zero))
- ;; Unfortunately, we'll rarely get here. For example,
- ;; assume(equal(x,0)) atan2(x,x) simplifies via the alike1 case above
- (merror (intl:gettext "atan2: atan2(0,0) is undefined.")))
+
+ ((and (eq signx '$neg) (member signy '($pos $neg $pz $zero) :test #'eq))
+ (cond ((eq signy '$neg) (sub (ftake '%atan (div y x)) '$%pi))
+ ((member signy '($pos $pz $zero)) (add (ftake '%atan (div y x)) '$%pi))
+ (t (give-up))))
+
(t (give-up)))))
;;;; ARITHF
diff --git a/src/init-cl.lisp b/src/init-cl.lisp
index 51066f3d0..dc65afd24 100644
--- a/src/init-cl.lisp
+++ b/src/init-cl.lisp
@@ -720,6 +720,7 @@ maxima [options] --batch-string='batch_answers_from_file:false; ...'
(setf $pointbound *alpha)
(setf (gethash '$pointbound *variable-initial-values*)
*alpha)
+ (initialize-atan2-hashtable)
(values))
(defun adjust-character-encoding ()
diff --git a/src/testsuite.lisp b/src/testsuite.lisp
index d34fbeacc..929913446 100644
--- a/src/testsuite.lisp
+++ b/src/testsuite.lisp
@@ -148,7 +148,8 @@
((mlist simp) 12 13))
((mlist simp) "rtest_great" ((mlist simp)))
-
+
+ ((mlist simp) "rtest_atan2" ((mlist simp) 65))
"rtest_gcd"
;; The tests that failed with abcl 1.5.0
((mlist simp) "rtest_hg"
diff --git a/tests/rtest15.mac b/tests/rtest15.mac
index 722f1d894..cae324adc 100644
--- a/tests/rtest15.mac
+++ b/tests/rtest15.mac
@@ -1619,14 +1619,14 @@ trigreduce(atan( sin(7*%pi/13) / cos(7*%pi/13) ));
-6*%pi/13;
carg( cos(7*%pi/13) + %i*sin(7*%pi/13) );
-atan(sin((7*%pi)/13)/cos((7*%pi)/13))+%pi;
+7*%pi/13$
trigreduce(carg( cos(7*%pi/13) + %i*sin(7*%pi/13) ));
7*%pi/13;
(z: cos ( 13 * %pi / 15 ) + %i * sin ( 13 * %pi / 15 ),
carg ( z ));
-atan(sin((13*%pi)/15)/cos((13*%pi)/15))+%pi;
+13*%pi/15$
atan ( tan ( 13 * %pi / 15 ) ) + %pi;
13*%pi/15;
@@ -1645,7 +1645,7 @@ trigreduce ( carg ( z ) );
/* examples from SF bug #4208: "Error with complex numbers - example with trigreduce" */
trigreduce(carg(c/d));
-24*%pi/13;
+-2*%pi/13$
trigreduce(carg(cos(3*%pi/5)+%i * sin(3*%pi/5)));
3*%pi/5;
diff --git a/tests/rtest_atan2.mac b/tests/rtest_atan2.mac
new file mode 100644
index 000000000..d03ed4332
--- /dev/null
+++ b/tests/rtest_atan2.mac
@@ -0,0 +1,254 @@
+(kill(values), 0);
+0$
+
+atan2(1, 1);
+%pi/4$
+
+atan2(1, -1);
+3*%pi/4$
+
+atan2(-1, -1);
+-3*%pi/4$
+
+atan2(-1, 1);
+-%pi/4$
+
+atan2(0, 1);
+0$
+
+atan2(0, -1);
+%pi$
+
+atan2(1, 0);
+%pi/2$
+
+atan2(-1, 0);
+-%pi/2$
+
+errcatch(atan2(0, 0));
+[]$
+
+atan2(0, inf);
+0$
+
+atan2(zerob, inf);
+0$
+
+atan2(zeroa, inf);
+0$
+
+atan2(0, -inf);
+%pi$
+
+atan2(zerob, -inf);
+-%pi$
+
+atan2(zeroa, -inf);
+%pi$
+
+atan2(0,minf);
+%pi$
+
+atan2(zerob,minf);
+-%pi$
+
+atan2(zeroa,minf);
+%pi$
+
+atan2(inf, 1);
+%pi/2$
+
+atan2(-inf, 1);
+-%pi/2$
+
+atan2(minf,1);
+-%pi/2$
+
+atan2(1, inf);
+0$
+
+atan2(1, -inf);
+%pi$
+
+atan2(1, minf);
+%pi$
+
+atan2(inf, -1);
+%pi/2$
+
+atan2(-inf, -1);
+-%pi/2$
+
+atan2(minf, -1);
+-%pi/2$
+
+block([ans],
+ assume(-%pi < x, x <= '%pi),
+ ans : atan2(sin(x),cos(x)),
+ forget(-%pi < x, x <= '%pi),
+ ans);
+x$
+
+atan2(sin(x), cos(x));
+x-2*%pi*ceiling((x-%pi)/(2*%pi))$
+
+/* test identity atan2(sin(x), cos(x)) */
+block([ans1 : makelist(trigreduce(atan2(sin(%pi*k/8),cos(%pi*k/8))),k,-16,16),
+ ans2 : block([zzz : atan2(sin(x),cos(x))], makelist(subst(x = %pi*k/8, zzz),k,-16,16))],
+ every(lambda([q],is(q=0)),trigsimp(ans1 - ans2)));
+true$
+
+/* test identity atan2(-sin(x), cos(x))*/
+block([ans1 : makelist(trigreduce(atan2(-sin(%pi*k/8),cos(%pi*k/8))),k,-16,16),
+ ans2 : block([zzz : atan2(-sin(x),cos(x))], makelist(subst(x = %pi*k/8, zzz),k,-16,16))],
+ every(lambda([q],is(q=0)), trigsimp(ans1 - ans2)));
+true$
+
+/* test identity atan2(sin(x), -cos(x))*/
+block([ans1 : makelist(trigreduce(atan2(sin(%pi*k/8),-cos(%pi*k/8))),k,-16,16),
+ ans2 : block([zzz : atan2(sin(x),-cos(x))], makelist(subst(x = %pi*k/8, zzz),k,-16,16))],
+ every(lambda([q],is(q=0)), trigsimp(ans1 - ans2)));
+true$
+
+/* test identity atan2(-sin(x), -cos(x))*/
+block([ans1 : makelist(trigreduce(atan2(-sin(%pi*k/8),-cos(%pi*k/8))),k,-16,16),
+ ans2 : block([zzz : atan2(-sin(x),-cos(x))], makelist(subst(x = %pi*k/8, zzz),k,-16,16))],
+ every(lambda([q],is(q=0)), trigsimp(ans1 - ans2)));
+true$
+
+/* test identity atan2(cos(x), sin(x)) */
+block([ans1 : makelist(trigreduce(atan2(cos(%pi*k/8),sin(%pi*k/8))),k,-16,16),
+ ans2 : block([zzz : atan2(cos(x),sin(x))], makelist(subst(x = %pi*k/8, zzz),k,-16,16))],
+ every(lambda([q],is(q=0)),trigsimp(ans1 - ans2)));
+true$
+
+/* test identity atan2(-cos(x), sin(x))*/
+block([ans1 : makelist(trigreduce(atan2(-cos(%pi*k/8),sin(%pi*k/8))),k,-16,16),
+ ans2 : block([zzz : atan2(-cos(x),sin(x))], makelist(subst(x = %pi*k/8, zzz),k,-16,16))],
+ every(lambda([q],is(q=0)), trigsimp(ans1 - ans2)));
+true$
+
+/* test identity atan2(cos(x), -sin(x))*/
+block([ans1 : makelist(trigreduce(atan2(cos(%pi*k/8),-sin(%pi*k/8))),k,-16,16),
+ ans2 : block([zzz : atan2(cos(x),-sin(x))], makelist(subst(x = %pi*k/8, zzz),k,-16,16))],
+ every(lambda([q],is(q=0)), trigsimp(ans1 - ans2)));
+true$
+
+/* test identity atan2(-sin(x), -cos(x))*/
+block([ans1 : makelist(trigreduce(atan2(-sin(%pi*k/8),-cos(%pi*k/8))),k,-16,16),
+ ans2 : block([zzz : atan2(-sin(x),-cos(x))], makelist(subst(x = %pi*k/8, zzz),k,-16,16))],
+ every(lambda([q],is(q=0)), trigsimp(ans1 - ans2)));
+true$
+
+integrate(atan2(sin(x),cos(x)),x,0,9*%pi);
+%pi^2/2$
+
+/* Directional limits near branch cuts */
+limit(atan2(epsilon, -1), epsilon, 0, plus);
+%pi$
+
+limit(atan2(epsilon, -1), epsilon, 0, minus);
+-%pi$
+
+limit(atan2(-1, epsilon), epsilon, 0, plus);
+-%pi/2$
+
+limit(atan2(-1, epsilon), epsilon, 0, minus);
+-%pi/2$
+
+atan2(1.0, 0.0);
+1.5707963267948966$
+
+atan2(inf, 1);
+%pi/2$
+
+atan2(-inf, 1);
+-%pi/2$
+
+atan2(1, inf);
+0$
+
+atan2(1, -inf);
+%pi$
+
+atan2(inf, inf);
+atan2(inf,inf)$
+
+atan2(-inf, -inf);
+atan2(-inf,-inf)$
+
+atan2(1.0e-100, -1);
+3.141592653589793$
+
+atan2(-1.0e-100, -1);
+-3.141592653589793$
+
+atan2(1, -1.0e-100);
+1.5707963267948966$
+
+atan2(-1, -1e-100);
+ -1.5707963267948966$
+
+atan2(1e-100, 1e-100);
+0.7853981633974483$
+
+atan2(-1e-100, -1e-100);
+-2.356194490192345$
+
+atan2(1, -0.0);
+1.5707963267948966$
+
+atan2(-1, -0.0);
+- 1.5707963267948966$
+
+block([ans],
+ assume(equal(x,0)),
+ ans : errcatch(atan2(x,x)),
+ forget(equal(x,0)),
+ ans);
+[]$
+
+block([ans],
+ assume(x > 0),
+ ans : atan2(x,x),
+ forget(x > 0),
+ ans);
+%pi/4$
+
+block([ans],
+ assume(x < 0),
+ ans : atan2(x,x),
+ forget(x < 0),
+ ans);
+-3*%pi/4$
+
+/* #4615 carg range is not in (-%pi, %pi] */
+block([c:3*(cos(5*%pi/13)+%i*sin(5*%pi/13)), d:4*(cos(7*%pi/13)+%i*sin(7*%pi/13))],
+ carg(c/d));
+-2*%pi/13$
+
+/* #4609 atan2(inf,inf) -> 0*/
+block([ans : atan2(inf,inf)],
+ [inpart(ans,0), args(ans)]);
+[atan2, [inf, inf]]$
+
+/* #3750 Quoting atan2 inhibits simplification*/
+'atan2(9,0);
+%pi/2$
+
+/* #3127 incorrect integral of expression containing atan2*/
+integrate(sin(t)*atan2(2*sin(t),1-2*cos(t)),t,0,%pi);
+%pi/4$
+
+/* #4613 integrate(atan2(sin(x), cos(x)), x, 0, 9*%pi);*/
+integrate(atan2(sin(x), cos(x)), x, 0, 9*%pi);
+%pi^2/2$
+
+(kill(values),0);
+0$
+
+facts();
+[]$
+
+(reset(trigsign),0);
+0$
\ No newline at end of file
-----------------------------------------------------------------------
Summary of changes:
src/comm2.lisp | 188 ++++++++++++++++++++++++++++++-------
src/init-cl.lisp | 1 +
src/testsuite.lisp | 3 +-
tests/rtest15.mac | 6 +-
tests/rtest_atan2.mac | 254 ++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 415 insertions(+), 37 deletions(-)
create mode 100644 tests/rtest_atan2.mac
hooks/post-receive
--
Maxima CAS
|