1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.numbers.core;
18
19 import java.math.BigDecimal;
20 import org.junit.jupiter.api.Assertions;
21 import org.junit.jupiter.api.Test;
22
23
24
25
26 class ExtendedPrecisionTest {
27 @Test
28 void testSplitAssumptions() {
29
30 final double scale = (1 << 27) + 1;
31
32 final double limit = 0x1.0p996;
33 Assertions.assertTrue(Double.isFinite(limit * scale));
34 Assertions.assertTrue(Double.isFinite(-limit * scale));
35
36 Assertions.assertEquals(Double.POSITIVE_INFINITY, limit * 2 * scale);
37 Assertions.assertEquals(Double.NEGATIVE_INFINITY, -limit * 2 * scale);
38
39
40 Assertions.assertTrue(Math.getExponent(2 * Math.sqrt(Double.MAX_VALUE)) - 2 > 508);
41 }
42
43 @Test
44 void testHighPartUnscaled() {
45 Assertions.assertEquals(Double.NaN, ExtendedPrecision.highPartUnscaled(Double.POSITIVE_INFINITY));
46 Assertions.assertEquals(Double.NaN, ExtendedPrecision.highPartUnscaled(Double.NEGATIVE_INFINITY));
47 Assertions.assertEquals(Double.NaN, ExtendedPrecision.highPartUnscaled(Double.NaN));
48
49 Assertions.assertEquals(Double.NaN, ExtendedPrecision.highPartUnscaled(Double.MAX_VALUE));
50 Assertions.assertEquals(Double.NaN, ExtendedPrecision.highPartUnscaled(-Double.MAX_VALUE));
51 }
52
53
54
55
56
57 @Test
58 void testProductLow() {
59 assertProductLow(0.0, 1.0, Math.nextDown(Double.MIN_NORMAL));
60 assertProductLow(0.0, -1.0, Math.nextDown(Double.MIN_NORMAL));
61 assertProductLow(Double.NaN, 1.0, Double.POSITIVE_INFINITY);
62 assertProductLow(Double.NaN, 1.0, Double.NEGATIVE_INFINITY);
63 assertProductLow(Double.NaN, 1.0, Double.NaN);
64 assertProductLow(0.0, 1.0, Double.MAX_VALUE);
65 assertProductLow(Double.NaN, 2.0, Double.MAX_VALUE);
66 }
67
68 private static void assertProductLow(double expected, double x, double y) {
69
70 Assertions.assertEquals(expected, ExtendedPrecision.productLow(x, y, x * y), 0.0);
71 }
72
73 @Test
74 void testIsNotNormal() {
75 for (double a : new double[] {Double.MAX_VALUE, 1.0, Double.MIN_NORMAL}) {
76 Assertions.assertFalse(ExtendedPrecision.isNotNormal(a));
77 Assertions.assertFalse(ExtendedPrecision.isNotNormal(-a));
78 }
79 for (double a : new double[] {Double.POSITIVE_INFINITY, 0.0,
80 Math.nextDown(Double.MIN_NORMAL), Double.NaN}) {
81 Assertions.assertTrue(ExtendedPrecision.isNotNormal(a));
82 Assertions.assertTrue(ExtendedPrecision.isNotNormal(-a));
83 }
84 }
85
86
87
88
89
90 @Test
91 void testSubNormalSplit() {
92 final double a = Double.longBitsToDouble(1L << 25);
93
94
95 final double hi1 = Double.longBitsToDouble(Double.doubleToRawLongBits(a) & ((-1L) << 27));
96 final double lo1 = a - hi1;
97 Assertions.assertEquals(0, hi1);
98 Assertions.assertEquals(a, lo1);
99 Assertions.assertFalse(Math.abs(hi1) > Math.abs(lo1));
100
101
102 final double hi2 = ExtendedPrecision.highPartUnscaled(a);
103 final double lo2 = a - hi2;
104 Assertions.assertEquals(a, hi2);
105 Assertions.assertEquals(0, lo2);
106
107 Assertions.assertTrue(Math.abs(hi2) > Math.abs(lo2));
108 }
109
110 @Test
111 void testSquareLowUnscaled() {
112 assertSquareLowUnscaled(0.0, 1.0);
113 assertSquareLowUnscaled(0.0, -1.0);
114 final double expected = new BigDecimal(Math.PI).pow(2)
115 .subtract(new BigDecimal(Math.PI * Math.PI)).doubleValue();
116 assertSquareLowUnscaled(expected, Math.PI);
117
118 assertSquareLowUnscaled(Double.NaN, Double.POSITIVE_INFINITY);
119 assertSquareLowUnscaled(Double.NaN, Double.NEGATIVE_INFINITY);
120 assertSquareLowUnscaled(Double.NaN, Double.NaN);
121 assertSquareLowUnscaled(Double.NaN, Double.MAX_VALUE);
122 }
123
124 private static void assertSquareLowUnscaled(final double expected, final double x) {
125 Assertions.assertEquals(expected, ExtendedPrecision.squareLowUnscaled(x, x * x));
126 }
127 }