| ... |
... |
@@ -853,3 +853,176 @@ |
|
853
|
853
|
(ext:with-float-traps-masked (:underflow :inexact)
|
|
854
|
854
|
(assert-equal 0 (kernel:double-float-high-bits 1.1d-322))
|
|
855
|
855
|
(assert-equal #x16 (kernel:double-float-low-bits 1.1d-322))))
|
|
|
856
|
+
|
|
|
857
|
+(define-test float-ratio-float.denormal-double-rounding.single
|
|
|
858
|
+ (:tag :issues)
|
|
|
859
|
+ ;; Regression for the double-rounding bug exposed by reading
|
|
|
860
|
+ ;; "7.290983e-39". The exact rational lies at 5203019.332 * 2^-149,
|
|
|
861
|
+ ;; below halfway between denormals #x4f644b and #x4f644c. An earlier
|
|
|
862
|
+ ;; fix rounded to 24 bits first (lifting it to the artificial tie
|
|
|
863
|
+ ;; 5203019.5 * 2^-149) and then re-rounded ties-to-even to #x4f644c.
|
|
|
864
|
+ ;; FLOAT-RATIO-FLOAT now re-rounds directly to denormal precision in a
|
|
|
865
|
+ ;; single step, yielding the correctly-rounded #x4f644b.
|
|
|
866
|
+ (assert-equal #x4f644b
|
|
|
867
|
+ (kernel:single-float-bits 7.290983e-39)))
|
|
|
868
|
+
|
|
|
869
|
+(define-test float-ratio-float.denormal-low-below-halfway.single
|
|
|
870
|
+ (:tag :issues)
|
|
|
871
|
+ ;; Exercise ROUND-DENORMAL's `low < halfway' branch via FLOAT-RATIO-
|
|
|
872
|
+ ;; FLOAT. Value 11/10 * least-positive is 1.1 denormal-units; the
|
|
|
873
|
+ ;; loop sees several bits of low and the comparison must take the
|
|
|
874
|
+ ;; round-down path so the mantissa stays at 1.
|
|
|
875
|
+ (let ((x (* 11/10 (expt 2 -149))))
|
|
|
876
|
+ (assert-equal #x00000001
|
|
|
877
|
+ (kernel:single-float-bits
|
|
|
878
|
+ (kernel::float-ratio-float x 'single-float))
|
|
|
879
|
+ x)))
|
|
|
880
|
+
|
|
|
881
|
+(define-test float-ratio-float.denormal-low-above-halfway.single
|
|
|
882
|
+ (:tag :issues)
|
|
|
883
|
+ ;; ROUND-DENORMAL's `low > halfway' branch: 17/10 * least-positive
|
|
|
884
|
+ ;; (= 1.7 denormal-units), past halfway between 1 and 2, rounds up.
|
|
|
885
|
+ (let ((x (* 17/10 (expt 2 -149))))
|
|
|
886
|
+ (assert-equal #x00000002
|
|
|
887
|
+ (kernel:single-float-bits
|
|
|
888
|
+ (kernel::float-ratio-float x 'single-float))
|
|
|
889
|
+ x)))
|
|
|
890
|
+
|
|
|
891
|
+(define-test float-ratio-float.denormal-tie-to-even.single
|
|
|
892
|
+ (:tag :issues)
|
|
|
893
|
+ ;; ROUND-DENORMAL's tie path, REM = 0: exact halfway between two
|
|
|
894
|
+ ;; denormals rounds to even. 3/2 * least-positive ties between
|
|
|
895
|
+ ;; denormals 1 and 2; the even neighbour is 2.
|
|
|
896
|
+ (let ((x (* 3/2 (expt 2 -149))))
|
|
|
897
|
+ (assert-equal #x00000002
|
|
|
898
|
+ (kernel:single-float-bits
|
|
|
899
|
+ (kernel::float-ratio-float x 'single-float))
|
|
|
900
|
+ x))
|
|
|
901
|
+ ;; 5/2 * least-positive ties between 2 and 3; even is 2.
|
|
|
902
|
+ (let ((x (* 5/2 (expt 2 -149))))
|
|
|
903
|
+ (assert-equal #x00000002
|
|
|
904
|
+ (kernel:single-float-bits
|
|
|
905
|
+ (kernel::float-ratio-float x 'single-float))
|
|
|
906
|
+ x))
|
|
|
907
|
+ ;; 7/2 * least-positive ties between 3 and 4; even is 4.
|
|
|
908
|
+ (let ((x (* 7/2 (expt 2 -149))))
|
|
|
909
|
+ (assert-equal #x00000004
|
|
|
910
|
+ (kernel:single-float-bits
|
|
|
911
|
+ (kernel::float-ratio-float x 'single-float))
|
|
|
912
|
+ x))
|
|
|
913
|
+ ;; 1/2 * least-positive ties between 0 and 1; even is 0.
|
|
|
914
|
+ (let ((x (* 1/2 (expt 2 -149))))
|
|
|
915
|
+ (assert-equal #x00000000
|
|
|
916
|
+ (kernel:single-float-bits
|
|
|
917
|
+ (kernel::float-ratio-float x 'single-float))
|
|
|
918
|
+ x)))
|
|
|
919
|
+
|
|
|
920
|
+(define-test float-ratio-float.denormal-tie-with-sticky.single
|
|
|
921
|
+ (:tag :issues)
|
|
|
922
|
+ ;; ROUND-DENORMAL's tie path with REM != 0: when the loop's
|
|
|
923
|
+ ;; FRACTION-AND-GUARD reaches an exact halfway pattern but the
|
|
|
924
|
+ ;; division has a nonzero remainder, the rounding must go up because
|
|
|
925
|
+ ;; the original rational is strictly above halfway. 3/2 * least-
|
|
|
926
|
+ ;; positive + a tiny fraction of least-positive lands just past tie 1-2,
|
|
|
927
|
+ ;; rounds up to 2.
|
|
|
928
|
+ (let ((x (+ (* 3/2 (expt 2 -149))
|
|
|
929
|
+ (* (expt 2 -149) 1/1000000000))))
|
|
|
930
|
+ (assert-equal #x00000002
|
|
|
931
|
+ (kernel:single-float-bits
|
|
|
932
|
+ (kernel::float-ratio-float x 'single-float))
|
|
|
933
|
+ x))
|
|
|
934
|
+ ;; 1/2 + tiny: just past tie 0-1, rounds up to 1.
|
|
|
935
|
+ (let ((x (+ (* 1/2 (expt 2 -149))
|
|
|
936
|
+ (* (expt 2 -149) 1/1000000000))))
|
|
|
937
|
+ (assert-equal #x00000001
|
|
|
938
|
+ (kernel:single-float-bits
|
|
|
939
|
+ (kernel::float-ratio-float x 'single-float))
|
|
|
940
|
+ x)))
|
|
|
941
|
+
|
|
|
942
|
+(define-test float-ratio-float.denormal-excess.single
|
|
|
943
|
+ (:tag :issues)
|
|
|
944
|
+ ;; Exercise DENORMAL-EXCESS over a range of magnitudes. EXCESS
|
|
|
945
|
+ ;; varies inversely with the result's magnitude; each case has the
|
|
|
946
|
+ ;; result land on a chosen denormal so an off-by-one in the EXCESS
|
|
|
947
|
+ ;; computation would shift the result by a factor of two.
|
|
|
948
|
+ ;; EXCESS = 1: value near smallest normal; pick (2^23 - 1) * 2^-149,
|
|
|
949
|
+ ;; the largest denormal.
|
|
|
950
|
+ (let ((x (* (1- (expt 2 23)) (expt 2 -149))))
|
|
|
951
|
+ (assert-equal #x007fffff
|
|
|
952
|
+ (kernel:single-float-bits
|
|
|
953
|
+ (kernel::float-ratio-float x 'single-float))
|
|
|
954
|
+ x))
|
|
|
955
|
+ ;; EXCESS = 4: small denormal, mantissa 2^19.
|
|
|
956
|
+ (let ((x (expt 2 -130)))
|
|
|
957
|
+ (assert-equal (ash 1 19)
|
|
|
958
|
+ (kernel:single-float-bits
|
|
|
959
|
+ (kernel::float-ratio-float x 'single-float))
|
|
|
960
|
+ x))
|
|
|
961
|
+ ;; EXCESS = 21: very small denormal, mantissa 8.
|
|
|
962
|
+ (let ((x (* 8 (expt 2 -149))))
|
|
|
963
|
+ (assert-equal #x00000008
|
|
|
964
|
+ (kernel:single-float-bits
|
|
|
965
|
+ (kernel::float-ratio-float x 'single-float))
|
|
|
966
|
+ x))
|
|
|
967
|
+ ;; EXCESS = 23 (the maximum): only the bottom three denormals are
|
|
|
968
|
+ ;; reachable. 3 * least-positive gives mantissa 3.
|
|
|
969
|
+ (let ((x (* 3 (expt 2 -149))))
|
|
|
970
|
+ (assert-equal #x00000003
|
|
|
971
|
+ (kernel:single-float-bits
|
|
|
972
|
+ (kernel::float-ratio-float x 'single-float))
|
|
|
973
|
+ x)))
|
|
|
974
|
+
|
|
|
975
|
+(define-test float-ratio-float.denormal-carry-to-normal.single
|
|
|
976
|
+ (:tag :issues)
|
|
|
977
|
+ ;; DENORMAL-FROM-BITS's carry-into-smallest-normal branch. Rounding
|
|
|
978
|
+ ;; promotes the denormal mantissa to 2^(DIGITS-1), which doesn't fit
|
|
|
979
|
+ ;; in the denormal's stored mantissa width; the result must be the
|
|
|
980
|
+ ;; smallest normal (stored exponent = 1, mantissa = 0).
|
|
|
981
|
+ ;;
|
|
|
982
|
+ ;; (2^24 - 1)/2 * 2^-149 is an exact tie between the largest denormal
|
|
|
983
|
+ ;; (mantissa 2^23 - 1) and the smallest normal (2^-126); the latter
|
|
|
984
|
+ ;; has stored mantissa 0 which is even, so the tie rounds to it.
|
|
|
985
|
+ (let ((x (* (1- (expt 2 24)) 1/2 (expt 2 -149))))
|
|
|
986
|
+ (assert-equal #x00800000
|
|
|
987
|
+ (kernel:single-float-bits
|
|
|
988
|
+ (kernel::float-ratio-float x 'single-float))
|
|
|
989
|
+ x))
|
|
|
990
|
+ ;; Just past that tie, also rounds up to smallest normal.
|
|
|
991
|
+ (let ((x (+ (* (1- (expt 2 24)) 1/2 (expt 2 -149))
|
|
|
992
|
+ (* (expt 2 -149) 1/1000))))
|
|
|
993
|
+ (assert-equal #x00800000
|
|
|
994
|
+ (kernel:single-float-bits
|
|
|
995
|
+ (kernel::float-ratio-float x 'single-float))
|
|
|
996
|
+ x))
|
|
|
997
|
+ ;; Just below that tie, rounds down to the largest denormal.
|
|
|
998
|
+ (let ((x (- (* (1- (expt 2 24)) 1/2 (expt 2 -149))
|
|
|
999
|
+ (* (expt 2 -149) 1/1000))))
|
|
|
1000
|
+ (assert-equal #x007fffff
|
|
|
1001
|
+ (kernel:single-float-bits
|
|
|
1002
|
+ (kernel::float-ratio-float x 'single-float))
|
|
|
1003
|
+ x)))
|
|
|
1004
|
+
|
|
|
1005
|
+(define-test float-ratio-float.denormal-double-rounding.double
|
|
|
1006
|
+ (:tag :issues)
|
|
|
1007
|
+ ;; Double-float equivalents. Pick a rational that lands strictly
|
|
|
1008
|
+ ;; below halfway between two denormals after 53-bit rounding would
|
|
|
1009
|
+ ;; otherwise lift to the halfway position. Verify a few denormal
|
|
|
1010
|
+ ;; cases also work end-to-end through FLOAT-RATIO-FLOAT.
|
|
|
1011
|
+ ;;
|
|
|
1012
|
+ ;; 1.1d-322 -> mantissa #x16 (= 22).
|
|
|
1013
|
+ (assert-equal 0 (kernel:double-float-high-bits 1.1d-322))
|
|
|
1014
|
+ (assert-equal #x16 (kernel:double-float-low-bits 1.1d-322))
|
|
|
1015
|
+ ;; Tie-to-even, double: 3/2 * least-positive ties between denormals
|
|
|
1016
|
+ ;; 1 and 2; even neighbour is 2.
|
|
|
1017
|
+ (let ((x (* 3/2 (expt 2 -1074))))
|
|
|
1018
|
+ (assert-equal 0 (kernel:double-float-high-bits
|
|
|
1019
|
+ (kernel::float-ratio-float x 'double-float)))
|
|
|
1020
|
+ (assert-equal 2 (kernel:double-float-low-bits
|
|
|
1021
|
+ (kernel::float-ratio-float x 'double-float))))
|
|
|
1022
|
+ ;; Carry into smallest normal: (2^53 - 1)/2 * 2^-1074 exactly halfway
|
|
|
1023
|
+ ;; between the largest double denormal and the smallest normal;
|
|
|
1024
|
+ ;; rounds up to the smallest normal #x00100000_00000000.
|
|
|
1025
|
+ (let* ((x (* (1- (expt 2 53)) 1/2 (expt 2 -1074)))
|
|
|
1026
|
+ (r (kernel::float-ratio-float x 'double-float)))
|
|
|
1027
|
+ (assert-equal #x00100000 (kernel:double-float-high-bits r) x)
|
|
|
1028
|
+ (assert-equal 0 (kernel:double-float-low-bits r) x))) |