Raymond Toy pushed to branch issue-456-more-accurate-complex-div at cmucl / cmucl

Commits:

1 changed file:

Changes:

  • src/code/numbers.lisp
    ... ... @@ -602,17 +602,19 @@
    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
    -(let* (;; This is the value of Scilab's %eps variable.
    
    606
    -       (eps (scale-float 1d0 -52))
    
    607
    -       (rmin least-positive-normalized-double-float)
    
    608
    -       (rbig (/ most-positive-double-float 2))
    
    609
    -       (rmin2 (scale-float 1d0 -53))
    
    610
    -       (rminscal (scale-float 1d0 51))
    
    611
    -       (rmax2 (* rbig rmin2))
    
    612
    -       (be (/ 2 (* eps eps)))
    
    613
    -       (2/eps (/ 2 eps)))
    
    605
    +(let* ((+eps+ (scale-float 1d0 -52))
    
    606
    +       (+rmin+ least-positive-normalized-double-float)
    
    607
    +       (+rbig+ (/ most-positive-double-float 2))
    
    608
    +       (+rmin2+ (scale-float 1d0 -53))
    
    609
    +       (+rminscal+ (scale-float 1d0 51))
    
    610
    +       (+rmax2+ (* +rbig+ +rmin2+))
    
    611
    +       (+be+ (/ 2 (* +eps+ +eps+)))
    
    612
    +       (+2/eps+ (/ 2 +eps+)))
    
    613
    +  (declare (double-float +eps+ +rmin+ +rbig+ +rmin2+
    
    614
    +			 +rminscal+ +rmax2+ +be+ +2/eps+))
    
    614 615
       (defun cdiv-double-float (x y)
    
    615
    -    (declare (type (complex double-float) x y))
    
    616
    +    (declare (type (complex double-float) x y)
    
    617
    +	     (optimize (speed 3) (safety 0)))
    
    616 618
         (labels
    
    617 619
     	((internal-compreal (a b c d r tt)
    
    618 620
     	   (declare (double-float a b c d r tt))
    
    ... ... @@ -634,7 +636,7 @@
    634 636
     	   (progn
    
    635 637
     	     (format t "a,b,c,d = ~A ~A ~A ~A~%" a b c d)
    
    636 638
     	     (format t "  r, tt = ~A ~A~%" r tt))
    
    637
    -	   (cond ((>= (abs r) rmin)
    
    639
    +	   (cond ((>= (abs r) +rmin+)
    
    638 640
     		  (let ((br (* b r)))
    
    639 641
     		    #+nil
    
    640 642
     		    (format t "br = ~A~%" br)
    
    ... ... @@ -678,43 +680,47 @@
    678 680
     		 (b (imagpart x))
    
    679 681
     		 (c (realpart y))
    
    680 682
     		 (d (imagpart y)))
    
    681
    -	     (flet ((maybe-scale (abs-tst)
    
    683
    +	     (declare (double-float a b c d))
    
    684
    +	     (flet ((maybe-scale (abs-tst a b c d)
    
    685
    +		      (declare (double-float a b c d))
    
    682 686
     		      ;; This implements McGehearty's iteration 3 to
    
    683 687
     		      ;; handle the case when some values are too big
    
    684 688
     		      ;; and should be scaled down.  Also if some
    
    685 689
     		      ;; values are too tiny, scale them up.
    
    686 690
     		      (let ((abs-a (abs a))
    
    687 691
     			    (abs-b (abs b)))
    
    688
    -			(if (or (> abs-tst rbig)
    
    689
    -				(> abs-a rbig)
    
    690
    -				(> abs-b rbig))
    
    692
    +			(if (or (> abs-tst +rbig+)
    
    693
    +				(> abs-a +rbig+)
    
    694
    +				(> abs-b +rbig+))
    
    691 695
     			    (setf a (* a 0.5d0)
    
    692 696
     				  b (* b 0.5d0)
    
    693 697
     				  c (* c 0.5d0)
    
    694 698
     				  d (* d 0.5d0))
    
    695
    -			    (if (< abs-tst rmin2)
    
    696
    -				(setf a (* a rminscal)
    
    697
    -				      b (* b rminscal)
    
    698
    -				      c (* c rminscal)
    
    699
    -				      d (* d rminscal))
    
    700
    -				(if (or (and (< abs-a rmin)
    
    701
    -					     (< abs-b rmax2)
    
    702
    -					     (< abs-tst rmax2))
    
    703
    -					(and (< abs-b rmin)
    
    704
    -					     (< abs-a rmax2)
    
    705
    -					     (< abs-tst rmax2)))
    
    706
    -				    (setf a (* a rminscal)
    
    707
    -					  b (* b rminscal)
    
    708
    -					  c (* c rminscal)
    
    709
    -					  d (* d rminscal))))))))
    
    699
    +			    (if (< abs-tst +rmin2+)
    
    700
    +				(setf a (* a +rminscal+)
    
    701
    +				      b (* b +rminscal+)
    
    702
    +				      c (* c +rminscal+)
    
    703
    +				      d (* d +rminscal+))
    
    704
    +				(if (or (and (< abs-a +rmin+)
    
    705
    +					     (< abs-b +rmax2+)
    
    706
    +					     (< abs-tst +rmax2+))
    
    707
    +					(and (< abs-b +rmin+)
    
    708
    +					     (< abs-a +rmax2+)
    
    709
    +					     (< abs-tst +rmax2+)))
    
    710
    +				    (setf a (* a +rminscal+)
    
    711
    +					  b (* b +rminscal+)
    
    712
    +					  c (* c +rminscal+)
    
    713
    +					  d (* d +rminscal+)))))
    
    714
    +			(values a b c d))))
    
    710 715
     	       (cond
    
    711 716
     		 ((<= (abs d) (abs c))
    
    712 717
     		  ;; |d| <= |c|, so we can use robust-subinternal to
    
    713 718
     		  ;; perform the division.
    
    714
    -		  (maybe-scale (abs c))
    
    715
    -		  (multiple-value-bind (e f)
    
    716
    -		      (robust-subinternal a b c d)
    
    717
    -		    (complex e f)))
    
    719
    +		  (multiple-value-bind (a b c d)
    
    720
    +		      (maybe-scale (abs c) a b c d)
    
    721
    +		    (multiple-value-bind (e f)
    
    722
    +			(robust-subinternal a b c d)
    
    723
    +		      (complex e f))))
    
    718 724
     		 (t
    
    719 725
     		  ;; |d| > |c|.  So, instead compute
    
    720 726
     		  ;;
    
    ... ... @@ -724,10 +730,11 @@
    724 730
     		  ;; realpart of the former is the same, but the
    
    725 731
     		  ;; imagpart of the former is the negative of the
    
    726 732
     		  ;; desired division.
    
    727
    -		  (maybe-scale (abs d))
    
    728
    -		  (multiple-value-bind (e f)
    
    729
    -		      (robust-subinternal b a d c)
    
    730
    -		    (complex e (- f)))))))))
    
    733
    +		  (multiple-value-bind (a b c d)
    
    734
    +		      (maybe-scale (abs d) a b c d)
    
    735
    +		    (multiple-value-bind (e f)
    
    736
    +			(robust-subinternal b a d c)
    
    737
    +		      (complex e (- f))))))))))
    
    731 738
           (let* ((a (realpart x))
    
    732 739
     	     (b (imagpart x))
    
    733 740
     	     (c (realpart y))
    
    ... ... @@ -735,22 +742,23 @@
    735 742
     	     (ab (max (abs a) (abs b)))
    
    736 743
     	     (cd (max (abs c) (abs d)))
    
    737 744
     	     (s 1d0))
    
    745
    +	(declare (double-float s))
    
    738 746
     	;; If a or b is big, scale down a and b.
    
    739
    -	(when (>= ab rbig)
    
    747
    +	(when (>= ab +rbig+)
    
    740 748
     	  (setf x (/ x 2)
    
    741 749
     		s (* s 2)))
    
    742 750
     	;; If c or d is big, scale down c and d.
    
    743
    -	(when (>= cd rbig)
    
    751
    +	(when (>= cd +rbig+)
    
    744 752
     	  (setf y (/ y 2)
    
    745 753
     		s (/ s 2)))
    
    746 754
     	;; If a or b is tiny, scale up a and b.
    
    747
    -	(when (<= ab (* rmin 2/eps))
    
    748
    -	  (setf x (* x be)
    
    749
    -		s (/ s be)))
    
    755
    +	(when (<= ab (* +rmin+ +2/eps+))
    
    756
    +	  (setf x (* x +be+)
    
    757
    +		s (/ s +be+)))
    
    750 758
     	;; If c or d is tiny, scale up c and d.
    
    751
    -	(when (<= cd (* rmin 2/eps))
    
    752
    -	  (setf y (* y be)
    
    753
    -		s (* s be)))
    
    759
    +	(when (<= cd (* +rmin+ +2/eps+))
    
    760
    +	  (setf y (* y +be+)
    
    761
    +		s (* s +be+)))
    
    754 762
     	(* s
    
    755 763
     	   (robust-internal x y))))))
    
    756 764