View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements. See the NOTICE file distributed with this
4    * work for additional information regarding copyright ownership. The ASF
5    * licenses this file to You under the Apache License, Version 2.0 (the
6    * "License"); you may not use this file except in compliance with the License.
7    * You may obtain a copy of the License at
8    * https://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
9    * or agreed to in writing, software distributed under the License is
10   * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
11   * KIND, either express or implied. See the License for the specific language
12   * governing permissions and limitations under the License.
13   */
14  package org.hipparchus.util;
15  
16  import org.hipparchus.UnitTestUtils;
17  import org.hipparchus.exception.MathRuntimeException;
18  import org.junit.jupiter.api.Test;
19  
20  import java.math.RoundingMode;
21  
22  import static org.junit.jupiter.api.Assertions.assertEquals;
23  import static org.junit.jupiter.api.Assertions.assertFalse;
24  import static org.junit.jupiter.api.Assertions.assertTrue;
25  import static org.junit.jupiter.api.Assertions.fail;
26  
27  /**
28   * Test cases for the {@link Precision} class.
29   */
30  class PrecisionTest {
31      @Test
32      void testEqualsWithRelativeTolerance() {
33          assertTrue(Precision.equalsWithRelativeTolerance(0d, 0d, 0d));
34          assertTrue(Precision.equalsWithRelativeTolerance(0d, 1 / Double.NEGATIVE_INFINITY, 0d));
35  
36          final double eps = 1e-14;
37          assertFalse(Precision.equalsWithRelativeTolerance(1.987654687654968, 1.987654687654988, eps));
38          assertTrue(Precision.equalsWithRelativeTolerance(1.987654687654968, 1.987654687654987, eps));
39          assertFalse(Precision.equalsWithRelativeTolerance(1.987654687654968, 1.987654687654948, eps));
40          assertTrue(Precision.equalsWithRelativeTolerance(1.987654687654968, 1.987654687654949, eps));
41  
42          assertFalse(Precision.equalsWithRelativeTolerance(Precision.SAFE_MIN, 0.0, eps));
43  
44          assertFalse(Precision.equalsWithRelativeTolerance(1.0000000000001e-300, 1e-300, eps));
45          assertTrue(Precision.equalsWithRelativeTolerance(1.00000000000001e-300, 1e-300, eps));
46  
47          assertFalse(Precision.equalsWithRelativeTolerance(Double.NEGATIVE_INFINITY, 1.23, eps));
48          assertFalse(Precision.equalsWithRelativeTolerance(Double.POSITIVE_INFINITY, 1.23, eps));
49  
50          assertTrue(Precision.equalsWithRelativeTolerance(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, eps));
51          assertTrue(Precision.equalsWithRelativeTolerance(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, eps));
52          assertFalse(Precision.equalsWithRelativeTolerance(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, eps));
53  
54          assertFalse(Precision.equalsWithRelativeTolerance(Double.NaN, 1.23, eps));
55          assertFalse(Precision.equalsWithRelativeTolerance(Double.NaN, Double.NaN, eps));
56      }
57  
58      @Test
59      void testEqualsIncludingNaN() {
60          double[] testArray = {
61              Double.NaN,
62              Double.POSITIVE_INFINITY,
63              Double.NEGATIVE_INFINITY,
64              1d,
65              0d };
66          for (int i = 0; i < testArray.length; i++) {
67              for (int j = 0; j < testArray.length; j++) {
68                  if (i == j) {
69                      assertTrue(Precision.equalsIncludingNaN(testArray[i], testArray[j]));
70                      assertTrue(Precision.equalsIncludingNaN(testArray[j], testArray[i]));
71                  } else {
72                      assertFalse(Precision.equalsIncludingNaN(testArray[i], testArray[j]));
73                      assertFalse(Precision.equalsIncludingNaN(testArray[j], testArray[i]));
74                  }
75              }
76          }
77      }
78  
79      @Test
80      void testEqualsWithAllowedDelta() {
81          assertTrue(Precision.equals(153.0000, 153.0000, .0625));
82          assertTrue(Precision.equals(153.0000, 153.0625, .0625));
83          assertTrue(Precision.equals(152.9375, 153.0000, .0625));
84          assertFalse(Precision.equals(153.0000, 153.0625, .0624));
85          assertFalse(Precision.equals(152.9374, 153.0000, .0625));
86          assertFalse(Precision.equals(Double.NaN, Double.NaN, 1.0));
87          assertTrue(Precision.equals(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, 1.0));
88          assertTrue(Precision.equals(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, 1.0));
89          assertFalse(Precision.equals(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, 1.0));
90      }
91  
92      @Test
93      void testMath475() {
94          final double a = 1.7976931348623182E16;
95          final double b = FastMath.nextUp(a);
96  
97          double diff = FastMath.abs(a - b);
98          // Because they are adjacent floating point numbers, "a" and "b" are
99          // considered equal even though the allowed error is smaller than
100         // their difference.
101         assertTrue(Precision.equals(a, b, 0.5 * diff));
102 
103         final double c = FastMath.nextUp(b);
104         diff = FastMath.abs(a - c);
105         // Because "a" and "c" are not adjacent, the tolerance is taken into
106         // account for assessing equality.
107         assertTrue(Precision.equals(a, c, diff));
108         assertFalse(Precision.equals(a, c, (1 - 1e-16) * diff));
109     }
110 
111     @Test
112     void testEqualsIncludingNaNWithAllowedDelta() {
113         assertTrue(Precision.equalsIncludingNaN(153.0000, 153.0000, .0625));
114         assertTrue(Precision.equalsIncludingNaN(153.0000, 153.0625, .0625));
115         assertTrue(Precision.equalsIncludingNaN(152.9375, 153.0000, .0625));
116         assertTrue(Precision.equalsIncludingNaN(Double.NaN, Double.NaN, 1.0));
117         assertTrue(Precision.equalsIncludingNaN(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, 1.0));
118         assertTrue(Precision.equalsIncludingNaN(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, 1.0));
119         assertFalse(Precision.equalsIncludingNaN(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, 1.0));
120         assertFalse(Precision.equalsIncludingNaN(153.0000, 153.0625, .0624));
121         assertFalse(Precision.equalsIncludingNaN(152.9374, 153.0000, .0625));
122     }
123 
124     // Tests for floating point equality
125     @Test
126     void testFloatEqualsWithAllowedUlps() {
127         assertTrue(Precision.equals(0.0f, -0.0f),"+0.0f == -0.0f");
128         assertTrue(Precision.equals(0.0f, -0.0f, 1),"+0.0f == -0.0f (1 ulp)");
129         float oneFloat = 1.0f;
130         assertTrue(Precision.equals(oneFloat, Float.intBitsToFloat(1 + Float.floatToIntBits(oneFloat))),"1.0f == 1.0f + 1 ulp");
131         assertTrue(Precision.equals(oneFloat, Float.intBitsToFloat(1 + Float.floatToIntBits(oneFloat)), 1),"1.0f == 1.0f + 1 ulp (1 ulp)");
132         assertFalse(Precision.equals(oneFloat, Float.intBitsToFloat(2 + Float.floatToIntBits(oneFloat)), 1),"1.0f != 1.0f + 2 ulp (1 ulp)");
133 
134         assertTrue(Precision.equals(153.0f, 153.0f, 1));
135 
136         // These tests need adjusting for floating point precision
137 //        Assertions.assertTrue(Precision.equals(153.0f, 153.00000000000003f, 1));
138 //        Assertions.assertFalse(Precision.equals(153.0f, 153.00000000000006f, 1));
139 //        Assertions.assertTrue(Precision.equals(153.0f, 152.99999999999997f, 1));
140 //        Assertions.assertFalse(Precision.equals(153f, 152.99999999999994f, 1));
141 //
142 //        Assertions.assertTrue(Precision.equals(-128.0f, -127.99999999999999f, 1));
143 //        Assertions.assertFalse(Precision.equals(-128.0f, -127.99999999999997f, 1));
144 //        Assertions.assertTrue(Precision.equals(-128.0f, -128.00000000000003f, 1));
145 //        Assertions.assertFalse(Precision.equals(-128.0f, -128.00000000000006f, 1));
146 
147         assertTrue(Precision.equals(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY, 1));
148         assertTrue(Precision.equals(Double.MAX_VALUE, Float.POSITIVE_INFINITY, 1));
149 
150         assertTrue(Precision.equals(Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY, 1));
151         assertTrue(Precision.equals(-Float.MAX_VALUE, Float.NEGATIVE_INFINITY, 1));
152 
153         assertFalse(Precision.equals(Float.NaN, Float.NaN, 1));
154         assertFalse(Precision.equals(Float.NaN, Float.NaN, 0));
155         assertFalse(Precision.equals(Float.NaN, 0, 0));
156         assertFalse(Precision.equals(Float.NaN, Float.POSITIVE_INFINITY, 0));
157         assertFalse(Precision.equals(Float.NaN, Float.NEGATIVE_INFINITY, 0));
158 
159         assertFalse(Precision.equals(Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY, 100000));
160     }
161 
162     @Test
163     void testEqualsWithAllowedUlps() {
164         assertTrue(Precision.equals(0.0, -0.0, 1));
165 
166         assertTrue(Precision.equals(1.0, 1 + FastMath.ulp(1d), 1));
167         assertFalse(Precision.equals(1.0, 1 + 2 * FastMath.ulp(1d), 1));
168 
169         final double nUp1 = FastMath.nextAfter(1d, Double.POSITIVE_INFINITY);
170         final double nnUp1 = FastMath.nextAfter(nUp1, Double.POSITIVE_INFINITY);
171         assertTrue(Precision.equals(1.0, nUp1, 1));
172         assertTrue(Precision.equals(nUp1, nnUp1, 1));
173         assertFalse(Precision.equals(1.0, nnUp1, 1));
174 
175         assertTrue(Precision.equals(0.0, FastMath.ulp(0d), 1));
176         assertTrue(Precision.equals(0.0, -FastMath.ulp(0d), 1));
177 
178         assertTrue(Precision.equals(153.0, 153.0, 1));
179 
180         assertTrue(Precision.equals(153.0, 153.00000000000003, 1));
181         assertFalse(Precision.equals(153.0, 153.00000000000006, 1));
182         assertTrue(Precision.equals(153.0, 152.99999999999997, 1));
183         assertFalse(Precision.equals(153, 152.99999999999994, 1));
184 
185         assertTrue(Precision.equals(-128.0, -127.99999999999999, 1));
186         assertFalse(Precision.equals(-128.0, -127.99999999999997, 1));
187         assertTrue(Precision.equals(-128.0, -128.00000000000003, 1));
188         assertFalse(Precision.equals(-128.0, -128.00000000000006, 1));
189 
190         assertTrue(Precision.equals(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, 1));
191         assertTrue(Precision.equals(Double.MAX_VALUE, Double.POSITIVE_INFINITY, 1));
192 
193         assertTrue(Precision.equals(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, 1));
194         assertTrue(Precision.equals(-Double.MAX_VALUE, Double.NEGATIVE_INFINITY, 1));
195 
196         assertFalse(Precision.equals(Double.NaN, Double.NaN, 1));
197         assertFalse(Precision.equals(Double.NaN, Double.NaN, 0));
198         assertFalse(Precision.equals(Double.NaN, 0, 0));
199         assertFalse(Precision.equals(Double.NaN, Double.POSITIVE_INFINITY, 0));
200         assertFalse(Precision.equals(Double.NaN, Double.NEGATIVE_INFINITY, 0));
201 
202         assertFalse(Precision.equals(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, 100000));
203     }
204 
205     @Test
206     void testEqualsIncludingNaNWithAllowedUlps() {
207         assertTrue(Precision.equalsIncludingNaN(0.0, -0.0, 1));
208 
209         assertTrue(Precision.equalsIncludingNaN(1.0, 1 + FastMath.ulp(1d), 1));
210         assertFalse(Precision.equalsIncludingNaN(1.0, 1 + 2 * FastMath.ulp(1d), 1));
211 
212         final double nUp1 = FastMath.nextAfter(1d, Double.POSITIVE_INFINITY);
213         final double nnUp1 = FastMath.nextAfter(nUp1, Double.POSITIVE_INFINITY);
214         assertTrue(Precision.equalsIncludingNaN(1.0, nUp1, 1));
215         assertTrue(Precision.equalsIncludingNaN(nUp1, nnUp1, 1));
216         assertFalse(Precision.equalsIncludingNaN(1.0, nnUp1, 1));
217 
218         assertTrue(Precision.equalsIncludingNaN(0.0, FastMath.ulp(0d), 1));
219         assertTrue(Precision.equalsIncludingNaN(0.0, -FastMath.ulp(0d), 1));
220 
221         assertTrue(Precision.equalsIncludingNaN(153.0, 153.0, 1));
222 
223         assertTrue(Precision.equalsIncludingNaN(153.0, 153.00000000000003, 1));
224         assertFalse(Precision.equalsIncludingNaN(153.0, 153.00000000000006, 1));
225         assertTrue(Precision.equalsIncludingNaN(153.0, 152.99999999999997, 1));
226         assertFalse(Precision.equalsIncludingNaN(153, 152.99999999999994, 1));
227 
228         assertTrue(Precision.equalsIncludingNaN(-128.0, -127.99999999999999, 1));
229         assertFalse(Precision.equalsIncludingNaN(-128.0, -127.99999999999997, 1));
230         assertTrue(Precision.equalsIncludingNaN(-128.0, -128.00000000000003, 1));
231         assertFalse(Precision.equalsIncludingNaN(-128.0, -128.00000000000006, 1));
232 
233         assertTrue(Precision.equalsIncludingNaN(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, 1));
234         assertTrue(Precision.equalsIncludingNaN(Double.MAX_VALUE, Double.POSITIVE_INFINITY, 1));
235 
236         assertTrue(Precision.equalsIncludingNaN(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, 1));
237         assertTrue(Precision.equalsIncludingNaN(-Double.MAX_VALUE, Double.NEGATIVE_INFINITY, 1));
238 
239         assertTrue(Precision.equalsIncludingNaN(Double.NaN, Double.NaN, 1));
240 
241         assertFalse(Precision.equalsIncludingNaN(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, 100000));
242     }
243 
244     @Test
245     void testCompareToEpsilon() {
246         assertEquals(0, Precision.compareTo(152.33, 152.32, .011));
247         assertTrue(Precision.compareTo(152.308, 152.32, .011) < 0);
248         assertTrue(Precision.compareTo(152.33, 152.318, .011) > 0);
249         assertEquals(0, Precision.compareTo(Double.MIN_VALUE, +0.0, Double.MIN_VALUE));
250         assertEquals(0, Precision.compareTo(Double.MIN_VALUE, -0.0, Double.MIN_VALUE));
251     }
252 
253     @Test
254     void testCompareToMaxUlps() {
255         double a     = 152.32;
256         double delta = FastMath.ulp(a);
257         for (int i = 0; i <= 10; ++i) {
258             if (i <= 5) {
259                 assertEquals( 0, Precision.compareTo(a, a + i * delta, 5));
260                 assertEquals( 0, Precision.compareTo(a, a - i * delta, 5));
261             } else {
262                 assertEquals(-1, Precision.compareTo(a, a + i * delta, 5));
263                 assertEquals(+1, Precision.compareTo(a, a - i * delta, 5));
264             }
265         }
266 
267         assertEquals( 0, Precision.compareTo(-0.0, 0.0, 0));
268 
269         assertEquals(-1, Precision.compareTo(-Double.MIN_VALUE, -0.0, 0));
270         assertEquals( 0, Precision.compareTo(-Double.MIN_VALUE, -0.0, 1));
271         assertEquals(-1, Precision.compareTo(-Double.MIN_VALUE, +0.0, 0));
272         assertEquals( 0, Precision.compareTo(-Double.MIN_VALUE, +0.0, 1));
273 
274         assertEquals(+1, Precision.compareTo( Double.MIN_VALUE, -0.0, 0));
275         assertEquals( 0, Precision.compareTo( Double.MIN_VALUE, -0.0, 1));
276         assertEquals(+1, Precision.compareTo( Double.MIN_VALUE, +0.0, 0));
277         assertEquals( 0, Precision.compareTo( Double.MIN_VALUE, +0.0, 1));
278 
279         assertEquals(-1, Precision.compareTo(-Double.MIN_VALUE, Double.MIN_VALUE, 0));
280         assertEquals(-1, Precision.compareTo(-Double.MIN_VALUE, Double.MIN_VALUE, 1));
281         assertEquals( 0, Precision.compareTo(-Double.MIN_VALUE, Double.MIN_VALUE, 2));
282 
283         assertEquals( 0, Precision.compareTo(Double.MAX_VALUE, Double.POSITIVE_INFINITY, 1));
284         assertEquals(-1, Precision.compareTo(Double.MAX_VALUE, Double.POSITIVE_INFINITY, 0));
285 
286         assertEquals(+1, Precision.compareTo(Double.MAX_VALUE, Double.NaN, Integer.MAX_VALUE));
287         assertEquals(+1, Precision.compareTo(Double.NaN, Double.MAX_VALUE, Integer.MAX_VALUE));
288     }
289 
290     @Test
291     void testRoundDouble() {
292         double x = 1.234567890;
293         assertEquals(1.23, Precision.round(x, 2), 0.0);
294         assertEquals(1.235, Precision.round(x, 3), 0.0);
295         assertEquals(1.2346, Precision.round(x, 4), 0.0);
296 
297         // JIRA MATH-151
298         assertEquals(39.25, Precision.round(39.245, 2), 0.0);
299         assertEquals(39.24, Precision.round(39.245, 2, RoundingMode.DOWN), 0.0);
300         double xx = 39.0;
301         xx += 245d / 1000d;
302         assertEquals(39.25, Precision.round(xx, 2), 0.0);
303 
304         // BZ 35904
305         assertEquals(30.1d, Precision.round(30.095d, 2), 0.0d);
306         assertEquals(30.1d, Precision.round(30.095d, 1), 0.0d);
307         assertEquals(33.1d, Precision.round(33.095d, 1), 0.0d);
308         assertEquals(33.1d, Precision.round(33.095d, 2), 0.0d);
309         assertEquals(50.09d, Precision.round(50.085d, 2), 0.0d);
310         assertEquals(50.19d, Precision.round(50.185d, 2), 0.0d);
311         assertEquals(50.01d, Precision.round(50.005d, 2), 0.0d);
312         assertEquals(30.01d, Precision.round(30.005d, 2), 0.0d);
313         assertEquals(30.65d, Precision.round(30.645d, 2), 0.0d);
314 
315         assertEquals(1.24, Precision.round(x, 2, RoundingMode.CEILING), 0.0);
316         assertEquals(1.235, Precision.round(x, 3, RoundingMode.CEILING), 0.0);
317         assertEquals(1.2346, Precision.round(x, 4, RoundingMode.CEILING), 0.0);
318         assertEquals(-1.23, Precision.round(-x, 2, RoundingMode.CEILING), 0.0);
319         assertEquals(-1.234, Precision.round(-x, 3, RoundingMode.CEILING), 0.0);
320         assertEquals(-1.2345, Precision.round(-x, 4, RoundingMode.CEILING), 0.0);
321 
322         assertEquals(1.23, Precision.round(x, 2, RoundingMode.DOWN), 0.0);
323         assertEquals(1.234, Precision.round(x, 3, RoundingMode.DOWN), 0.0);
324         assertEquals(1.2345, Precision.round(x, 4, RoundingMode.DOWN), 0.0);
325         assertEquals(-1.23, Precision.round(-x, 2, RoundingMode.DOWN), 0.0);
326         assertEquals(-1.234, Precision.round(-x, 3, RoundingMode.DOWN), 0.0);
327         assertEquals(-1.2345, Precision.round(-x, 4, RoundingMode.DOWN), 0.0);
328 
329         assertEquals(1.23, Precision.round(x, 2, RoundingMode.FLOOR), 0.0);
330         assertEquals(1.234, Precision.round(x, 3, RoundingMode.FLOOR), 0.0);
331         assertEquals(1.2345, Precision.round(x, 4, RoundingMode.FLOOR), 0.0);
332         assertEquals(-1.24, Precision.round(-x, 2, RoundingMode.FLOOR), 0.0);
333         assertEquals(-1.235, Precision.round(-x, 3, RoundingMode.FLOOR), 0.0);
334         assertEquals(-1.2346, Precision.round(-x, 4, RoundingMode.FLOOR), 0.0);
335 
336         assertEquals(1.23, Precision.round(x, 2, RoundingMode.HALF_DOWN), 0.0);
337         assertEquals(1.235, Precision.round(x, 3, RoundingMode.HALF_DOWN), 0.0);
338         assertEquals(1.2346, Precision.round(x, 4, RoundingMode.HALF_DOWN), 0.0);
339         assertEquals(-1.23, Precision.round(-x, 2, RoundingMode.HALF_DOWN), 0.0);
340         assertEquals(-1.235, Precision.round(-x, 3, RoundingMode.HALF_DOWN), 0.0);
341         assertEquals(-1.2346, Precision.round(-x, 4, RoundingMode.HALF_DOWN), 0.0);
342         assertEquals(1.234, Precision.round(1.2345, 3, RoundingMode.HALF_DOWN), 0.0);
343         assertEquals(-1.234, Precision.round(-1.2345, 3, RoundingMode.HALF_DOWN), 0.0);
344 
345         assertEquals(1.23, Precision.round(x, 2, RoundingMode.HALF_EVEN), 0.0);
346         assertEquals(1.235, Precision.round(x, 3, RoundingMode.HALF_EVEN), 0.0);
347         assertEquals(1.2346, Precision.round(x, 4, RoundingMode.HALF_EVEN), 0.0);
348         assertEquals(-1.23, Precision.round(-x, 2, RoundingMode.HALF_EVEN), 0.0);
349         assertEquals(-1.235, Precision.round(-x, 3, RoundingMode.HALF_EVEN), 0.0);
350         assertEquals(-1.2346, Precision.round(-x, 4, RoundingMode.HALF_EVEN), 0.0);
351         assertEquals(1.234, Precision.round(1.2345, 3, RoundingMode.HALF_EVEN), 0.0);
352         assertEquals(-1.234, Precision.round(-1.2345, 3, RoundingMode.HALF_EVEN), 0.0);
353         assertEquals(1.236, Precision.round(1.2355, 3, RoundingMode.HALF_EVEN), 0.0);
354         assertEquals(-1.236, Precision.round(-1.2355, 3, RoundingMode.HALF_EVEN), 0.0);
355 
356         assertEquals(1.23, Precision.round(x, 2, RoundingMode.HALF_UP), 0.0);
357         assertEquals(1.235, Precision.round(x, 3, RoundingMode.HALF_UP), 0.0);
358         assertEquals(1.2346, Precision.round(x, 4, RoundingMode.HALF_UP), 0.0);
359         assertEquals(-1.23, Precision.round(-x, 2, RoundingMode.HALF_UP), 0.0);
360         assertEquals(-1.235, Precision.round(-x, 3, RoundingMode.HALF_UP), 0.0);
361         assertEquals(-1.2346, Precision.round(-x, 4, RoundingMode.HALF_UP), 0.0);
362         assertEquals(1.235, Precision.round(1.2345, 3, RoundingMode.HALF_UP), 0.0);
363         assertEquals(-1.235, Precision.round(-1.2345, 3, RoundingMode.HALF_UP), 0.0);
364 
365         assertEquals(-1.23, Precision.round(-1.23, 2, RoundingMode.UNNECESSARY), 0.0);
366         assertEquals(1.23, Precision.round(1.23, 2, RoundingMode.UNNECESSARY), 0.0);
367 
368         try {
369             Precision.round(1.234, 2, RoundingMode.UNNECESSARY);
370             fail();
371         } catch (ArithmeticException ex) {
372             // expected
373         }
374 
375         assertEquals(1.24, Precision.round(x, 2, RoundingMode.UP), 0.0);
376         assertEquals(1.235, Precision.round(x, 3, RoundingMode.UP), 0.0);
377         assertEquals(1.2346, Precision.round(x, 4, RoundingMode.UP), 0.0);
378         assertEquals(-1.24, Precision.round(-x, 2, RoundingMode.UP), 0.0);
379         assertEquals(-1.235, Precision.round(-x, 3, RoundingMode.UP), 0.0);
380         assertEquals(-1.2346, Precision.round(-x, 4, RoundingMode.UP), 0.0);
381 
382         // MATH-151
383         assertEquals(39.25, Precision.round(39.245, 2, RoundingMode.HALF_UP), 0.0);
384 
385         // special values
386         UnitTestUtils.customAssertEquals(Double.NaN, Precision.round(Double.NaN, 2), 0.0);
387         assertEquals(0.0, Precision.round(0.0, 2), 0.0);
388         assertEquals(Double.POSITIVE_INFINITY, Precision.round(Double.POSITIVE_INFINITY, 2), 0.0);
389         assertEquals(Double.NEGATIVE_INFINITY, Precision.round(Double.NEGATIVE_INFINITY, 2), 0.0);
390         // comparison of positive and negative zero is not possible -> always equal thus do string comparison
391         assertEquals("-0.0", Double.toString(Precision.round(-0.0, 0)));
392         assertEquals("-0.0", Double.toString(Precision.round(-1e-10, 0)));
393     }
394 
395     @Test
396     void testRoundFloat() {
397         float x = 1.234567890f;
398         assertEquals(1.23f, Precision.round(x, 2), 0.0);
399         assertEquals(1.235f, Precision.round(x, 3), 0.0);
400         assertEquals(1.2346f, Precision.round(x, 4), 0.0);
401 
402         // BZ 35904
403         assertEquals(30.1f, Precision.round(30.095f, 2), 0.0f);
404         assertEquals(30.1f, Precision.round(30.095f, 1), 0.0f);
405         assertEquals(50.09f, Precision.round(50.085f, 2), 0.0f);
406         assertEquals(50.19f, Precision.round(50.185f, 2), 0.0f);
407         assertEquals(50.01f, Precision.round(50.005f, 2), 0.0f);
408         assertEquals(30.01f, Precision.round(30.005f, 2), 0.0f);
409         assertEquals(30.65f, Precision.round(30.645f, 2), 0.0f);
410 
411         assertEquals(1.24f, Precision.round(x, 2, RoundingMode.CEILING), 0.0);
412         assertEquals(1.235f, Precision.round(x, 3, RoundingMode.CEILING), 0.0);
413         assertEquals(1.2346f, Precision.round(x, 4, RoundingMode.CEILING), 0.0);
414         assertEquals(-1.23f, Precision.round(-x, 2, RoundingMode.CEILING), 0.0);
415         assertEquals(-1.234f, Precision.round(-x, 3, RoundingMode.CEILING), 0.0);
416         assertEquals(-1.2345f, Precision.round(-x, 4, RoundingMode.CEILING), 0.0);
417 
418         assertEquals(1.23f, Precision.round(x, 2, RoundingMode.DOWN), 0.0);
419         assertEquals(1.234f, Precision.round(x, 3, RoundingMode.DOWN), 0.0);
420         assertEquals(1.2345f, Precision.round(x, 4, RoundingMode.DOWN), 0.0);
421         assertEquals(-1.23f, Precision.round(-x, 2, RoundingMode.DOWN), 0.0);
422         assertEquals(-1.234f, Precision.round(-x, 3, RoundingMode.DOWN), 0.0);
423         assertEquals(-1.2345f, Precision.round(-x, 4, RoundingMode.DOWN), 0.0);
424 
425         assertEquals(1.23f, Precision.round(x, 2, RoundingMode.FLOOR), 0.0);
426         assertEquals(1.234f, Precision.round(x, 3, RoundingMode.FLOOR), 0.0);
427         assertEquals(1.2345f, Precision.round(x, 4, RoundingMode.FLOOR), 0.0);
428         assertEquals(-1.24f, Precision.round(-x, 2, RoundingMode.FLOOR), 0.0);
429         assertEquals(-1.235f, Precision.round(-x, 3, RoundingMode.FLOOR), 0.0);
430         assertEquals(-1.2346f, Precision.round(-x, 4, RoundingMode.FLOOR), 0.0);
431 
432         assertEquals(1.23f, Precision.round(x, 2, RoundingMode.HALF_DOWN), 0.0);
433         assertEquals(1.235f, Precision.round(x, 3, RoundingMode.HALF_DOWN), 0.0);
434         assertEquals(1.2346f, Precision.round(x, 4, RoundingMode.HALF_DOWN), 0.0);
435         assertEquals(-1.23f, Precision.round(-x, 2, RoundingMode.HALF_DOWN), 0.0);
436         assertEquals(-1.235f, Precision.round(-x, 3, RoundingMode.HALF_DOWN), 0.0);
437         assertEquals(-1.2346f, Precision.round(-x, 4, RoundingMode.HALF_DOWN), 0.0);
438         assertEquals(1.234f, Precision.round(1.2345f, 3, RoundingMode.HALF_DOWN), 0.0);
439         assertEquals(-1.234f, Precision.round(-1.2345f, 3, RoundingMode.HALF_DOWN), 0.0);
440 
441         assertEquals(1.23f, Precision.round(x, 2, RoundingMode.HALF_EVEN), 0.0);
442         assertEquals(1.235f, Precision.round(x, 3, RoundingMode.HALF_EVEN), 0.0);
443         assertEquals(1.2346f, Precision.round(x, 4, RoundingMode.HALF_EVEN), 0.0);
444         assertEquals(-1.23f, Precision.round(-x, 2, RoundingMode.HALF_EVEN), 0.0);
445         assertEquals(-1.235f, Precision.round(-x, 3, RoundingMode.HALF_EVEN), 0.0);
446         assertEquals(-1.2346f, Precision.round(-x, 4, RoundingMode.HALF_EVEN), 0.0);
447         assertEquals(1.234f, Precision.round(1.2345f, 3, RoundingMode.HALF_EVEN), 0.0);
448         assertEquals(-1.234f, Precision.round(-1.2345f, 3, RoundingMode.HALF_EVEN), 0.0);
449         assertEquals(1.236f, Precision.round(1.2355f, 3, RoundingMode.HALF_EVEN), 0.0);
450         assertEquals(-1.236f, Precision.round(-1.2355f, 3, RoundingMode.HALF_EVEN), 0.0);
451 
452         assertEquals(1.23f, Precision.round(x, 2, RoundingMode.HALF_UP), 0.0);
453         assertEquals(1.235f, Precision.round(x, 3, RoundingMode.HALF_UP), 0.0);
454         assertEquals(1.2346f, Precision.round(x, 4, RoundingMode.HALF_UP), 0.0);
455         assertEquals(-1.23f, Precision.round(-x, 2, RoundingMode.HALF_UP), 0.0);
456         assertEquals(-1.235f, Precision.round(-x, 3, RoundingMode.HALF_UP), 0.0);
457         assertEquals(-1.2346f, Precision.round(-x, 4, RoundingMode.HALF_UP), 0.0);
458         assertEquals(1.235f, Precision.round(1.2345f, 3, RoundingMode.HALF_UP), 0.0);
459         assertEquals(-1.235f, Precision.round(-1.2345f, 3, RoundingMode.HALF_UP), 0.0);
460 
461         assertEquals(-1.23f, Precision.round(-1.23f, 2, RoundingMode.UNNECESSARY), 0.0);
462         assertEquals(1.23f, Precision.round(1.23f, 2, RoundingMode.UNNECESSARY), 0.0);
463 
464         try {
465             Precision.round(1.234f, 2, RoundingMode.UNNECESSARY);
466             fail();
467         } catch (MathRuntimeException ex) {
468             // success
469         }
470 
471         assertEquals(1.24f, Precision.round(x, 2, RoundingMode.UP), 0.0);
472         assertEquals(1.235f, Precision.round(x, 3, RoundingMode.UP), 0.0);
473         assertEquals(1.2346f, Precision.round(x, 4, RoundingMode.UP), 0.0);
474         assertEquals(-1.24f, Precision.round(-x, 2, RoundingMode.UP), 0.0);
475         assertEquals(-1.235f, Precision.round(-x, 3, RoundingMode.UP), 0.0);
476         assertEquals(-1.2346f, Precision.round(-x, 4, RoundingMode.UP), 0.0);
477 
478         // special values
479         UnitTestUtils.customAssertEquals(Float.NaN, Precision.round(Float.NaN, 2), 0.0f);
480         assertEquals(0.0f, Precision.round(0.0f, 2), 0.0f);
481         assertEquals(Float.POSITIVE_INFINITY, Precision.round(Float.POSITIVE_INFINITY, 2), 0.0f);
482         assertEquals(Float.NEGATIVE_INFINITY, Precision.round(Float.NEGATIVE_INFINITY, 2), 0.0f);
483         // comparison of positive and negative zero is not possible -> always equal thus do string comparison
484         assertEquals("-0.0", Float.toString(Precision.round(-0.0f, 0)));
485         assertEquals("-0.0", Float.toString(Precision.round(-1e-10f, 0)));
486 
487         // MATH-1070
488         assertEquals(0.0f, Precision.round(0f, 2, RoundingMode.UP), 0.0f);
489         assertEquals(0.05f, Precision.round(0.05f, 2, RoundingMode.UP), 0.0f);
490         assertEquals(0.06f, Precision.round(0.051f, 2, RoundingMode.UP), 0.0f);
491         assertEquals(0.06f, Precision.round(0.0505f, 2, RoundingMode.UP), 0.0f);
492         assertEquals(0.06f, Precision.round(0.059f, 2, RoundingMode.UP), 0.0f);
493     }
494 
495 
496     @Test
497     void testIssue721() {
498         assertEquals(-53,   FastMath.getExponent(Precision.EPSILON));
499         assertEquals(-1022, FastMath.getExponent(Precision.SAFE_MIN));
500     }
501 
502 
503     @Test
504     void testRepresentableDelta() {
505         int nonRepresentableCount = 0;
506         final double x = 100;
507         final int numTrials = 10000;
508         for (int i = 0; i < numTrials; i++) {
509             final double originalDelta = FastMath.random();
510             final double delta = Precision.representableDelta(x, originalDelta);
511             if (delta != originalDelta) {
512                 ++nonRepresentableCount;
513             }
514         }
515 
516         assertTrue(nonRepresentableCount / (double) numTrials > 0.9);
517     }
518 
519     @Test
520     void testMath843() {
521         final double afterEpsilon = FastMath.nextAfter(Precision.EPSILON,
522                                                        Double.POSITIVE_INFINITY);
523 
524         // a) 1 + EPSILON is equal to 1.
525         assertEquals(1, 1 + Precision.EPSILON);
526 
527         // b) 1 + "the number after EPSILON" is not equal to 1.
528         assertFalse(1 + afterEpsilon == 1);
529     }
530 
531     @Test
532     void testMath1127() {
533         assertFalse(Precision.equals(2.0, -2.0, 1));
534         assertTrue(Precision.equals(0.0, -0.0, 0));
535         assertFalse(Precision.equals(2.0f, -2.0f, 1));
536         assertTrue(Precision.equals(0.0f, -0.0f, 0));
537     }
538 
539     @Test
540     void testIsMathematicalIntegerDouble() {
541 
542         assertFalse(Precision.isMathematicalInteger(Double.NaN));
543         assertFalse(Precision.isMathematicalInteger(Double.POSITIVE_INFINITY));
544         assertFalse(Precision.isMathematicalInteger(Double.NEGATIVE_INFINITY));
545         assertFalse(Precision.isMathematicalInteger(Double.MIN_NORMAL));
546         assertFalse(Precision.isMathematicalInteger(Double.MIN_VALUE));
547 
548         assertTrue(Precision.isMathematicalInteger(-0.0));
549         assertTrue(Precision.isMathematicalInteger(+0.0));
550 
551         for (int i = -1000; i < 1000; ++i) {
552             final double d = i;
553             assertTrue(Precision.isMathematicalInteger(d));
554             assertFalse(Precision.isMathematicalInteger(FastMath.nextAfter(d, Double.POSITIVE_INFINITY)));
555             assertFalse(Precision.isMathematicalInteger(FastMath.nextAfter(d, Double.NEGATIVE_INFINITY)));
556         }
557 
558         double minNoFractional = 0x1l << 52;
559         assertTrue(Precision.isMathematicalInteger(minNoFractional));
560         assertFalse(Precision.isMathematicalInteger(minNoFractional - 0.5));
561         assertTrue(Precision.isMathematicalInteger(minNoFractional + 0.5));
562 
563     }
564 
565     @Test
566     void testIsMathematicalIntegerFloat() {
567 
568         assertFalse(Precision.isMathematicalInteger(Float.NaN));
569         assertFalse(Precision.isMathematicalInteger(Float.POSITIVE_INFINITY));
570         assertFalse(Precision.isMathematicalInteger(Float.NEGATIVE_INFINITY));
571         assertFalse(Precision.isMathematicalInteger(Float.MIN_NORMAL));
572         assertFalse(Precision.isMathematicalInteger(Float.MIN_VALUE));
573 
574         assertTrue(Precision.isMathematicalInteger(-0.0f));
575         assertTrue(Precision.isMathematicalInteger(+0.0f));
576 
577         for (int i = -1000; i < 1000; ++i) {
578             final float f = i;
579             assertTrue(Precision.isMathematicalInteger(f));
580             assertFalse(Precision.isMathematicalInteger(FastMath.nextAfter(f, Float.POSITIVE_INFINITY)));
581             assertFalse(Precision.isMathematicalInteger(FastMath.nextAfter(f, Float.NEGATIVE_INFINITY)));
582         }
583 
584         float minNoFractional = 0x1l << 23;
585         assertTrue(Precision.isMathematicalInteger(minNoFractional));
586         assertFalse(Precision.isMathematicalInteger(minNoFractional - 0.5f));
587         assertTrue(Precision.isMathematicalInteger(minNoFractional + 0.5f));
588 
589     }
590 
591 }