Raymond Toy pushed to branch master at cmucl / cmucl

Commits:

5 changed files:

Changes:

  • src/code/numbers.lisp
    ... ... @@ -602,34 +602,40 @@
    602 602
     ;; In particular iteration 1 and 3 are added.  Iteration 2 and 4 were
    
    603 603
     ;; not added.  The test examples from iteration 2 and 4 didn't change
    
    604 604
     ;; with or without changes added.
    
    605
    -(defconstant +cdiv-rmin+ least-positive-normalized-double-float)
    
    606
    -(defconstant +cdiv-rbig+ (/ most-positive-double-float 2))
    
    607
    -(defconstant +cdiv-rmin2+ (scale-float 1d0 -53))
    
    608
    -(defconstant +cdiv-rminscal+ (scale-float 1d0 51))
    
    609
    -(defconstant +cdiv-rmax2+ (* +cdiv-rbig+ +cdiv-rmin2+))
    
    610
    -;; This is the value of %eps from Scilab
    
    611
    -(defconstant +cdiv-eps+ (scale-float 1d0 -52))
    
    612
    -(defconstant +cdiv-be+ (/ 2 (* +cdiv-eps+ +cdiv-eps+)))
    
    613
    -(defconstant +cdiv-2/eps+ (/ 2 +cdiv-eps+))
    
    614
    -
    
    615
    -;; Make these functions accessible.  cdiv-double-float and
    
    616
    -;; cdiv-single-float are used by deftransforms.  Of course, two-arg-/
    
    617
    -;; is the interface to division.  cdiv-generic isn't used anywhere
    
    618
    -;; else.
    
    619
    -(declaim (ext:start-block cdiv-double-float cdiv-single-float two-arg-/))
    
    620
    -
    
    621
    -(defun cdiv-double-float (x y)
    
    622
    -  "Accurate division of complex double-float numbers x and y."
    
    623
    -  (declare (type (complex double-float) x y)
    
    624
    -	   (optimize (speed 3) (safety 0)))
    
    625
    -  (labels
    
    626
    -      ((internal-compreal (a b c d r tt)
    
    627
    -	 (declare (double-float a b c d r tt))
    
    628
    -	 ;; Compute the real part of the complex division
    
    629
    -	 ;; (a+ib)/(c+id), assuming |c| <= |d|.  r = d/c and tt = 1/(c+d*r).
    
    605
    +;;
    
    606
    +;; Make these functions accessible outside the block compilation.
    
    607
    +;; CDIV-DOUBLE-FLOAT and CDIV-SINGLE-FLOAT are used by deftransforms.
    
    608
    +;; Of course, TWO-ARG-/ is the interface to division.  CDIV-GENERIC
    
    609
    +;; isn't used anywhere else.
    
    610
    +(declaim (ext:start-block cdiv-double-float cdiv-single-float
    
    611
    +			  cdiv-double-double-float
    
    612
    +			  two-arg-/))
    
    613
    +
    
    614
    +;; The code for both the double-float and double-double-float
    
    615
    +;; implementation is basically identical except for the constants.
    
    616
    +;; use a macro to generate both versions.
    
    617
    +(eval-when (:compile-toplevel)
    
    618
    +(defmacro define-cdiv (type &key rmin rbig rmin2 rminscal eps)
    
    619
    +  (let* ((opt '((optimize (speed 3) (safety 0))))
    
    620
    +	 (name (symbolicate "CDIV-" type))
    
    621
    +	 (compreal (symbolicate "CDIV-" type "-INTERNAL-COMPREAL"))
    
    622
    +	 (subinternal (symbolicate "CDIV-" type "-ROBUST-SUBINTERNAL"))
    
    623
    +	 (internal (symbolicate "CDIV-" type "-ROBUST-INTERNAL"))
    
    624
    +	 (docstring (let ((*print-case* :downcase))
    
    625
    +		      (format nil "Accurate division of complex ~A numbers x and y."
    
    626
    +			      type))))
    
    627
    +    `(progn
    
    628
    +       (defun ,compreal (a b c d r tt)
    
    629
    +	 (declare (,type a b c d r tt)
    
    630
    +		  ,@opt)
    
    631
    +	 ;; Computes the real part of the complex division
    
    632
    +	 ;; (a+ib)/(c+id), assuming |d| <= |c|.  Then let r = d/c and
    
    633
    +	 ;; tt = (c+d*r).
    
    630 634
     	 ;;
    
    631 635
     	 ;; The realpart is (a*c+b*d)/(c^2+d^2).
    
    632 636
     	 ;;
    
    637
    +	 ;; The denominator is
    
    638
    +	 ;;
    
    633 639
     	 ;;   c^2+d^2 = c*(c+d*(d/c)) = c*(c+d*r)
    
    634 640
     	 ;;
    
    635 641
     	 ;; Then
    
    ... ... @@ -639,124 +645,174 @@
    639 645
     	 ;;                       = (a + b*r)/(c + d*r).
    
    640 646
     	 ;;
    
    641 647
     	 ;; Thus tt = (c + d*r).
    
    642
    -	 (cond ((>= (abs r) +cdiv-rmin+)
    
    648
    +	 (cond ((>= (abs r) ,rmin)
    
    643 649
     		(let ((br (* b r)))
    
    644 650
     		  (if (/= br 0)
    
    645 651
     		      (/ (+ a br) tt)
    
    646 652
     		      ;; b*r underflows.  Instead, compute
    
    647 653
     		      ;;
    
    648
    -		      ;; (a + b*r)*tt = a*tt + b*tt*r
    
    649
    -		      ;;              = a*tt + (b*tt)*r
    
    650 654
     		      ;; (a + b*r)/tt = a/tt + b/tt*r
    
    651
    -		      ;;              = a*tt + (b*tt)*r
    
    652 655
     		      (+ (/ a tt)
    
    653 656
     			 (* (/ b tt)
    
    654 657
     			    r)))))
    
    655 658
     	       (t
    
    656
    -		;; r = 0 so d is very tiny compared to c.
    
    659
    +		;; r is very small so d is very tiny compared to c.
    
    657 660
     		;;
    
    658 661
     		(/ (+ a (* d (/ b c)))
    
    659 662
     		   tt))))
    
    660
    -       (robust-subinternal (a b c d)
    
    661
    -	 (declare (double-float a b c d))
    
    663
    +       (defun ,subinternal (a b c d)
    
    664
    +	 (declare (,type a b c d)
    
    665
    +		  ,@opt)
    
    662 666
     	 (let* ((r (/ d c))
    
    663 667
     		(tt (+ c (* d r))))
    
    664
    -	   ;; e is the real part and f is the imaginary part.  We
    
    665
    -	   ;; can use internal-compreal for the imaginary part by
    
    666
    -	   ;; noticing that the imaginary part of (a+i*b)/(c+i*d) is
    
    667
    -	   ;; the same as the real part of (b-i*a)/(c+i*d).
    
    668
    -	   (let ((e (internal-compreal a b c d r tt))
    
    669
    -		 (f (internal-compreal b (- a) c d r tt)))
    
    670
    -	     (values e
    
    671
    -		     f))))
    
    672
    -	 
    
    673
    -       (robust-internal (x y)
    
    674
    -	 (declare (type (complex double-float) x y))
    
    675
    -	 (let ((a (realpart x))
    
    676
    -	       (b (imagpart x))
    
    677
    -	       (c (realpart y))
    
    678
    -	       (d (imagpart y)))
    
    679
    -	   (declare (double-float a b c d))
    
    680
    -	   (flet ((maybe-scale (abs-tst a b c d)
    
    681
    -		    (declare (double-float a b c d))
    
    682
    -		    ;; This implements McGehearty's iteration 3 to
    
    683
    -		    ;; handle the case when some values are too big
    
    684
    -		    ;; and should be scaled down.  Also if some
    
    685
    -		    ;; values are too tiny, scale them up.
    
    686
    -		    (let ((abs-a (abs a))
    
    687
    -			  (abs-b (abs b)))
    
    688
    -		      (if (or (> abs-tst +cdiv-rbig+)
    
    689
    -			      (> abs-a +cdiv-rbig+)
    
    690
    -			      (> abs-b +cdiv-rbig+))
    
    691
    -			  (setf a (* a 0.5d0)
    
    692
    -				b (* b 0.5d0)
    
    693
    -				c (* c 0.5d0)
    
    694
    -				d (* d 0.5d0))
    
    695
    -			  (if (< abs-tst +cdiv-rmin2+)
    
    696
    -			      (setf a (* a +cdiv-rminscal+)
    
    697
    -				    b (* b +cdiv-rminscal+)
    
    698
    -				    c (* c +cdiv-rminscal+)
    
    699
    -				    d (* d +cdiv-rminscal+))
    
    700
    -			      (if (or (and (< abs-a +cdiv-rmin+)
    
    701
    -					   (< abs-b +cdiv-rmax2+)
    
    702
    -					   (< abs-tst +cdiv-rmax2+))
    
    703
    -				      (and (< abs-b +cdiv-rmin+)
    
    704
    -					   (< abs-a +cdiv-rmax2+)
    
    705
    -					   (< abs-tst +cdiv-rmax2+)))
    
    706
    -				  (setf a (* a +cdiv-rminscal+)
    
    707
    -					b (* b +cdiv-rminscal+)
    
    708
    -					c (* c +cdiv-rminscal+)
    
    709
    -					d (* d +cdiv-rminscal+)))))
    
    710
    -		      (values a b c d))))
    
    711
    -	     (cond
    
    712
    -	       ((<= (abs d) (abs c))
    
    713
    -		;; |d| <= |c|, so we can use robust-subinternal to
    
    714
    -		;; perform the division.
    
    715
    -		(multiple-value-bind (a b c d)
    
    716
    -		    (maybe-scale (abs c) a b c d)
    
    717
    -		  (multiple-value-bind (e f)
    
    718
    -		      (robust-subinternal a b c d)
    
    719
    -		    (complex e f))))
    
    720
    -	       (t
    
    721
    -		;; |d| > |c|.  So, instead compute
    
    722
    -		;;
    
    723
    -		;;   (b + i*a)/(d + i*c) = ((b*d+a*c) + (a*d-b*c)*i)/(d^2+c^2)
    
    724
    -		;;
    
    725
    -		;; Compare this to (a+i*b)/(c+i*d) and we see that
    
    726
    -		;; realpart of the former is the same, but the
    
    727
    -		;; imagpart of the former is the negative of the
    
    728
    -		;; desired division.
    
    729
    -		(multiple-value-bind (a b c d)
    
    730
    -		    (maybe-scale (abs d) a b c d)
    
    731
    -		  (multiple-value-bind (e f)
    
    732
    -		      (robust-subinternal b a d c)
    
    733
    -		    (complex e (- f))))))))))
    
    734
    -    (let* ((a (realpart x))
    
    735
    -	   (b (imagpart x))
    
    736
    -	   (c (realpart y))
    
    737
    -	   (d (imagpart y))
    
    738
    -	   (ab (max (abs a) (abs b)))
    
    739
    -	   (cd (max (abs c) (abs d)))
    
    740
    -	   (s 1d0))
    
    741
    -      (declare (double-float s))
    
    742
    -      ;; If a or b is big, scale down a and b.
    
    743
    -      (when (>= ab +cdiv-rbig+)
    
    744
    -	(setf x (/ x 2)
    
    745
    -	      s (* s 2)))
    
    746
    -      ;; If c or d is big, scale down c and d.
    
    747
    -      (when (>= cd +cdiv-rbig+)
    
    748
    -	(setf y (/ y 2)
    
    749
    -	      s (/ s 2)))
    
    750
    -      ;; If a or b is tiny, scale up a and b.
    
    751
    -      (when (<= ab (* +cdiv-rmin+ +cdiv-2/eps+))
    
    752
    -	(setf x (* x +cdiv-be+)
    
    753
    -	      s (/ s +cdiv-be+)))
    
    754
    -      ;; If c or d is tiny, scale up c and d.
    
    755
    -      (when (<= cd (* +cdiv-rmin+ +cdiv-2/eps+))
    
    756
    -	(setf y (* y +cdiv-be+)
    
    757
    -	      s (* s +cdiv-be+)))
    
    758
    -      (* s
    
    759
    -	 (robust-internal x y)))))
    
    668
    +	   ;; e is the real part and f is the imaginary part.  We can
    
    669
    +	   ;; use COMPREAL for the imaginary part by noticing that the
    
    670
    +	   ;; imaginary part of (a+i*b)/(c+i*d) is the same as the
    
    671
    +	   ;; real part of (b-i*a)/(c+i*d).
    
    672
    +	   (let ((e (,compreal a b c d r tt))
    
    673
    +		 (f (,compreal b (- a) c d r tt)))
    
    674
    +	     (values e f))))
    
    675
    +       (defun ,internal (x y)
    
    676
    +	   (declare (type (complex ,type) x y)
    
    677
    +		    ,@opt)
    
    678
    +	   (let ((a (realpart x))
    
    679
    +		 (b (imagpart x))
    
    680
    +		 (c (realpart y))
    
    681
    +		 (d (imagpart y)))
    
    682
    +	     (declare (,type a b c d))
    
    683
    +	     (flet ((maybe-scale (abs-tst a b c d)
    
    684
    +		      (declare (,type a b c d))
    
    685
    +		      ;; This implements McGehearty's iteration 3 to
    
    686
    +		      ;; handle the case when some values are too big
    
    687
    +		      ;; and should be scaled down.  Also if some
    
    688
    +		      ;; values are too tiny, scale them up.
    
    689
    +		      (let ((+rbig+ ,rbig)
    
    690
    +			    (+rmin2+ ,rmin2)
    
    691
    +			    (+rminscal+ ,rminscal)
    
    692
    +			    (+rmax2+ (* ,rbig ,rmin2))
    
    693
    +			    (+rmin+ ,rmin)
    
    694
    +			    (abs-a (abs a))
    
    695
    +			    (abs-b (abs b)))
    
    696
    +			(if (or (> abs-tst +rbig+)
    
    697
    +				(> abs-a +rbig+)
    
    698
    +				(> abs-b +rbig+))
    
    699
    +			    (setf a (* a 0.5d0)
    
    700
    +				  b (* b 0.5d0)
    
    701
    +				  c (* c 0.5d0)
    
    702
    +				  d (* d 0.5d0))
    
    703
    +			    (if (< abs-tst +rmin2+)
    
    704
    +				(setf a (* a +rminscal+)
    
    705
    +				      b (* b +rminscal+)
    
    706
    +				      c (* c +rminscal+)
    
    707
    +				      d (* d +rminscal+))
    
    708
    +				(if (or (and (< abs-a +rmin+)
    
    709
    +					     (< abs-b +rmax2+)
    
    710
    +					     (< abs-tst +rmax2+))
    
    711
    +					(and (< abs-b +rmin+)
    
    712
    +					     (< abs-a +rmax2+)
    
    713
    +					     (< abs-tst +rmax2+)))
    
    714
    +				    (setf a (* a +rminscal+)
    
    715
    +					  b (* b +rminscal+)
    
    716
    +					  c (* c +rminscal+)
    
    717
    +					  d (* d +rminscal+)))))
    
    718
    +			(values a b c d))))
    
    719
    +	       (cond
    
    720
    +		 ((<= (abs d) (abs c))
    
    721
    +		  ;; |d| <= |c|, so we can use robust-subinternal to
    
    722
    +		  ;; perform the division.
    
    723
    +		  (multiple-value-bind (a b c d)
    
    724
    +		      (maybe-scale (abs c) a b c d)
    
    725
    +		    (,subinternal a b c d)))
    
    726
    +		 (t
    
    727
    +		  ;; |d| > |c|.  So, instead compute
    
    728
    +		  ;;
    
    729
    +		  ;;   (b + i*a)/(d + i*c) = ((b*d+a*c) + (a*d-b*c)*i)/(d^2+c^2)
    
    730
    +		  ;;
    
    731
    +		  ;; Compare this to (a+i*b)/(c+i*d) and we see that
    
    732
    +		  ;; realpart of the former is the same, but the
    
    733
    +		  ;; imagpart of the former is the negative of the
    
    734
    +		  ;; desired division.
    
    735
    +		  (multiple-value-bind (a b c d)
    
    736
    +		      (maybe-scale (abs d) a b c d)
    
    737
    +		    (multiple-value-bind (e f)
    
    738
    +			(,subinternal b a d c)
    
    739
    +		      (values e (- f)))))))))
    
    740
    +	 (defun ,name (x y)
    
    741
    +	   ,docstring
    
    742
    +	   (declare (type (complex ,type) x y)
    
    743
    +		    ,@opt)
    
    744
    +	   (let ((+rmin+ ,rmin)
    
    745
    +		 (+rbig+ ,rbig)
    
    746
    +		 (+2/eps+ (/ 2 ,eps))
    
    747
    +		 (+be+ (/ 2 (* ,eps ,eps))))
    
    748
    +	     (let* ((a (realpart x))
    
    749
    +		    (b (imagpart x))
    
    750
    +		    (c (realpart y))
    
    751
    +		    (d (imagpart y))
    
    752
    +		    (ab (max (abs a) (abs b)))
    
    753
    +		    (cd (max (abs c) (abs d)))
    
    754
    +		    ;; S is always multipled by a power of 2.  It's
    
    755
    +		    ;; multiplied by either 2, 0.5, or +be+, which is
    
    756
    +		    ;; also a power of two.  (Either 2^105 or 2^209).
    
    757
    +		    ;; Hence, we can just use a double-float instead
    
    758
    +		    ;; of a double-double-float because the
    
    759
    +		    ;; double-double always has 0d0 for the lo part.
    
    760
    +		    (s 1d0))
    
    761
    +	       (declare (double-float s))
    
    762
    +	       ;; If a or b is big, scale down a and b.
    
    763
    +	       (when (>= ab +rbig+)
    
    764
    +		 (setf x (* x 0.5d0)
    
    765
    +		       s (* s 2)))
    
    766
    +	       ;; If c or d is big, scale down c and d.
    
    767
    +	       (when (>= cd +rbig+)
    
    768
    +		 (setf y (* y 0.5d0)
    
    769
    +		       s (* s 0.5d0)))
    
    770
    +	       ;; If a or b is tiny, scale up a and b.
    
    771
    +	       (when (<= ab (* +rmin+ +2/eps+))
    
    772
    +		 (setf x (* x +be+)
    
    773
    +		       s (/ s +be+)))
    
    774
    +	       ;; If c or d is tiny, scale up c and d.
    
    775
    +	       (when (<= cd (* +rmin+ +2/eps+))
    
    776
    +		 (setf y (* y +be+)
    
    777
    +		       s (* s +be+)))
    
    778
    +	       (multiple-value-bind (e f)
    
    779
    +		   (,internal x y)
    
    780
    +		 (complex (* s e)
    
    781
    +			  (* s f)))))))))
    
    782
    +)
    
    783
    +
    
    784
    +(define-cdiv double-float
    
    785
    +  :rmin least-positive-normalized-double-float
    
    786
    +  :rbig (/ most-positive-double-float 2)
    
    787
    +  :rmin2 (scale-float 1d0 -53)
    
    788
    +  :rminscal (scale-float 1d0 51)
    
    789
    +  ;; This is the value of %eps from Scilab
    
    790
    +  :eps (scale-float 1d0 -52))
    
    791
    +
    
    792
    +;; Same constants but for DOUBLE-DOUBLE-FLOATS.  Some of these aren't
    
    793
    +;; well-defined for DOUBLE-DOUBLE-FLOATS (like eps) so we make our
    
    794
    +;; best guess at what they might be.  Since double-doubles have
    
    795
    +;; twice as many bits of precision as a DOUBLE-FLOAT, we generally
    
    796
    +;; just double the exponent (for SCALE-FLOAT) of the corresponding
    
    797
    +;; DOUBLE-FLOAT values above.
    
    798
    +;;
    
    799
    +;; Note also that since both
    
    800
    +;; LEAST-POSITIVE-NORMALIZED-DOUBLE-DOUBLE-FLOAT and
    
    801
    +;; MOST-POSITIVE-DOUBLE-DOUBLE-FLOAT have a low component of 0,
    
    802
    +;; there's no loss of precision if we use the corresponding
    
    803
    +;; DOUBLE-FLOAT values.  Likewise, all the other constants here are
    
    804
    +;; powers of 2, so the DOUBLE-DOUBLE-FLOAT values can be represented
    
    805
    +;; exactly as a DOUBLE-FLOAT.  We can use DOUBLE-FLOAT values.  This
    
    806
    +;; also makes some of the operations a bit simpler since operations
    
    807
    +;; between a DOUBLE-DOUBLE-FLOAT and a DOUBLE-FLOAT are simpler than
    
    808
    +;; if both were DOUBLE-DOUBLE-FLOATs.
    
    809
    +(define-cdiv double-double-float
    
    810
    +  :rmin least-positive-normalized-double-float
    
    811
    +  :rbig (/ most-positive-double-float 2)
    
    812
    +  :rmin2 (scale-float 1d0 -106)
    
    813
    +  :rminscal (scale-float 1d0 102)
    
    814
    +  :eps (scale-float 1d0 -104))
    
    815
    +
    
    760 816
     
    
    761 817
     ;; Smith's algorithm for complex division for (complex single-float).
    
    762 818
     ;; We convert the parts to double-floats before computing the result.
    
    ... ... @@ -825,13 +881,14 @@
    825 881
         (((complex double-double-float)
    
    826 882
           (foreach (complex rational) (complex single-float) (complex double-float)
    
    827 883
     	       (complex double-double-float)))
    
    828
    -     ;; We should do something better for double-double floats.
    
    829
    -     (cdiv-generic x y))
    
    884
    +     (cdiv-double-double-float x
    
    885
    +				  (coerce y '(complex double-double-float))))
    
    830 886
         
    
    831 887
         (((foreach integer ratio single-float double-float double-double-float
    
    832 888
     	       (complex rational) (complex single-float) (complex double-float))
    
    833 889
           (complex double-double-float))
    
    834
    -     (cdiv-generic x y))
    
    890
    +     (cdiv-double-double-float (coerce x '(complex double-double-float))
    
    891
    +				  y))
    
    835 892
     
    
    836 893
         (((foreach integer ratio single-float double-float double-double-float)
    
    837 894
           (complex rational))
    

  • src/compiler/float-tran-dd.lisp
    ... ... @@ -576,6 +576,10 @@
    576 576
          (truly-the ,(type-specifier (node-derived-type node))
    
    577 577
     		(kernel:%make-double-double-float hi lo))))
    
    578 578
     
    
    579
    +(deftransform / ((a b) ((complex vm::double-double-float) (complex vm::double-double-float))
    
    580
    +		 *)
    
    581
    +  `(kernel::cdiv-double-double-float a b))
    
    582
    +  	      
    
    579 583
     (declaim (inline sqr-d))
    
    580 584
     (defun sqr-d (a)
    
    581 585
       "Square"
    

  • src/general-info/release-22a.md
    ... ... @@ -38,6 +38,9 @@ public domain.
    38 38
                 using Baudin and Smith's robust complex division algorithm
    
    39 39
                 with improvements by Patrick McGehearty.
    
    40 40
         * #458: Spurious overflow in double-double-float multiply
    
    41
    +    * #459: Improve accuracy for division of complex
    
    42
    +            double-double-floats.  The same algorithm is used here as
    
    43
    +            for #456.
    
    41 44
       * Other changes:
    
    42 45
       * Improvements to the PCL implementation of CLOS:
    
    43 46
       * Changes to building procedure:
    

  • src/i18n/locale/cmucl.pot
    ... ... @@ -4389,6 +4389,10 @@ msgstr ""
    4389 4389
     msgid "Accurate division of complex double-float numbers x and y."
    
    4390 4390
     msgstr ""
    
    4391 4391
     
    
    4392
    +#: src/code/numbers.lisp
    
    4393
    +msgid "Accurate division of complex double-double-float numbers x and y."
    
    4394
    +msgstr ""
    
    4395
    +
    
    4392 4396
     #: src/code/numbers.lisp
    
    4393 4397
     msgid "Accurate division of complex single-float numbers x and y."
    
    4394 4398
     msgstr ""
    

  • tests/float.lisp
    ... ... @@ -343,6 +343,249 @@
    343 343
         (assert-true (typep new-mode 'x86::float-modes))
    
    344 344
         (assert-equal new-mode (setf (x86::x87-floating-point-modes) new-mode))))
    
    345 345
     
    
    346
    +;; Rudimentary code to read C %a formatted numbers that look like
    
    347
    +;; "-0x1.c4dba4ba1ee79p-620".  We assume STRING is exactly in this
    
    348
    +;; format.  No error-checking is done.
    
    349
    +(defun parse-hex-float (string)
    
    350
    +  (let* ((sign (if (char= (aref string 0) #\-)
    
    351
    +		   -1
    
    352
    +		   1))
    
    353
    +	 (dot-posn (position #\. string))
    
    354
    +	 (p-posn (position #\p string))
    
    355
    +	 (lead (parse-integer string :start (1- dot-posn) :end dot-posn))
    
    356
    +	 (frac (parse-integer string :start (1+ dot-posn) :end p-posn :radix 16))
    
    357
    +	 (exp (parse-integer string :start (1+ p-posn))))
    
    358
    +    (* sign
    
    359
    +       (scale-float (float (+ (ash lead 52)
    
    360
    +			      frac)
    
    361
    +			   1d0)
    
    362
    +		    (- exp 52)))))
    
    363
    +
    
    364
    +;; Relative error in terms of bits of accuracy.  This is the
    
    365
    +;; definition used by Baudin and Smith.  A result of 53 means the two
    
    366
    +;; numbers have identical bits.  For complex numbers, we use the min
    
    367
    +;; of the bits of accuracy of the real and imaginary parts.
    
    368
    +(defun rel-err (computed expected)
    
    369
    +  (flet ((rerr (c e)
    
    370
    +	   (let ((diff (abs (- c e))))
    
    371
    +	     (if (zerop diff)
    
    372
    +		 (float-digits diff)
    
    373
    +		 (floor (- (log (/ diff (abs e)) 2d0)))))))
    
    374
    +    (min (rerr (realpart computed) (realpart expected))
    
    375
    +	 (rerr (imagpart computed) (imagpart expected)))))
    
    376
    +
    
    377
    +(defun do-cdiv-test (x y z-true expected-rel)
    
    378
    +  (let* ((z (/ x y))
    
    379
    +	 (rel (rel-err z z-true)))
    
    380
    +    (assert-equal expected-rel
    
    381
    +		  rel
    
    382
    +		  x y z z-true rel)))
    
    383
    +
    
    384
    +(defun do-cdiv-dd-test (x y z-true expected-rel)
    
    385
    +  (flet ((compute-true (a b)
    
    386
    +	   ;; Convert a and b to complex rationals, do the
    
    387
    +	   ;; division and convert back to get the true
    
    388
    +	   ;; expected result.
    
    389
    +	   (coerce
    
    390
    +	    (/ (complex (rational (realpart a))
    
    391
    +			(rational (imagpart a)))
    
    392
    +	       (complex (rational (realpart b))
    
    393
    +			(rational (imagpart b))))
    
    394
    +	    '(complex ext:double-double-float))))
    
    395
    +    (let* ((z (/ (coerce x '(complex ext:double-double-float))
    
    396
    +		 (coerce y '(complex ext:double-double-float))))
    
    397
    +	   (z-true (compute-true x y))
    
    398
    +	   (rel (rel-err z z-true)))
    
    399
    +      (assert-equal expected-rel
    
    400
    +		    rel
    
    401
    +		    k x y z z-true rel))))
    
    402
    +
    
    403
    +;; Issue #456: improve accuracy of division of complex double-floats.
    
    404
    +;;
    
    405
    +;; Tests for complex division.  Tests 1-10 are from Baudin and Smith.
    
    406
    +;; Test 11 is an example from Maxima.  Test 12 is an example from the
    
    407
    +;; ansi-tests where (/ z z) didn't produce exactly 1.  Tests 13-16 are
    
    408
    +;; for examples for improvement iterations 1-4 from McGehearty.
    
    409
    +(macrolet
    
    410
    +    ((frob (name x y z-true rel dd-rel)
    
    411
    +       `(define-test ,name
    
    412
    +	  (:tag :issues)
    
    413
    +	  (do-cdiv-test ,x ,y ,z-true ,rel)
    
    414
    +	  (do-cdiv-dd-test ,x ,y ,z-true ,dd-rel))))
    
    415
    +  ;; First cases are from Baudin and Smith
    
    416
    +  ;; 1
    
    417
    +  (frob cdiv.baudin-case.1
    
    418
    +	(complex 1d0 1d0)
    
    419
    +	(complex 1d0 (scale-float 1d0 1023))
    
    420
    +	(complex (scale-float 1d0 -1023)
    
    421
    +		 (scale-float -1d0 -1023))
    
    422
    +	53
    
    423
    +	106)
    
    424
    +  ;; 2
    
    425
    +  (frob cdiv.baudin-case.2
    
    426
    +	(complex 1d0 1d0)
    
    427
    +	(complex (scale-float 1d0 -1023) (scale-float 1d0 -1023))
    
    428
    +	(complex (scale-float 1d0 1023) 0)
    
    429
    +	53
    
    430
    +	106)
    
    431
    +  ;; 3
    
    432
    +  (frob cdiv.baudin-case.3
    
    433
    +	(complex (scale-float 1d0 1023) (scale-float 1d0 -1023))
    
    434
    +	(complex (scale-float 1d0 677) (scale-float 1d0 -677))
    
    435
    +	(complex (scale-float 1d0 346) (scale-float -1d0 -1008))
    
    436
    +	53
    
    437
    +	106)
    
    438
    +  ;; 4
    
    439
    +  (frob cdiv.baudin-case.4.overflow
    
    440
    +	(complex (scale-float 1d0 1023) (scale-float 1d0 1023))
    
    441
    +	(complex 1d0 1d0)
    
    442
    +	(complex (scale-float 1d0 1023) 0)
    
    443
    +	53
    
    444
    +	106)
    
    445
    +  ;; 5
    
    446
    +  (frob cdiv.baudin-case.5.underflow-ratio
    
    447
    +	(complex (scale-float 1d0 1020) (scale-float 1d0 -844))
    
    448
    +	(complex (scale-float 1d0 656) (scale-float 1d0 -780))
    
    449
    +	(complex (scale-float 1d0 364) (scale-float -1d0 -1072))
    
    450
    +	53
    
    451
    +	106)
    
    452
    +  ;; 6
    
    453
    +  (frob cdiv.baudin-case.6.underflow-realpart
    
    454
    +	(complex (scale-float 1d0 -71) (scale-float 1d0 1021))
    
    455
    +	(complex (scale-float 1d0 1001) (scale-float 1d0 -323))
    
    456
    +	(complex (scale-float 1d0 -1072) (scale-float 1d0 20))
    
    457
    +	53
    
    458
    +	106)
    
    459
    +  ;; 7
    
    460
    +  (frob cdiv.baudin-case.7.overflow-both-parts
    
    461
    +	(complex (scale-float 1d0 -347) (scale-float 1d0 -54))
    
    462
    +	(complex (scale-float 1d0 -1037) (scale-float 1d0 -1058))
    
    463
    +	(complex 3.898125604559113300d289 8.174961907852353577d295)
    
    464
    +	53
    
    465
    +	106)
    
    466
    +  ;; 8
    
    467
    +  (frob cdiv.baudin-case.8
    
    468
    +	(complex (scale-float 1d0 -1074) (scale-float 1d0 -1074))
    
    469
    +	(complex (scale-float 1d0 -1073) (scale-float 1d0 -1074))
    
    470
    +	(complex 0.6d0 0.2d0)
    
    471
    +	53
    
    472
    +	106)
    
    473
    +  ;; 9
    
    474
    +  (frob cdiv.baudin-case.9
    
    475
    +	(complex (scale-float 1d0 1015) (scale-float 1d0 -989))
    
    476
    +	(complex (scale-float 1d0 1023) (scale-float 1d0 1023))
    
    477
    +	(complex 0.001953125d0 -0.001953125d0)
    
    478
    +	53
    
    479
    +	106)
    
    480
    +  ;; 10
    
    481
    +  (frob cdiv.baudin-case.10.improve-imagpart-accuracy
    
    482
    +	(complex (scale-float 1d0 -622) (scale-float 1d0 -1071))
    
    483
    +	(complex (scale-float 1d0 -343) (scale-float 1d0 -798))
    
    484
    +	(complex 1.02951151789360578d-84 6.97145987515076231d-220)
    
    485
    +	53
    
    486
    +	106)
    
    487
    +  ;; 11
    
    488
    +  ;;
    
    489
    +  ;; From Maxima.  This was from a (private) email where Maxima used
    
    490
    +  ;; CL:/ to compute the ratio but was not very accurate.
    
    491
    +  (frob cdiv.maxima-case
    
    492
    +	#c(5.43d-10 1.13d-100)
    
    493
    +	#c(1.2d-311 5.7d-312)
    
    494
    +	#c(3.691993880674614517999740937026568563794896024143749539711267954d301
    
    495
    +	   -1.753697093319947872394996242210428954266103103602859195409591583d301)
    
    496
    +	52
    
    497
    +	107)
    
    498
    +  ;; 12
    
    499
    +  ;;
    
    500
    +  ;; Found by ansi tests. z/z should be exactly 1.
    
    501
    +  (frob cdiv.ansi-test-z/z
    
    502
    +	#c(1.565640716292489d19 0.0d0)
    
    503
    +	#c(1.565640716292489d19 0.0d0)
    
    504
    +	#c(1d0 0)
    
    505
    +	53
    
    506
    +	106)
    
    507
    +  ;; 13
    
    508
    +  ;; Iteration 1.  Without this, we would instead return
    
    509
    +  ;;
    
    510
    +  ;;   (complex (parse-hex-float "0x1.ba8df8075bceep+155")
    
    511
    +  ;;            (parse-hex-float "-0x1.a4ad6329485f0p-895"))
    
    512
    +  ;;
    
    513
    +  ;; whose imaginary part is quite a bit off.
    
    514
    +  (frob cdiv.mcgehearty-iteration.1
    
    515
    +	(complex (parse-hex-float "0x1.73a3dac1d2f1fp+509")
    
    516
    +		 (parse-hex-float "-0x1.c4dba4ba1ee79p-620"))
    
    517
    +	(complex (parse-hex-float "0x1.adf526c249cf0p+353")
    
    518
    +		 (parse-hex-float "0x1.98b3fbc1677bbp-697"))
    
    519
    +	(complex (parse-hex-float "0x1.BA8DF8075BCEEp+155")
    
    520
    +		 (parse-hex-float "-0x1.A4AD628DA5B74p-895"))
    
    521
    +	53
    
    522
    +	106)
    
    523
    +  ;; 14
    
    524
    +  ;; Iteration 2.
    
    525
    +  (frob cdiv.mcgehearty-iteration.2
    
    526
    +	(complex (parse-hex-float "-0x0.000000008e4f8p-1022")
    
    527
    +		 (parse-hex-float "0x0.0000060366ba7p-1022"))
    
    528
    +	(complex (parse-hex-float "-0x1.605b467369526p-245")
    
    529
    +		 (parse-hex-float "0x1.417bd33105808p-256"))
    
    530
    +	(complex (parse-hex-float "0x1.cde593daa4ffep-810")
    
    531
    +		 (parse-hex-float "-0x1.179b9a63df6d3p-799"))
    
    532
    +	52
    
    533
    +	106)
    
    534
    +  ;; 15
    
    535
    +  ;; Iteration 3
    
    536
    +  (frob cdiv.mcgehearty-iteration.3
    
    537
    +	(complex (parse-hex-float "0x1.cb27eece7c585p-355 ")
    
    538
    +		 (parse-hex-float "0x0.000000223b8a8p-1022"))
    
    539
    +	(complex (parse-hex-float "-0x1.74e7ed2b9189fp-22")
    
    540
    +		 (parse-hex-float "0x1.3d80439e9a119p-731"))
    
    541
    +	(complex (parse-hex-float "-0x1.3b35ed806ae5ap-333")
    
    542
    +		 (parse-hex-float "-0x0.05e01bcbfd9f6p-1022"))
    
    543
    +	53
    
    544
    +	106)
    
    545
    +  ;; 16
    
    546
    +  ;; Iteration 4
    
    547
    +  (frob cdiv.mcgehearty-iteration.4
    
    548
    +	(complex (parse-hex-float "-0x1.f5c75c69829f0p-530")
    
    549
    +		 (parse-hex-float "-0x1.e73b1fde6b909p+316"))
    
    550
    +	(complex (parse-hex-float "-0x1.ff96c3957742bp+1023")
    
    551
    +		 (parse-hex-float "0x1.5bd78c9335899p+1021"))
    
    552
    +	(complex (parse-hex-float "-0x1.423c6ce00c73bp-710")
    
    553
    +		 (parse-hex-float "0x1.d9edcf45bcb0ep-708"))
    
    554
    +	52
    
    555
    +	106))
    
    556
    +
    
    557
    +(define-test complex-division.misc
    
    558
    +    (:tag :issue)
    
    559
    +  (let ((num '(1
    
    560
    +	       1/2
    
    561
    +	       1.0
    
    562
    +	       1d0
    
    563
    +	       #c(1 2)
    
    564
    +	       #c(1.0 2.0)
    
    565
    +	       #c(1d0 2d0)
    
    566
    +	       #c(1w0 2w0))))
    
    567
    +    ;; Try all combinations of divisions of different types.  This is
    
    568
    +    ;; primarily to test that we got all the numeric contagion cases
    
    569
    +    ;; for division in CL:/.
    
    570
    +    (dolist (x num)
    
    571
    +      (dolist (y num)
    
    572
    +	(assert-true (/ x y)
    
    573
    +		     x y)))))
    
    574
    +
    
    575
    +(define-test complex-division.single
    
    576
    +    (:tag :issues)
    
    577
    +  (let* ((x #c(1 2))
    
    578
    +	 (y (complex (expt 2 127) (expt 2 127)))
    
    579
    +	 (expected (coerce (/ x y)
    
    580
    +			   '(complex single-float))))
    
    581
    +    ;; A naive implementation of complex division would cause an
    
    582
    +    ;; overflow in computing the denominator.
    
    583
    +    (assert-equal expected
    
    584
    +		  (/ (coerce x '(complex single-float))
    
    585
    +		     (coerce y '(complex single-float)))
    
    586
    +		  x
    
    587
    +		  y)))
    
    588
    +
    
    346 589
     ;; Issue #458
    
    347 590
     (define-test dd-mult-overflow
    
    348 591
       (:tag :issues)