Update of /project/oct/cvsroot/oct
In directory clnet:/tmp/cvs-serv8050
Modified Files:
qd-dd.lisp qd-package.lisp qd.lisp
Log Message:
Make TWO-SUM a macro, just like we did for QUICK-TWO-SUM.
All RT tests pass on CMUCL and Allegro.
qd-package.lisp:
o Don't import C::TWO-SUM anymore.
qd-dd.lisp:
o Make TWO-SUM a macro.
qd.lisp
o Add TWO-SUM macro for CMUCL (which just calls C::TWO-SUM).
o Update all uses of TWO-SUM to use the macro appropriately.
--- /project/oct/cvsroot/oct/qd-dd.lisp 2007/09/16 02:46:24 1.9
+++ /project/oct/cvsroot/oct/qd-dd.lisp 2007/09/16 05:04:04 1.10
@@ -52,6 +52,7 @@
(setf ,s (+ ,a ,b))
(setf ,e (- ,b (- ,s ,a))))))
+#||
(declaim (inline two-sum))
(defun two-sum (a b)
"Computes fl(a+b) and err(a+b)"
@@ -63,21 +64,21 @@
(- b v))))
(declare (double-float s v e))
(values s e)))
+||#
-#+nil
(defmacro two-sum (s e x y)
"Computes fl(a+b) and err(a+b)"
(let ((a (gensym))
(b (gensym))
- (v (gensym))
+ (v (gensym)))
`(let ((,a ,x)
(,b ,y))
(declare (double-float ,a ,b))
(setf ,s (+ ,a ,b))
(let ((,v (- ,s ,a)))
- (declare (double-float v))
- (setf e (+ (- ,a (- ,s ,v))
- (- ,b ,v))))))))
+ (declare (double-float ,v))
+ (setf ,e (+ (- ,a (- ,s ,v))
+ (- ,b ,v)))))))
(declaim (inline two-prod))
(declaim (inline split))
--- /project/oct/cvsroot/oct/qd-package.lisp 2007/09/16 02:46:24 1.38
+++ /project/oct/cvsroot/oct/qd-package.lisp 2007/09/16 05:04:05 1.39
@@ -97,7 +97,6 @@
#:make-qd-dd)
#+cmu
(:import-from #:c
- #:two-sum
#:two-prod
#:two-sqr))
--- /project/oct/cvsroot/oct/qd.lisp 2007/09/16 02:46:24 1.47
+++ /project/oct/cvsroot/oct/qd.lisp 2007/09/16 05:04:05 1.48
@@ -46,6 +46,14 @@
(declaim (inline three-sum three-sum2))
;; Internal routines for implementing quad-double.
+
+#+cmu
+(defmacro two-sum (s e x y)
+ `(multiple-value-setq (,s ,e)
+ (c::two-sum ,x ,y)))
+
+
+#+nil
(defun three-sum (a b c)
(declare (double-float a b c)
(optimize (speed 3)))
@@ -57,6 +65,19 @@
(two-sum t2 t3)
(values a b c)))))
+(defun three-sum (a b c)
+ (declare (double-float a b c)
+ (optimize (speed 3)))
+ (let* ((t1 0d0)
+ (t2 t1)
+ (t3 t1))
+ (declare (double-float t1 t2 t3))
+ (two-sum t1 t2 a b)
+ (two-sum a t3 c t1)
+ (two-sum b c t2 t3)
+ (values a b c)))
+
+#+nil
(defun three-sum2 (a b c)
(declare (double-float a b c)
(optimize (speed 3)))
@@ -66,6 +87,17 @@
(two-sum c t1)
(values a (cl:+ t2 t3) c))))
+(defun three-sum2 (a b c)
+ (declare (double-float a b c)
+ (optimize (speed 3)))
+ (let* ((t1 0d0)
+ (t2 t1)
+ (t3 t1))
+ (two-sum t1 t2 a b)
+ (two-sum a t3 c t1)
+ (values a (cl:+ t2 t3) c)))
+
+
;; Not needed????
#+nil
(declaim (inline quick-three-accum))
@@ -137,11 +169,6 @@
`(multiple-value-setq (,s ,e)
(c::quick-two-sum ,x ,y)))
-#+(and nil cmu)
-(defmacro two-sum (s e x y)
- `(multiple-value-setq (s e)
- (c::two-sum x y)))
-
#-(or qd-inline (not cmu))
(declaim (ext:start-block renorm-4 renorm-5
make-qd-d
@@ -267,22 +294,24 @@
(double-float b)
(optimize (speed 3)
(space 0)))
- (multiple-value-bind (c0 e)
- (two-sum (qd-0 a) b)
+ (let* ((c0 0d0)
+ (e c0)
+ (c1 c0)
+ (c2 c0)
+ (c3 c0))
+ (declare (double-float e c0 c1 c2 c3))
+ (two-sum c0 e (qd-0 a) b)
#+cmu
(when (float-infinity-p c0)
(return-from add-qd-d (%make-qd-d c0 0d0 0d0 0d0)))
- (multiple-value-bind (c1 e)
- (two-sum (qd-1 a) e)
- (multiple-value-bind (c2 e)
- (two-sum (qd-2 a) e)
- (multiple-value-bind (c3 e)
- (two-sum (qd-3 a) e)
- (multiple-value-bind (r0 r1 r2 r3)
- (renorm-5 c0 c1 c2 c3 e)
- (if (and (zerop (qd-0 a)) (zerop b))
- (%make-qd-d c0 0d0 0d0 0d0)
- (%make-qd-d r0 r1 r2 r3))))))))
+ (two-sum c1 e (qd-1 a) e)
+ (two-sum c2 e (qd-2 a) e)
+ (two-sum c3 e (qd-3 a) e)
+ (multiple-value-bind (r0 r1 r2 r3)
+ (renorm-5 c0 c1 c2 c3 e)
+ (if (and (zerop (qd-0 a)) (zerop b))
+ (%make-qd-d c0 0d0 0d0 0d0)
+ (%make-qd-d r0 r1 r2 r3)))))
(defun add-d-qd (a b)
(declare (double-float a)
@@ -297,19 +326,21 @@
(double-double-float b)
(optimize (speed 3)
(space 0)))
- (multiple-value-bind (s0 t0)
- (two-sum (qd-0 a) (kernel:double-double-hi b))
- (multiple-value-bind (s1 t1)
- (two-sum (qd-1 a) (kernel:double-double-lo b))
- (multiple-value-bind (s1 t0)
- (two-sum s1 t0)
- (multiple-value-bind (s2 t0 t1)
- (three-sum (qd-2 a) t0 t1)
- (multiple-value-bind (s3 t0)
- (two-sum t0 (qd-3 a))
- (let ((t0 (cl:+ t0 t1)))
- (multiple-value-call #'%make-qd-d
- (renorm-5 s0 s1 s2 s3 t0)))))))))
+ (let* ((s0 0d0)
+ (t0 s0)
+ (s1 s0)
+ (t1 s0)
+ (s3 s0))
+ (declare (double-float s0 s1 s3 t0 t1))
+ (two-sum s0 t1 (qd-0 a) (kernel:double-double-hi b))
+ (two-sum s1 t1 (qd-1 a) (kernel:double-double-lo b))
+ (two-sum s1 t0 s1 t0)
+ (multiple-value-bind (s2 t0 t1)
+ (three-sum (qd-2 a) t0 t1)
+ (two-sum s3 t0 t0 (qd-3 a))
+ (let ((t0 (cl:+ t0 t1)))
+ (multiple-value-call #'%make-qd-d
+ (renorm-5 s0 s1 s2 s3 t0))))))
#+cmu
(defun add-dd-qd (a b)
@@ -386,20 +417,19 @@
(t1 (cl:+ w1 u1))
(t2 (cl:+ w2 u2))
(t3 (cl:+ w3 u3)))
- (multiple-value-bind (s1 t0)
- (two-sum s1 t0)
- (multiple-value-bind (s2 t0 t1)
- (three-sum s2 t0 t1)
- (multiple-value-bind (s3 t0)
- (three-sum2 s3 t0 t2)
- (declare (double-float t0))
- (setf t0 (cl:+ t0 t1 t3))
- ;; Renormalize
- (multiple-value-setq (s0 s1 s2 s3)
- (renorm-5 s0 s1 s2 s3 t0))
- (if (and (zerop a0) (zerop b0))
- (%make-qd-d (+ a0 b0) 0d0 0d0 0d0)
- (%make-qd-d s0 s1 s2 s3))))))))))))))
+ (two-sum s1 t0 s1 t0)
+ (multiple-value-bind (s2 t0 t1)
+ (three-sum s2 t0 t1)
+ (multiple-value-bind (s3 t0)
+ (three-sum2 s3 t0 t2)
+ (declare (double-float t0))
+ (setf t0 (cl:+ t0 t1 t3))
+ ;; Renormalize
+ (multiple-value-setq (s0 s1 s2 s3)
+ (renorm-5 s0 s1 s2 s3 t0))
+ (if (and (zerop a0) (zerop b0))
+ (%make-qd-d (+ a0 b0) 0d0 0d0 0d0)
+ (%make-qd-d s0 s1 s2 s3)))))))))))))
(defun neg-qd (a)
(declare (type %quad-double a))
@@ -451,50 +481,23 @@
(two-prod (qd-1 a) b)
(multiple-value-bind (p2 q2)
(two-prod (qd-2 a) b)
- (let ((p3 (cl:* (qd-3 a) b))
- (s0 p0))
- #+nil
- (format t "q0 p1 = ~A ~A~%" q0 p1)
- (multiple-value-bind (s1 s2)
- (two-sum q0 p1)
- #+nil
- (format t "s1 s2 = ~A ~A~%" s1 s2)
- #+nil
- (format t "s2 q1 p2 = ~A ~A ~A~%"
- s2 q1 p2)
- (multiple-value-bind (s2 q1 p2)
- (three-sum s2 q1 p2)
- #+nil
- (format t "s2,q1,p2 = ~A ~A ~A~%"
- s2 q1 p2)
- #+nil
- (format t "q1 q2 p3 = ~A ~A ~A~%"
- q1 q2 p3)
- (multiple-value-bind (q1 q2)
- (three-sum2 q1 q2 p3)
- #+nil
- (format t "q1 q2, p3 = ~A ~A ~A~%" q1 q2 p3)
- (let ((s3 q1)
- (s4 (cl:+ q2 p2)))
- #+nil
- (progn
- (format t "~a~%" s0)
- (format t "~a~%" s1)
- (format t "~a~%" s2)
- (format t "~a~%" s3)
- (format t "~a~%" s4))
- (multiple-value-bind (s0 s1 s2 s3)
- (renorm-5 s0 s1 s2 s3 s4)
- #+nil
- (progn
- (format t "~a~%" s0)
- (format t "~a~%" s1)
- (format t "~a~%" s2)
- (format t "~a~%" s3)
- (format t "~a~%" s4))
- (if (zerop s0)
- (%make-qd-d (float-sign p0 0d0) 0d0 0d0 0d0)
- (%make-qd-d s0 s1 s2 s3))))))))))))
+ (let* ((p3 (cl:* (qd-3 a) b))
+ (s0 p0)
+ (s1 p0)
+ (s2 p0))
+ (declare (double-float s0 s1 s2 p3))
+ (two-sum s1 s2 q0 p1)
+ (multiple-value-bind (s2 q1 p2)
+ (three-sum s2 q1 p2)
+ (multiple-value-bind (q1 q2)
+ (three-sum2 q1 q2 p3)
+ (let ((s3 q1)
+ (s4 (cl:+ q2 p2)))
+ (multiple-value-bind (s0 s1 s2 s3)
+ (renorm-5 s0 s1 s2 s3 s4)
+ (if (zerop s0)
+ (%make-qd-d (float-sign p0 0d0) 0d0 0d0 0d0)
+ (%make-qd-d s0 s1 s2 s3)))))))))))
;; a0 * b0 0
;; a0 * b1 1
@@ -617,34 +620,35 @@
(multiple-value-setq (p3 p4 p5)
(three-sum p3 p4 p5))
;; Compute (s0,s1,s2) = (p2,q1,q2) + (p3,p4,p5)
- (multiple-value-bind (s0 t0)
- (two-sum p2 p3)
- (multiple-value-bind (s1 t1)
- (two-sum q1 p4)
- (let ((s2 (cl:+ q2 p5)))
- (declare (double-float s2))
- (multiple-value-bind (s1 t0)
- (two-sum s1 t0)
- (declare (double-float s1))
- (incf s2 (cl:+ t0 t1))
- ;; O(eps^3) order terms. This is the sloppy
- ;; multiplication version. Should we use
- ;; the precise version? It's significantly
- ;; more complex.
+ (let* ((s0 0d0)
+ (s1 s0)
+ (t0 s0)
+ (t1 s0))
+ (declare (double-float s0 s1 t0 t1))
+ (two-sum s0 t0 p2 p3)
+ (two-sum s1 t1 q1 p4)
+ (let ((s2 (cl:+ q2 p5)))
+ (declare (double-float s2))
+ (two-sum s1 t0 s1 t0)
+ (incf s2 (cl:+ t0 t1))
+ ;; O(eps^3) order terms. This is the sloppy
+ ;; multiplication version. Should we use
+ ;; the precise version? It's significantly
+ ;; more complex.
- (incf s1 (cl:+ (cl:* a0 b3)
- (cl:* a1 b2)
- (cl:* a2 b1)
- (cl:* a3 b0)
- q0 q3 q4 q5))
- #+nil
- (format t "p0,p1,s0,s1,s2 = ~a ~a ~a ~a ~a~%"
- p0 p1 s0 s1 s2)
- (multiple-value-bind (r0 r1 s0 s1)
- (renorm-5 p0 p1 s0 s1 s2)
- (if (zerop r0)
- (%make-qd-d p0 0d0 0d0 0d0)
- (%make-qd-d r0 r1 s0 s1))))))))))))))))
+ (incf s1 (cl:+ (cl:* a0 b3)
+ (cl:* a1 b2)
+ (cl:* a2 b1)
+ (cl:* a3 b0)
+ q0 q3 q4 q5))
+ #+nil
+ (format t "p0,p1,s0,s1,s2 = ~a ~a ~a ~a ~a~%"
+ p0 p1 s0 s1 s2)
+ (multiple-value-bind (r0 r1 s0 s1)
+ (renorm-5 p0 p1 s0 s1 s2)
+ (if (zerop r0)
+ (%make-qd-d p0 0d0 0d0 0d0)
+ (%make-qd-d r0 r1 s0 s1))))))))))))))
;; This is the non-sloppy version. I think this works just fine, but
;; since qd defaults to the sloppy multiplication version, we do the
@@ -760,45 +764,37 @@
(two-prod (cl:* 2 (qd-0 a)) (qd-2 a))
(multiple-value-bind (p3 q3)
(two-sqr (qd-1 a))
- (multiple-value-setq (p1 q0)
- (two-sum q0 p1))
- (multiple-value-setq (q0 q1)
- (two-sum q0 q1))
- (multiple-value-setq (p2 p3)
- (two-sum p2 p3))
-
- (multiple-value-bind (s0 t0)
- (two-sum q0 p2)
- (declare (double-float t0))
- (multiple-value-bind (s1 t1)
- (two-sum q1 p3)
- (declare (double-float s1 t1))
- (multiple-value-setq (s1 t0)
- (two-sum s1 t0))
- (incf t0 t1)
- (quick-two-sum s1 t0 s1 t0)
- (quick-two-sum p2 t1 s0 s1)
- (quick-two-sum p3 q0 t1 t0)
-
- (let ((p4 (cl:* 2 (qd-0 a) (qd-3 a)))
- (p5 (cl:* 2 (qd-1 a) (qd-2 a))))
- (declare (double-float p4))
- (multiple-value-setq (p4 p5)
- (two-sum p4 p5))
- (multiple-value-setq (q2 q3)
- (two-sum q2 q3))
-
- (multiple-value-setq (t0 t1)
- (two-sum p4 q2))
-
- (incf t1 (cl:+ p5 q3))
-
- (multiple-value-setq (p3 p4)
- (two-sum p3 t0))
- (incf p4 (cl:+ q0 t1))
+ (two-sum p1 q0 q0 p1)
+ (two-sum q0 q1 q0 q1)
+ (two-sum p2 p3 p2 p3)
+
+ (let* ((s0 0d0)
+ (t0 s0)
+ (s1 s0)
+ (t1 s0))
+ (declare (double-float s0 s1 t0 t1))
+ (two-sum s0 t0 q0 p2)
+ (two-sum s1 t1 q1 p3)
+ (two-sum s1 t0 s1 t0)
+ (incf t0 t1)
+ (quick-two-sum s1 t0 s1 t0)
+ (quick-two-sum p2 t1 s0 s1)
+ (quick-two-sum p3 q0 t1 t0)
+
+ (let ((p4 (cl:* 2 (qd-0 a) (qd-3 a)))
+ (p5 (cl:* 2 (qd-1 a) (qd-2 a))))
+ (declare (double-float p4 p5))
+ (two-sum p4 p5 p4 p5)
+ (two-sum q2 q3 q2 q3)
+ (two-sum t0 t1 p4 q2)
+
+ (incf t1 (cl:+ p5 q3))
- (multiple-value-call #'%make-qd-d
- (renorm-5 p0 p1 p2 p3 p4))))))))))
+ (two-sum p3 p4 p3 t0)
+ (incf p4 (cl:+ q0 t1))
+
+ (multiple-value-call #'%make-qd-d
+ (renorm-5 p0 p1 p2 p3 p4)))))))))
(defun div-qd (a b)