[git] CMU Common Lisp branch master updated. snapshot201312a28gbf11273
Raymond Toy
rtoy at commonlisp.net
Sat Dec 21 06:42:10 UTC 2013
This is an automated email from the git hooks/postreceive script. It was
generated because a ref change was pushed to the repository containing
the project "CMU Common Lisp".
The branch, master has been updated
via bf1127321b08ef7e02eb7159f194c054078b95f2 (commit)
via 196e1482e0563250b4ca257a2a119dbe09e6b0a3 (commit)
from b71b7c854469191e462162c9d11d0c35222a284a (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 bf1127321b08ef7e02eb7159f194c054078b95f2
Author: Raymond Toy <toy.raymond at gmail.com>
Date: Fri Dec 20 22:41:59 2013 0800
Document the value of atan better. The CLHS is confusing.
Clean up comments for asin too.
diff git a/src/tests/trig.lisp b/src/tests/trig.lisp
index 78e643d..011aeaf 100644
 a/src/tests/trig.lisp
+++ b/src/tests/trig.lisp
@@ 482,14 +482,16 @@
(complex 0 z)))
;; asin(x) = i*log(i*x + sqrt(1x^2))
(defun asindef (z)
 ( (i*z (log (+ (i*z z)
 (sqrt (1z (* z z))))))))

