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 org.junit.jupiter.api.Assertions;
20 import org.junit.jupiter.api.Test;
21
22
23
24
25
26 class EpsilonDoubleEquivalenceTest {
27 @Test
28 void testInvalidEpsilonValues() {
29
30 Assertions.assertThrows(IllegalArgumentException.class, () -> Precision.doubleEquivalenceOfEpsilon(-1d));
31
32 String msg;
33
34 msg = Assertions.assertThrows(IllegalArgumentException.class,
35 () -> Precision.doubleEquivalenceOfEpsilon(Double.NaN)).getMessage();
36 Assertions.assertEquals("Invalid epsilon value: NaN", msg);
37
38 msg = Assertions.assertThrows(IllegalArgumentException.class,
39 () -> Precision.doubleEquivalenceOfEpsilon(Double.POSITIVE_INFINITY)).getMessage();
40 Assertions.assertEquals("Invalid epsilon value: Infinity", msg);
41
42 msg = Assertions.assertThrows(IllegalArgumentException.class,
43 () -> Precision.doubleEquivalenceOfEpsilon(Double.NEGATIVE_INFINITY)).getMessage();
44 Assertions.assertEquals("Invalid epsilon value: -Infinity", msg);
45 }
46
47 @Test
48 void testSignum() {
49
50 final double eps = 1e-2;
51
52 final Precision.DoubleEquivalence cmp = Precision.doubleEquivalenceOfEpsilon(eps);
53
54
55 Assertions.assertEquals(Double.POSITIVE_INFINITY, 1 / cmp.signum(0.0), 0d);
56 Assertions.assertEquals(Double.NEGATIVE_INFINITY, 1 / cmp.signum(-0.0), 0d);
57
58 Assertions.assertEquals(Double.POSITIVE_INFINITY, 1 / cmp.signum(eps), 0d);
59 Assertions.assertEquals(Double.NEGATIVE_INFINITY, 1 / cmp.signum(-eps), 0d);
60
61 Assertions.assertEquals(1, cmp.signum(Math.nextUp(eps)), 0d);
62 Assertions.assertEquals(-1, cmp.signum(Math.nextDown(-eps)), 0d);
63
64 Assertions.assertTrue(Double.isNaN(cmp.signum(Double.NaN)));
65 Assertions.assertEquals(1, cmp.signum(Double.POSITIVE_INFINITY), 0d);
66 Assertions.assertEquals(-1, cmp.signum(Double.NEGATIVE_INFINITY), 0d);
67 }
68
69 @Test
70 void testCompare_simple() {
71
72 final Precision.DoubleEquivalence cmp = Precision.doubleEquivalenceOfEpsilon(1e-10);
73
74
75 Assertions.assertEquals(0, cmp.compare(1, 1));
76 Assertions.assertEquals(-1, cmp.compare(1, 2));
77 Assertions.assertEquals(1, cmp.compare(2, 1));
78
79 Assertions.assertEquals(0, cmp.compare(-1, -1));
80 Assertions.assertEquals(1, cmp.compare(-1, -2));
81 Assertions.assertEquals(-1, cmp.compare(-2, -1));
82 }
83
84 @Test
85 void testCompare_compareToZero() {
86
87 final double eps = 1e-2;
88
89 final Precision.DoubleEquivalence cmp = Precision.doubleEquivalenceOfEpsilon(eps);
90
91
92 Assertions.assertEquals(0, cmp.compare(0.0, 0.0));
93 Assertions.assertEquals(0, cmp.compare(+0.0, -0.0));
94 Assertions.assertEquals(0, cmp.compare(eps, -0.0));
95 Assertions.assertEquals(0, cmp.compare(+0.0, eps));
96
97 Assertions.assertEquals(0, cmp.compare(-eps, -0.0));
98 Assertions.assertEquals(0, cmp.compare(+0.0, -eps));
99
100 Assertions.assertEquals(-1, cmp.compare(0.0, 1.0));
101 Assertions.assertEquals(1, cmp.compare(1.0, 0.0));
102
103 Assertions.assertEquals(1, cmp.compare(0.0, -1.0));
104 Assertions.assertEquals(-1, cmp.compare(-1.0, 0.0));
105 }
106
107 @Test
108 void testCompare_compareNonZero() {
109
110 final double eps = 1e-5;
111 final double small = 1e-3;
112 final double big = 1e100;
113
114 final Precision.DoubleEquivalence cmp = Precision.doubleEquivalenceOfEpsilon(eps);
115
116
117 Assertions.assertEquals(0, cmp.compare(eps, 2 * eps));
118 Assertions.assertEquals(0, cmp.compare(-2 * eps, -eps));
119
120 Assertions.assertEquals(0, cmp.compare(small, small + (0.9 * eps)));
121 Assertions.assertEquals(0, cmp.compare(-small - (0.9 * eps), -small));
122
123 Assertions.assertEquals(0, cmp.compare(big, nextUp(big, 1)));
124 Assertions.assertEquals(0, cmp.compare(nextDown(-big, 1), -big));
125
126 Assertions.assertEquals(-1, cmp.compare(small, small + (1.1 * eps)));
127 Assertions.assertEquals(1, cmp.compare(-small, -small - (1.1 * eps)));
128
129 Assertions.assertEquals(-1, cmp.compare(big, nextUp(big, 2)));
130 Assertions.assertEquals(1, cmp.compare(-big, nextDown(-big, 2)));
131 }
132
133 @Test
134 void testCompare_NaN() {
135
136 final Precision.DoubleEquivalence cmp = Precision.doubleEquivalenceOfEpsilon(1e-6);
137
138
139 Assertions.assertEquals(-1, cmp.compare(0, Double.NaN));
140 Assertions.assertEquals(1, cmp.compare(Double.NaN, 0));
141 Assertions.assertEquals(0, cmp.compare(Double.NaN, Double.NaN));
142
143 Assertions.assertEquals(-1, cmp.compare(Double.POSITIVE_INFINITY, Double.NaN));
144 Assertions.assertEquals(1, cmp.compare(Double.NaN, Double.POSITIVE_INFINITY));
145
146 Assertions.assertEquals(-1, cmp.compare(Double.NEGATIVE_INFINITY, Double.NaN));
147 Assertions.assertEquals(1, cmp.compare(Double.NaN, Double.NEGATIVE_INFINITY));
148 }
149
150 @Test
151 void testCompare_infinity() {
152
153 final Precision.DoubleEquivalence cmp = Precision.doubleEquivalenceOfEpsilon(1e-6);
154
155
156 Assertions.assertEquals(-1, cmp.compare(0, Double.POSITIVE_INFINITY));
157 Assertions.assertEquals(1, cmp.compare(Double.POSITIVE_INFINITY, 0));
158 Assertions.assertEquals(0, cmp.compare(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY));
159
160 Assertions.assertEquals(1, cmp.compare(0, Double.NEGATIVE_INFINITY));
161 Assertions.assertEquals(-1, cmp.compare(Double.NEGATIVE_INFINITY, 0));
162 Assertions.assertEquals(0, cmp.compare(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY));
163 }
164
165 @Test
166 void testEq() {
167
168 final double eps = Math.ulp(1.0);
169 final double twoEps = 2 * eps;
170 final Precision.DoubleEquivalence cmp = Precision.doubleEquivalenceOfEpsilon(eps);
171
172
173 Assertions.assertTrue(cmp.eq(0.0, 0.0));
174
175 Assertions.assertTrue(cmp.eq(1.0, 1.0));
176 Assertions.assertTrue(cmp.eq(1.0, 1.0 + eps));
177 Assertions.assertTrue(cmp.eq(1.0, 1.0 - eps));
178 Assertions.assertFalse(cmp.eq(1.0, 1.0 + twoEps));
179 Assertions.assertFalse(cmp.eq(1.0, 1.0 - twoEps));
180
181 Assertions.assertTrue(cmp.eq(-1.0, -1.0));
182 Assertions.assertTrue(cmp.eq(-1.0, -1.0 + eps));
183 Assertions.assertTrue(cmp.eq(-1.0, -1.0 - eps));
184 Assertions.assertFalse(cmp.eq(-1.0, -1.0 + twoEps));
185 Assertions.assertFalse(cmp.eq(-1.0, -1.0 - twoEps));
186 }
187
188 @Test
189 void testEqZero() {
190
191 final double eps = 1e-6;
192 final Precision.DoubleEquivalence cmp = Precision.doubleEquivalenceOfEpsilon(eps);
193
194
195 Assertions.assertTrue(cmp.eqZero(0.0));
196
197 Assertions.assertFalse(cmp.eqZero(Math.nextUp(eps)));
198 Assertions.assertFalse(cmp.eqZero(Math.nextDown(-eps)));
199 }
200
201 @Test
202 void testLt() {
203
204 final Precision.DoubleEquivalence cmp = Precision.doubleEquivalenceOfEpsilon(1e-6);
205
206
207 Assertions.assertTrue(cmp.lt(1, 2));
208 Assertions.assertTrue(cmp.lt(-2, -1));
209
210 Assertions.assertFalse(cmp.lt(1, 1));
211 Assertions.assertFalse(cmp.lt(-1, -1));
212 Assertions.assertFalse(cmp.lt(2, 1));
213 Assertions.assertFalse(cmp.lt(-1, -2));
214 }
215
216 @Test
217 void testLte() {
218
219 final Precision.DoubleEquivalence cmp = Precision.doubleEquivalenceOfEpsilon(1e-6);
220
221
222 Assertions.assertTrue(cmp.lte(1, 2));
223 Assertions.assertTrue(cmp.lte(-2, -1));
224 Assertions.assertTrue(cmp.lte(1, 1));
225 Assertions.assertTrue(cmp.lte(-1, -1));
226
227 Assertions.assertFalse(cmp.lte(2, 1));
228 Assertions.assertFalse(cmp.lte(-1, -2));
229 }
230
231 @Test
232 void testGt() {
233
234 final Precision.DoubleEquivalence cmp = Precision.doubleEquivalenceOfEpsilon(1e-6);
235
236
237 Assertions.assertTrue(cmp.gt(2, 1));
238 Assertions.assertTrue(cmp.gt(-1, -2));
239
240 Assertions.assertFalse(cmp.gt(1, 1));
241 Assertions.assertFalse(cmp.gt(-1, -1));
242 Assertions.assertFalse(cmp.gt(1, 2));
243 Assertions.assertFalse(cmp.gt(-2, -1));
244 }
245
246 @Test
247 void testGte() {
248
249 final Precision.DoubleEquivalence cmp = Precision.doubleEquivalenceOfEpsilon(1e-6);
250
251
252 Assertions.assertTrue(cmp.gte(2, 1));
253 Assertions.assertTrue(cmp.gte(-1, -2));
254 Assertions.assertTrue(cmp.gte(1, 1));
255 Assertions.assertTrue(cmp.gte(-1, -1));
256
257 Assertions.assertFalse(cmp.gte(1, 2));
258 Assertions.assertFalse(cmp.gte(-2, -1));
259 }
260
261
262
263
264
265
266
267
268 private static double nextUp(final double n, final int count) {
269 double result = n;
270 for (int i = 0; i < count; ++i) {
271 result = Math.nextUp(result);
272 }
273
274 return result;
275 }
276
277
278
279
280
281
282
283
284 private static double nextDown(final double n, final int count) {
285 double result = n;
286 for (int i = 0; i < count; ++i) {
287 result = Math.nextDown(result);
288 }
289
290 return result;
291 }
292 }