| ... |
... |
@@ -612,25 +612,33 @@ |
|
612
|
612
|
(defconstant +cdiv-be+ (/ 2 (* +cdiv-eps+ +cdiv-eps+)))
|
|
613
|
613
|
(defconstant +cdiv-2/eps+ (/ 2 +cdiv-eps+))
|
|
614
|
614
|
|
|
615
|
|
-;; Same constants but for double-double-floats. Some of these aren't
|
|
616
|
|
-;; well-defined for double-double-floats so we make our best guess at
|
|
|
615
|
+;; Same constants but for DOUBLE-DOUBLE-FLOATS. Some of these aren't
|
|
|
616
|
+;; well-defined for DOUBLE-DOUBLE-FLOATS so we make our best guess at
|
|
617
|
617
|
;; what they might be. Since double-doubles have about twice as many
|
|
618
|
|
-;; bits of precision as a double-float, we generally just double the
|
|
619
|
|
-;; exponent of the corresponding double-float values above.
|
|
|
618
|
+;; bits of precision as a DOUBLE-FLOAT, we generally just double the
|
|
|
619
|
+;; exponent (for SCALE-FLOAT) of the corresponding DOUBLE-FLOAT values
|
|
|
620
|
+;; above.
|
|
|
621
|
+;;
|
|
|
622
|
+;; Note also that both LEAST-POSITIVE-NORMALIZED-DOUBLE-DOUBLE-FLOAT
|
|
|
623
|
+;; and MOST-POSITIVE-DOUBLE-DOUBLE-FLOAT have a low component of 0, so
|
|
|
624
|
+;; there's no loss of precision if we use the corresponding
|
|
|
625
|
+;; DOUBLE-FLOAT values. Likewise, all the other constants here are
|
|
|
626
|
+;; powers of 2, so the DOUBLE-DOUBLE-FLOAT values can be represented
|
|
|
627
|
+;; exactly as a DOUBLE-FLOAT. We can use DOUBLE-FLOAT values.
|
|
620
|
628
|
(defconstant +cdiv-dd-rmin+
|
|
621
|
|
- least-positive-normalized-double-double-float)
|
|
|
629
|
+ least-positive-normalized-double-float)
|
|
622
|
630
|
(defconstant +cdiv-dd-rbig+
|
|
623
|
|
- (/ most-positive-double-double-float 2))
|
|
|
631
|
+ (/ most-positive-double-float 2))
|
|
624
|
632
|
(defconstant +cdiv-dd-rmin2+
|
|
625
|
|
- (scale-float 1w0 -106))
|
|
|
633
|
+ (scale-float 1d0 -106))
|
|
626
|
634
|
(defconstant +cdiv-dd-rminscal+
|
|
627
|
|
- (scale-float 1w0 102))
|
|
|
635
|
+ (scale-float 1d0 102))
|
|
628
|
636
|
(defconstant +cdiv-dd-rmax2+
|
|
629
|
637
|
(* +cdiv-dd-rbig+ +cdiv-dd-rmin2+))
|
|
630
|
638
|
;; Epsilon for double-doubles isn't really well-defined because things
|
|
631
|
639
|
;; like (+ 1w0 1w-200) is a valid double-double float.
|
|
632
|
640
|
(defconstant +cdiv-dd-eps+
|
|
633
|
|
- (scale-float 1w0 -104))
|
|
|
641
|
+ (scale-float 1d0 -104))
|
|
634
|
642
|
(defconstant +cdiv-dd-be+
|
|
635
|
643
|
(/ 2 (* +cdiv-dd-eps+ +cdiv-dd-eps+)))
|
|
636
|
644
|
(defconstant +cdiv-dd-2/eps+
|
| ... |
... |
@@ -643,179 +651,11 @@ |
|
643
|
651
|
;; else.
|
|
644
|
652
|
(declaim (ext:start-block cdiv-double-float cdiv-single-float
|
|
645
|
653
|
cdiv-double-double-float
|
|
646
|
|
- two-arg-/
|
|
647
|
|
- cdiv-double-float-internal-compreal
|
|
648
|
|
- cdiv-double-float-robust-subinternal
|
|
649
|
|
- cdiv-double-float-robust-internal
|
|
650
|
|
- cdiv-double-double-float-internal-compreal
|
|
651
|
|
- cdiv-double-double-float-robust-subinternal
|
|
652
|
|
- cdiv-double-double-float-robust-internal))
|
|
|
654
|
+ two-arg-/))
|
|
653
|
655
|
|
|
654
|
656
|
;; The code for both the double-float and double-double-float
|
|
655
|
657
|
;; implementation is basically identical except for the constants.
|
|
656
|
658
|
;; use a macro to generate both versions.
|
|
657
|
|
-#+nil
|
|
658
|
|
-(macrolet
|
|
659
|
|
- ((frob (type)
|
|
660
|
|
- (let* ((dd (if (eq type 'double-float)
|
|
661
|
|
- ""
|
|
662
|
|
- "DD-"))
|
|
663
|
|
- (name (symbolicate "CDIV-" type))
|
|
664
|
|
- (docstring (let ((*print-case* :downcase))
|
|
665
|
|
- (format nil "Accurate division of complex ~A numbers x and y."
|
|
666
|
|
- type)))
|
|
667
|
|
- ;; Create the correct symbols for the constants we need,
|
|
668
|
|
- ;; as defined above.
|
|
669
|
|
- (+rmin+ (symbolicate "+CDIV-" dd "RMIN+"))
|
|
670
|
|
- (+rbig+ (symbolicate "+CDIV-" dd "RBIG+"))
|
|
671
|
|
- (+rmin2+ (symbolicate "+CDIV-" dd "RMIN2+"))
|
|
672
|
|
- (+rminscal+ (symbolicate "+CDIV-" dd "RMINSCAL+"))
|
|
673
|
|
- (+rmax2+ (symbolicate "+CDIV-" dd "RMAX2+"))
|
|
674
|
|
- (+eps+ (symbolicate "+CDIV-" dd "EPS+"))
|
|
675
|
|
- (+be+ (symbolicate "+CDIV-" dd "BE+"))
|
|
676
|
|
- (+2/eps+ (symbolicate "+CDIV-" dd "2/EPS+")))
|
|
677
|
|
- `(defun ,name (x y)
|
|
678
|
|
- ,docstring
|
|
679
|
|
- (declare (type (complex ,type) x y)
|
|
680
|
|
- (optimize (speed 3) (safety 0)))
|
|
681
|
|
- (labels
|
|
682
|
|
- ((internal-compreal (a b c d r tt)
|
|
683
|
|
- (declare (,type a b c d r tt))
|
|
684
|
|
- ;; Compute the real part of the complex division
|
|
685
|
|
- ;; (a+ib)/(c+id), assuming |c| <= |d|. r = d/c and tt = 1/(c+d*r).
|
|
686
|
|
- ;;
|
|
687
|
|
- ;; The realpart is (a*c+b*d)/(c^2+d^2).
|
|
688
|
|
- ;;
|
|
689
|
|
- ;; c^2+d^2 = c*(c+d*(d/c)) = c*(c+d*r)
|
|
690
|
|
- ;;
|
|
691
|
|
- ;; Then
|
|
692
|
|
- ;;
|
|
693
|
|
- ;; (a*c+b*d)/(c^2+d^2) = (a*c+b*d)/(c*(c+d*r))
|
|
694
|
|
- ;; = (a + b*d/c)/(c+d*r)
|
|
695
|
|
- ;; = (a + b*r)/(c + d*r).
|
|
696
|
|
- ;;
|
|
697
|
|
- ;; Thus tt = (c + d*r).
|
|
698
|
|
- (cond ((>= (abs r) ,+rmin+)
|
|
699
|
|
- (let ((br (* b r)))
|
|
700
|
|
- (if (/= br 0)
|
|
701
|
|
- (/ (+ a br) tt)
|
|
702
|
|
- ;; b*r underflows. Instead, compute
|
|
703
|
|
- ;;
|
|
704
|
|
- ;; (a + b*r)*tt = a*tt + b*tt*r
|
|
705
|
|
- ;; = a*tt + (b*tt)*r
|
|
706
|
|
- ;; (a + b*r)/tt = a/tt + b/tt*r
|
|
707
|
|
- ;; = a*tt + (b*tt)*r
|
|
708
|
|
- (+ (/ a tt)
|
|
709
|
|
- (* (/ b tt)
|
|
710
|
|
- r)))))
|
|
711
|
|
- (t
|
|
712
|
|
- ;; r = 0 so d is very tiny compared to c.
|
|
713
|
|
- ;;
|
|
714
|
|
- (/ (+ a (* d (/ b c)))
|
|
715
|
|
- tt))))
|
|
716
|
|
- (robust-subinternal (a b c d)
|
|
717
|
|
- (declare (,type a b c d))
|
|
718
|
|
- (let* ((r (/ d c))
|
|
719
|
|
- (tt (+ c (* d r))))
|
|
720
|
|
- ;; e is the real part and f is the imaginary part. We
|
|
721
|
|
- ;; can use internal-compreal for the imaginary part by
|
|
722
|
|
- ;; noticing that the imaginary part of (a+i*b)/(c+i*d) is
|
|
723
|
|
- ;; the same as the real part of (b-i*a)/(c+i*d).
|
|
724
|
|
- (let ((e (internal-compreal a b c d r tt))
|
|
725
|
|
- (f (internal-compreal b (- a) c d r tt)))
|
|
726
|
|
- (values e
|
|
727
|
|
- f))))
|
|
728
|
|
- (robust-internal (x y)
|
|
729
|
|
- (declare (type (complex ,type) x y))
|
|
730
|
|
- (let ((a (realpart x))
|
|
731
|
|
- (b (imagpart x))
|
|
732
|
|
- (c (realpart y))
|
|
733
|
|
- (d (imagpart y)))
|
|
734
|
|
- (declare (,type a b c d))
|
|
735
|
|
- (flet ((maybe-scale (abs-tst a b c d)
|
|
736
|
|
- (declare (,type a b c d))
|
|
737
|
|
- ;; This implements McGehearty's iteration 3 to
|
|
738
|
|
- ;; handle the case when some values are too big
|
|
739
|
|
- ;; and should be scaled down. Also if some
|
|
740
|
|
- ;; values are too tiny, scale them up.
|
|
741
|
|
- (let ((abs-a (abs a))
|
|
742
|
|
- (abs-b (abs b)))
|
|
743
|
|
- (if (or (> abs-tst ,+rbig+)
|
|
744
|
|
- (> abs-a ,+rbig+)
|
|
745
|
|
- (> abs-b ,+rbig+))
|
|
746
|
|
- (setf a (* a 0.5d0)
|
|
747
|
|
- b (* b 0.5d0)
|
|
748
|
|
- c (* c 0.5d0)
|
|
749
|
|
- d (* d 0.5d0))
|
|
750
|
|
- (if (< abs-tst ,+rmin2+)
|
|
751
|
|
- (setf a (* a ,+rminscal+)
|
|
752
|
|
- b (* b ,+rminscal+)
|
|
753
|
|
- c (* c ,+rminscal+)
|
|
754
|
|
- d (* d ,+rminscal+))
|
|
755
|
|
- (if (or (and (< abs-a ,+rmin+)
|
|
756
|
|
- (< abs-b ,+rmax2+)
|
|
757
|
|
- (< abs-tst ,+rmax2+))
|
|
758
|
|
- (and (< abs-b ,+rmin+)
|
|
759
|
|
- (< abs-a ,+rmax2+)
|
|
760
|
|
- (< abs-tst ,+rmax2+)))
|
|
761
|
|
- (setf a (* a ,+rminscal+)
|
|
762
|
|
- b (* b ,+rminscal+)
|
|
763
|
|
- c (* c ,+rminscal+)
|
|
764
|
|
- d (* d ,+rminscal+)))))
|
|
765
|
|
- (values a b c d))))
|
|
766
|
|
- (cond
|
|
767
|
|
- ((<= (abs d) (abs c))
|
|
768
|
|
- ;; |d| <= |c|, so we can use robust-subinternal to
|
|
769
|
|
- ;; perform the division.
|
|
770
|
|
- (multiple-value-bind (a b c d)
|
|
771
|
|
- (maybe-scale (abs c) a b c d)
|
|
772
|
|
- (multiple-value-bind (e f)
|
|
773
|
|
- (robust-subinternal a b c d)
|
|
774
|
|
- (complex e f))))
|
|
775
|
|
- (t
|
|
776
|
|
- ;; |d| > |c|. So, instead compute
|
|
777
|
|
- ;;
|
|
778
|
|
- ;; (b + i*a)/(d + i*c) = ((b*d+a*c) + (a*d-b*c)*i)/(d^2+c^2)
|
|
779
|
|
- ;;
|
|
780
|
|
- ;; Compare this to (a+i*b)/(c+i*d) and we see that
|
|
781
|
|
- ;; realpart of the former is the same, but the
|
|
782
|
|
- ;; imagpart of the former is the negative of the
|
|
783
|
|
- ;; desired division.
|
|
784
|
|
- (multiple-value-bind (a b c d)
|
|
785
|
|
- (maybe-scale (abs d) a b c d)
|
|
786
|
|
- (multiple-value-bind (e f)
|
|
787
|
|
- (robust-subinternal b a d c)
|
|
788
|
|
- (complex e (- f))))))))))
|
|
789
|
|
- (let* ((a (realpart x))
|
|
790
|
|
- (b (imagpart x))
|
|
791
|
|
- (c (realpart y))
|
|
792
|
|
- (d (imagpart y))
|
|
793
|
|
- (ab (max (abs a) (abs b)))
|
|
794
|
|
- (cd (max (abs c) (abs d)))
|
|
795
|
|
- (s (coerce 1 ',type)))
|
|
796
|
|
- (declare (,type s))
|
|
797
|
|
- ;; If a or b is big, scale down a and b.
|
|
798
|
|
- (when (>= ab ,+rbig+)
|
|
799
|
|
- (setf x (* x 0.5d0)
|
|
800
|
|
- s (* s 2)))
|
|
801
|
|
- ;; If c or d is big, scale down c and d.
|
|
802
|
|
- (when (>= cd ,+rbig+)
|
|
803
|
|
- (setf y (* y 0.5d0)
|
|
804
|
|
- s (* s 0.5d0)))
|
|
805
|
|
- ;; If a or b is tiny, scale up a and b.
|
|
806
|
|
- (when (<= ab (* ,+rmin+ ,+2/eps+))
|
|
807
|
|
- (setf x (* x ,+be+)
|
|
808
|
|
- s (/ s ,+be+)))
|
|
809
|
|
- ;; If c or d is tiny, scale up c and d.
|
|
810
|
|
- (when (<= cd (* ,+rmin+ ,+2/eps+))
|
|
811
|
|
- (setf y (* y ,+be+)
|
|
812
|
|
- s (* s ,+be+)))
|
|
813
|
|
- (* s
|
|
814
|
|
- (robust-internal x y))))))))
|
|
815
|
|
- (frob double-float)
|
|
816
|
|
- #+double-double
|
|
817
|
|
- (frob double-double-float))
|
|
818
|
|
-
|
|
819
|
659
|
(eval-when (:compile-toplevel)
|
|
820
|
660
|
(defmacro define-cdiv (type)
|
|
821
|
661
|
(let* ((dd (if (eq type 'double-float)
|
| ... |
... |
@@ -842,11 +682,14 @@ |
|
842
|
682
|
(defun ,compreal (a b c d r tt)
|
|
843
|
683
|
(declare (,type a b c d r tt)
|
|
844
|
684
|
,@opt)
|
|
845
|
|
- ;; Compute the real part of the complex division
|
|
846
|
|
- ;; (a+ib)/(c+id), assuming |c| <= |d|. r = d/c and tt = 1/(c+d*r).
|
|
|
685
|
+ ;; Computes the real part of the complex division
|
|
|
686
|
+ ;; (a+ib)/(c+id), assuming |d| <= |c|. Then let r = d/c and
|
|
|
687
|
+ ;; tt = (c+d*r).
|
|
847
|
688
|
;;
|
|
848
|
689
|
;; The realpart is (a*c+b*d)/(c^2+d^2).
|
|
849
|
690
|
;;
|
|
|
691
|
+ ;; The denominator is
|
|
|
692
|
+ ;;
|
|
850
|
693
|
;; c^2+d^2 = c*(c+d*(d/c)) = c*(c+d*r)
|
|
851
|
694
|
;;
|
|
852
|
695
|
;; Then
|
| ... |
... |
@@ -862,15 +705,12 @@ |
|
862
|
705
|
(/ (+ a br) tt)
|
|
863
|
706
|
;; b*r underflows. Instead, compute
|
|
864
|
707
|
;;
|
|
865
|
|
- ;; (a + b*r)*tt = a*tt + b*tt*r
|
|
866
|
|
- ;; = a*tt + (b*tt)*r
|
|
867
|
708
|
;; (a + b*r)/tt = a/tt + b/tt*r
|
|
868
|
|
- ;; = a*tt + (b*tt)*r
|
|
869
|
709
|
(+ (/ a tt)
|
|
870
|
710
|
(* (/ b tt)
|
|
871
|
711
|
r)))))
|
|
872
|
712
|
(t
|
|
873
|
|
- ;; r = 0 so d is very tiny compared to c.
|
|
|
713
|
+ ;; r is very small so d is very tiny compared to c.
|
|
874
|
714
|
;;
|
|
875
|
715
|
(/ (+ a (* d (/ b c)))
|
|
876
|
716
|
tt))))
|
| ... |
... |
@@ -931,9 +771,7 @@ |
|
931
|
771
|
;; perform the division.
|
|
932
|
772
|
(multiple-value-bind (a b c d)
|
|
933
|
773
|
(maybe-scale (abs c) a b c d)
|
|
934
|
|
- (multiple-value-bind (e f)
|
|
935
|
|
- (,subinternal a b c d)
|
|
936
|
|
- (complex e f))))
|
|
|
774
|
+ (,subinternal a b c d)))
|
|
937
|
775
|
(t
|
|
938
|
776
|
;; |d| > |c|. So, instead compute
|
|
939
|
777
|
;;
|
| ... |
... |
@@ -947,7 +785,7 @@ |
|
947
|
785
|
(maybe-scale (abs d) a b c d)
|
|
948
|
786
|
(multiple-value-bind (e f)
|
|
949
|
787
|
(,subinternal b a d c)
|
|
950
|
|
- (complex e (- f)))))))))
|
|
|
788
|
+ (values e (- f)))))))))
|
|
951
|
789
|
(defun ,name (x y)
|
|
952
|
790
|
,docstring
|
|
953
|
791
|
(declare (type (complex ,type) x y)
|
| ... |
... |
@@ -982,14 +820,15 @@ |
|
982
|
820
|
(when (<= cd (* ,+rmin+ ,+2/eps+))
|
|
983
|
821
|
(setf y (* y ,+be+)
|
|
984
|
822
|
s (* s ,+be+)))
|
|
985
|
|
- (* s
|
|
986
|
|
- (,internal x y)))))))
|
|
|
823
|
+ (multiple-value-bind (e f)
|
|
|
824
|
+ (,internal x y)
|
|
|
825
|
+ (complex (* s e)
|
|
|
826
|
+ (* s f))))))))
|
|
987
|
827
|
)
|
|
988
|
828
|
|
|
989
|
829
|
(define-cdiv double-float)
|
|
990
|
830
|
(define-cdiv double-double-float)
|
|
991
|
831
|
|
|
992
|
|
-
|
|
993
|
832
|
;; Smith's algorithm for complex division for (complex single-float).
|
|
994
|
833
|
;; We convert the parts to double-floats before computing the result.
|
|
995
|
834
|
(defun cdiv-single-float (x y)
|