;; asin branch cut is the real axis x > 1. For x < 1, it is
+;;
+;; The branch cut is the real axis x > 1. For x < 1, it is
;; continuous with quadrant II; for x > 1, continuous with quadrant
;; IV.
;;
+(defun asindef (z)
+ ( (i*z (log (+ (i*z z)
+ (sqrt (1z (* z z))))))))
+
+
(definetest branchcut.asin
(:tag :asin :branchcuts)
;; Test for x < 1, which is continuous with Quadrant II. Compute
@@ 566,6 +568,33 @@
;; atan(z) = (log(1+i*z)  log(1i*z))/(2*i)
;; = i/2*(log(1+i*z)  log(1i*z))
;;
+;; WARNING: The CLHS is a bit confused here. Two definitions of atan
+;; are given in the CLHS
+;; http://www.lispworks.com/documentation/HyperSpec/Body/f_asin_.htm
+;; and they are not consistent. Plus, there is a typo in the second
+;; definition. (Missing parens.)
+;;
+;; For clarification, we turn to
+;; http://www.lispworks.com/documentation/HyperSpec/Issues/iss069_w.htm,
+;; which recommends using the second formula and also puts in the
+;; parentheses in the correct places.
+;;
+;; BUT, this is further confused by the example that atan(0+2*i) is
+;; 1.570.549*i for the proposed formula but 1.57+0.549*i under the
+;; current formula.
+;;
+;;
+;; I think the inconsistency is that the results are derived without
+;; signed zeroes. But we have signed zeroes, so let us derive the
+;; actual value of atan(0+2*i) using the (second) formula.
+;;
+;; atan(0+2*i) = (log(1+i*(0+2*i))  log(1i*(0+2*i)))/(2*i)
+;; = (log(1+(2+0*i))  log(1(2+0*i)))/(2*i)
+;; = (log(10*i)  log(30*i))/(2*i)
+;; = ((log(1)  pi*i)  (log(3)  0*i))/(2*i)
+;; = (log(3)  pi*i)/(2*i)
+;; = pi/2 + log(3)/2*i
+;;
;; The branch cut is the imaginary axis, y > 1. For y < 1, atan is
;; continuous with Quadrant IV; for y > 1, Quadrant II.
(defun atandef (z)
commit 196e1482e0563250b4ca257a2a119dbe09e6b0a3
Author: Raymond Toy <toy.raymond at gmail.com>
Date: Fri Dec 20 22:16:27 2013 0800
Add tests for branch cuts.
diff git a/src/tests/trig.lisp b/src/tests/trig.lisp
index 58d5440..78e643d 100644
 a/src/tests/trig.lisp
+++ b/src/tests/trig.lisp
@@ 228,6 +228,8 @@
t
err)))
+
+;;; Tests for doubledoublefloats
(definetest ddsin.signedzeroes
"Test sin for 0w0 and 0w0"
(:tag :sin :doubledouble :signedzeroes)
@@ 431,3 +433,169 @@
(asserteql nil
(ddsincostest (scalefloat 1w0 1023) 1000)))
+
+;;; Tests for branch cuts.
+
+
+;; Compute fun(arg) and check that the signs of the real and imaginary
+;; parts match the value of realsign and imagsign, respectively.
+;; Return T if the signs match.
+(defun checksigns (fun arg realsign imagsign)
+ (let* ((z (funcall fun arg))
+ (x (realpart z))
+ (y (imagpart z)))
+ (cond ((and (= (floatsign x) realsign)
+ (= (floatsign y) imagsign))
+ t)
+ (t
+ (format t "Sign of result doesn't match expected signs~%~
+ ~& fun = ~A~
+ ~& arg = ~A~
+ ~& res = ~A~
+ ~& expected = ~A ~A~%"
+ fun arg z realsign imagsign)
+ nil))))
+
+;; Return the signs of the real and imaginary parts of z.
+(defun getsigns (z)
+ (values (floatsign (realpart z))
+ (floatsign (imagpart z))))
+
+;; Carefully compute 1z. For z = x + i*y, we want 1x  i*y, which
+;; only really matters when y is a signed zero.
+(defun 1z (z)
+ (if (complexp z)
+ (complex ( 1 (realpart z)) ( (imagpart z)))
+ ( 1 z)))
+
+;; Carefully compute 1+z. For z = x + i*y, we want 1+x + i*y, which
+;; only really matters when y is a signed zero.
+(defun 1+z (z)
+ (if (complexp z)
+ (complex (+ 1 (realpart z)) (imagpart z))
+ (+ 1 z)))
+
+;; Carefully compute i*z = i*(x+i*y) = y + i*x.
+(defun i*z (z)
+ (if (complexp z)
+ (complex ( (imagpart z)) (realpart z))
+ (complex 0 z)))
+
+;; asin(x) = i*log(i*x + sqrt(1x^2))
+(defun asindef (z)
+ ( (i*z (log (+ (i*z z)
+ (sqrt (1z (* z z))))))))
+
+;; asin branch cut is the real axis x > 1. For x < 1, it is
+;; continuous with quadrant II; for x > 1, continuous with quadrant
+;; IV.
+;;
+(definetest branchcut.asin
+ (:tag :asin :branchcuts)
+ ;; Test for x < 1, which is continuous with Quadrant II. Compute
+ ;; the value at #c(2d0 1d10) and check that components of
+ ;; asin(2+0.0*i) have the same signs as the reference value.
+ (multiplevaluebind (tr ti)
+ (getsigns (asindef #c(2d0 1d20)))
+ (asserttrue (checksigns #'asin 2d0 tr ti))
+ (asserttrue (checksigns #'asin 2w0 tr ti))
+ (asserttrue (checksigns #'asin #c(2d0 0) tr ti))
+ (asserttrue (checksigns #'asin #c(2w0 0) tr ti)))
+ ;; Test the other side of the branch cut for x < 1.
+ (multiplevaluebind (tr ti)
+ (getsigns (asindef #c(2d0 1d20)))
+ (asserttrue (checksigns #'asin #c(2d0 0d0) tr ti))
+ (asserttrue (checksigns #'asin #c(2w0 0w0) tr ti)))
+
+ ;; Test for x > 1, which is continuous with Quadrant IV, using the
+ ;; value at #c(+2d0 1d10) as the reference
+ (multiplevaluebind (tr ti)
+ (getsigns (asindef #c(2d0 1d20)))
+ (asserttrue (checksigns #'asin #c(2d0 0) tr ti))
+ (asserttrue (checksigns #'asin #c(2w0 0) tr ti)))
+ ;; Test the other side of the branch cut for x > 1.
+ (multiplevaluebind (tr ti)
+ (getsigns (asindef #c(2d0 1d20)))
+ (asserttrue (checksigns #'asin 2d0 tr ti))
+ (asserttrue (checksigns #'asin 2w0 tr ti))
+ (asserttrue (checksigns #'asin #c(2d0 0d0) tr ti))
+ (asserttrue (checksigns #'asin #c(2w0 0w0) tr ti))))
+
+;; acos(z) = pi/2  asin(z).
+;;
+;; The branch cut is the real axis for x > 1. For x < 1, it is
+;; continous with Quadrant II; for x > 1, Quadrant IV.
+(defun acosdef (z)
+ (if (typep z 'kernel:doubledoublefloat)
+ ( (/ kernel:ddpi 2)
+ (asindef z))
+ ( (/ pi 2)
+ (asindef z))))
+
+(definetest branchcut.acos
+ (:tag :acos :branchcuts)
+ ;; Test for x < 1, which is continuous with Quadrant II. Compute
+ ;; the value at #c(2d0 1d10) and check that components of
+ ;; acos(2+0.0*i) have the same signs as the reference value.
+ (multiplevaluebind (tr ti)
+ (getsigns (acosdef #c(2d0 1d20)))
+ (asserttrue (checksigns #'acos 2d0 tr ti))
+ (asserttrue (checksigns #'acos 2w0 tr ti))
+ (asserttrue (checksigns #'acos #c(2d0 0) tr ti))
+ (asserttrue (checksigns #'acos #c(2w0 0) tr ti)))
+ ;; Test the other side of the branch cut for x < 1.
+ (multiplevaluebind (tr ti)
+ (getsigns (acosdef #c(2d0 1d20)))
+ (asserttrue (checksigns #'acos #c(2d0 0d0) tr ti))
+ (asserttrue (checksigns #'acos #c(2w0 0w0) tr ti)))
+
+ ;; Test for x > 1, which is continuous with Quadrant IV, using the
+ ;; value at #c(+2d0 1d10) as the reference
+ (multiplevaluebind (tr ti)
+ (getsigns (acosdef #c(2d0 1d20)))
+ (asserttrue (checksigns #'acos #c(2d0 0) tr ti))
+ (asserttrue (checksigns #'acos #c(2w0 0) tr ti)))
+ ;; Test the other side of the branch cut for x > 1.
+ (multiplevaluebind (tr ti)
+ (getsigns (acosdef #c(2d0 1d20)))
+ (asserttrue (checksigns #'acos 2d0 tr ti))
+ (asserttrue (checksigns #'acos 2w0 tr ti))
+ (asserttrue (checksigns #'acos #c(2d0 0d0) tr ti))
+ (asserttrue (checksigns #'acos #c(2w0 0w0) tr ti))))
+
+;; atan(z) = (log(1+i*z)  log(1i*z))/(2*i)
+;; = i/2*(log(1+i*z)  log(1i*z))
+;;
+;; The branch cut is the imaginary axis, y > 1. For y < 1, atan is
+;; continuous with Quadrant IV; for y > 1, Quadrant II.
+(defun atandef (z)
+ (let* ((iz (i*z z))
+ (w ( (log (1+z iz))
+ (log (1z iz)))))
+ (* 1/2 (i*z w))))
+
+(definetest branchcut.atan
+ (:tag :atan :branchcuts)
+ ;; Test for y < 1, which is continuous with Quadrant IV. Use the
+ ;; value at #c(1d20 2d0) as the reference.
+ (multiplevaluebind (tr ti)
+ (getsigns (atandef #c(1d20 2d0)))
+ (asserttrue (checksigns #'atan #c(0d0 2d0) tr ti))
+ (asserttrue (checksigns #'atan #c(0w0 2w0) tr ti)))
+ ;; Test the other side of the branch cut for x < 1.
+ (multiplevaluebind (tr ti)
+ (getsigns (atandef #c(1d20 2d0)))
+ (asserttrue (checksigns #'atan #c(0d0 2d0) tr ti))
+ (asserttrue (checksigns #'atan #c(0w0 2w0) tr ti)))
+
+ ;; Test for y > 1, which is continuous with Quadrant II, using the
+ ;; value at #c(1d20 +2d0) as the reference
+ (multiplevaluebind (tr ti)
+ (getsigns (atandef #c(1d20 2d0)))
+ (asserttrue (checksigns #'atan #c(0d0 2d0) tr ti))
+ (asserttrue (checksigns #'atan #c(0w0 2w0) tr ti)))
+ ;; Test the other side of the branch cut for x > 1.
+ (multiplevaluebind (tr ti)
+ (getsigns (atandef #c(1d20 2d0)))
+ (asserttrue (checksigns #'atan #c(0d0 2d0) tr ti))
+ (asserttrue (checksigns #'atan #c(0d0 2w0) tr ti))))

Summary of changes:
src/tests/trig.lisp  197 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 197 insertions(+)
hooks/postreceive

CMU Common Lisp
More information about the cmuclcvs
mailing list