[oct-cvs] Oct commit: oct qd-fun.lisp qd-rep.lisp qd.lisp

rtoy rtoy at common-lisp.net
Wed Nov 7 03:45:41 UTC 2007


Update of /project/oct/cvsroot/oct
In directory clnet:/tmp/cvs-serv16164

Modified Files:
      Tag: THREE-ARG-BRANCH
	qd-fun.lisp qd-rep.lisp qd.lisp 
Log Message:
qd-rep.lisp:
o Fix typo in compiler macro for sub-d-qd

qd.lisp:
o Use 3-arg versions in div-qd-t to speed things up.  Approximately
  doubles the speed with clisp.

qd-fun.lisp:
o Use 3-arg versions in sqrt-qd to speed things up.  Approximately
  doubles the speed with clisp.


--- /project/oct/cvsroot/oct/qd-fun.lisp	2007/10/18 14:38:56	1.90
+++ /project/oct/cvsroot/oct/qd-fun.lisp	2007/11/07 03:45:41	1.90.2.1
@@ -47,6 +47,7 @@
 
 #+cmu
 (declaim (ext:maybe-inline sqrt-qd))
+#+nil
 (defun sqrt-qd (a)
   "Square root of the (non-negative) quad-float"
   (declare (type %quad-double a)
@@ -79,6 +80,47 @@
 	(setf r (add-qd r (mul-qd r (sub-d-qd half (mul-qd h (sqr-qd r)))))))
       (scale-float-qd (mul-qd r new-a) (ash k -1)))))
 
+(defun sqrt-qd (a)
+  "Square root of the (non-negative) quad-float"
+  (declare (type %quad-double a)
+	   (optimize (speed 3) (space 0)))
+  ;; Perform the following Newton iteration:
+  ;;
+  ;;  x' = x + (1 - a * x^2) * x / 2
+  ;;
+  ;; which converges to 1/sqrt(a).
+  ;;
+  ;; However, there appear to be round-off errors when x is either
+  ;; very large or very small.  So let x = f*2^(2*k).  Then sqrt(x) =
+  ;; 2^k*sqrt(f), and sqrt(f) doesn't have round-off problems.
+  (when (zerop-qd a)
+    (return-from sqrt-qd a))
+  (when (float-infinity-p (qd-0 a))
+    (return-from sqrt-qd a))
+
+  (let* ((k (logandc2 (logb-finite (qd-0 a)) 1))
+	 (new-a (scale-float-qd a (- k))))
+    (assert (evenp k))
+    (let* ((r (make-qd-d (cl:/ (sqrt (the (double-float (0d0))
+				       (qd-0 new-a))))))
+	   (temp (%make-qd-d 0d0 0d0 0d0 0d0))
+	   (half 0.5d0)
+	   (h (mul-qd-d new-a half)))
+      (declare (type %quad-double r))
+      ;; Since we start with double-float precision, three more
+      ;; iterations should give us full accuracy.
+      (dotimes (k 3)
+	#+nil
+	(setf r (add-qd r (mul-qd r (sub-d-qd half (mul-qd h (sqr-qd r))))))
+	(sqr-qd r temp)
+	(mul-qd h temp temp)
+	(sub-d-qd half temp temp)
+	(mul-qd r temp temp)
+	(add-qd r temp r)
+	)
+      (mul-qd r new-a r)
+      (scale-float-qd r (ash k -1)))))
+
 (defun hypot-aux-qd (x y)
   (declare (type %quad-double x y))
   (let ((k (- (logb-finite (max (cl:abs (qd-0 x))
--- /project/oct/cvsroot/oct/qd-rep.lisp	2007/11/07 03:08:26	1.10.2.5
+++ /project/oct/cvsroot/oct/qd-rep.lisp	2007/11/07 03:45:41	1.10.2.6
@@ -299,7 +299,7 @@
 
 #-cmu
 (define-compiler-macro sub-d-qd (a b &optional (c #-cmu (%make-qd-d 0d0 0d0 0d0 0d0)))
-  `(add-d-qd a (neg-qd ,b) ,c))
+  `(add-d-qd ,a (neg-qd ,b) ,c))
 
 #+cmu
 (define-compiler-macro neg-qd (a &optional c)
--- /project/oct/cvsroot/oct/qd.lisp	2007/11/07 03:08:26	1.60.2.6
+++ /project/oct/cvsroot/oct/qd.lisp	2007/11/07 03:45:41	1.60.2.7
@@ -863,6 +863,7 @@
 (defun div-qd (a b &optional (target #-cmu (%make-qd-d 0d0 0d0 0d0 0d0)))
   (div-qd-t a b target))
 
+#+nil
 (defun div-qd-t (a b target)
   (declare (type %quad-double a b)
 	   (optimize (speed 3)
@@ -886,6 +887,33 @@
 	      (renorm-4 q0 q1 q2 q3)
 	    (%store-qd-d target q0 q1 q2 q3)))))))
 
+(defun div-qd-t (a b target)
+  (declare (type %quad-double a b)
+	   (optimize (speed 3)
+		     (space 0))
+	   (inline float-infinity-p)
+	   #+cmu
+	   (ignore target))
+  (let ((a0 (qd-0 a))
+	(b0 (qd-0 b)))
+    (let* ((q0 (cl:/ a0 b0))
+	   (r (%make-qd-d 0d0 0d0 0d0 0d0)))
+      (mul-qd-d b q0 r)
+      (sub-qd a r r)
+      (let* ((q1 (cl:/ (qd-0 r) b0))
+	     (temp (mul-qd-d b q1)))
+	(when (float-infinity-p q0)
+	  (return-from div-qd-t (%store-qd-d target q0 0d0 0d0 0d0)))
+	
+	(sub-qd r temp r)
+	(let ((q2 (cl:/ (qd-0 r) b0)))
+	  (mul-qd-d b q2 temp)
+	  (sub-qd r temp r)
+	  (let ((q3 (cl:/ (qd-0 r) b0)))
+	    (multiple-value-bind (q0 q1 q2 q3)
+		(renorm-4 q0 q1 q2 q3)
+	      (%store-qd-d target q0 q1 q2 q3))))))))
+
 (declaim (inline invert-qd))
 
 (defun invert-qd (v)




More information about the oct-cvs mailing list