1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.hipparchus.util;
15
16 import org.hipparchus.Field;
17 import org.hipparchus.CalculusFieldElement;
18 import org.hipparchus.FieldElement;
19 import org.hipparchus.exception.LocalizedCoreFormats;
20 import org.hipparchus.exception.MathIllegalArgumentException;
21 import org.hipparchus.exception.MathRuntimeException;
22 import org.hipparchus.exception.NullArgumentException;
23 import org.hipparchus.random.RandomDataGenerator;
24 import org.hipparchus.util.MathUtils.FieldSumAndResidual;
25 import org.hipparchus.util.MathUtils.SumAndResidual;
26 import org.junit.Assert;
27 import org.junit.Test;
28
29
30
31
32 public final class MathUtilsTest {
33 @Test
34 public void testEqualsDouble() {
35 final double x = 1234.5678;
36 Assert.assertTrue(MathUtils.equals(x, x));
37 Assert.assertFalse(MathUtils.equals(x, -x));
38
39
40
41 Assert.assertTrue(MathUtils.equals(Double.NaN, Double.NaN));
42
43 final double mZero = -0d;
44 final double zero = 0d;
45 Assert.assertTrue(MathUtils.equals(zero, zero));
46 Assert.assertTrue(MathUtils.equals(mZero, mZero));
47 Assert.assertFalse(MathUtils.equals(mZero, zero));
48 }
49
50 @Test
51 public void testHash() {
52 double[] testArray = {
53 Double.NaN,
54 Double.POSITIVE_INFINITY,
55 Double.NEGATIVE_INFINITY,
56 1d,
57 0d,
58 1E-14,
59 (1 + 1E-14),
60 Double.MIN_VALUE,
61 Double.MAX_VALUE };
62 for (int i = 0; i < testArray.length; i++) {
63 for (int j = 0; j < testArray.length; j++) {
64 if (i == j) {
65 Assert.assertEquals(MathUtils.hash(testArray[i]), MathUtils.hash(testArray[j]));
66 Assert.assertEquals(MathUtils.hash(testArray[j]), MathUtils.hash(testArray[i]));
67 } else {
68 Assert.assertTrue(MathUtils.hash(testArray[i]) != MathUtils.hash(testArray[j]));
69 Assert.assertTrue(MathUtils.hash(testArray[j]) != MathUtils.hash(testArray[i]));
70 }
71 }
72 }
73 }
74
75 @Test
76 public void testArrayHash() {
77 Assert.assertEquals(0, MathUtils.hash((double[]) null));
78 Assert.assertEquals(MathUtils.hash(new double[] {
79 Double.NaN, Double.POSITIVE_INFINITY,
80 Double.NEGATIVE_INFINITY, 1d, 0d
81 }),
82 MathUtils.hash(new double[] {
83 Double.NaN, Double.POSITIVE_INFINITY,
84 Double.NEGATIVE_INFINITY, 1d, 0d
85 }));
86 Assert.assertFalse(MathUtils.hash(new double[] { 1d }) ==
87 MathUtils.hash(new double[] { FastMath.nextAfter(1d, 2d) }));
88 Assert.assertFalse(MathUtils.hash(new double[] { 1d }) ==
89 MathUtils.hash(new double[] { 1d, 1d }));
90 }
91
92
93
94
95 @Test
96 public void testPermutedArrayHash() {
97 double[] original = new double[10];
98 double[] permuted = new double[10];
99 RandomDataGenerator random = new RandomDataGenerator(100);
100
101
102 for (int i = 0; i < 10; i++) {
103 original[i] = random.nextUniform(i + 0.5, i + 0.75);
104 }
105
106
107 boolean isIdentity = true;
108 do {
109 int[] permutation = random.nextPermutation(10, 10);
110 for (int i = 0; i < 10; i++) {
111 if (i != permutation[i]) {
112 isIdentity = false;
113 }
114 permuted[i] = original[permutation[i]];
115 }
116 } while (isIdentity);
117
118
119 Assert.assertFalse(MathUtils.hash(original) == MathUtils.hash(permuted));
120 }
121
122 @Test
123 public void testIndicatorByte() {
124 Assert.assertEquals((byte)1, MathUtils.copySign((byte)1, (byte)2));
125 Assert.assertEquals((byte)1, MathUtils.copySign((byte)1, (byte)0));
126 Assert.assertEquals((byte)(-1), MathUtils.copySign((byte)1, (byte)(-2)));
127 }
128
129 @Test
130 public void testIndicatorInt() {
131 Assert.assertEquals(1, MathUtils.copySign(1, 2));
132 Assert.assertEquals(1, MathUtils.copySign(1, 0));
133 Assert.assertEquals((-1), MathUtils.copySign(1, -2));
134 }
135
136 @Test
137 public void testIndicatorLong() {
138 Assert.assertEquals(1L, MathUtils.copySign(1L, 2L));
139 Assert.assertEquals(1L, MathUtils.copySign(1L, 0L));
140 Assert.assertEquals(-1L, MathUtils.copySign(1L, -2L));
141 }
142
143 @Test
144 public void testIndicatorShort() {
145 Assert.assertEquals((short)1, MathUtils.copySign((short)1, (short)2));
146 Assert.assertEquals((short)1, MathUtils.copySign((short)1, (short)0));
147 Assert.assertEquals((short)(-1), MathUtils.copySign((short)1, (short)(-2)));
148 }
149
150 @Test
151 public void testNormalizeAngle() {
152 for (double a = -15.0; a <= 15.0; a += 0.1) {
153 for (double b = -15.0; b <= 15.0; b += 0.2) {
154 double c = MathUtils.normalizeAngle(a, b);
155 Assert.assertTrue((b - FastMath.PI) <= c);
156 Assert.assertTrue(c <= (b + FastMath.PI));
157 double twoK = FastMath.rint((a - c) / FastMath.PI);
158 Assert.assertEquals(c, a - twoK * FastMath.PI, 1.0e-14);
159 }
160 }
161 }
162
163 @Test
164 public void testFieldNormalizeAngle() {
165 doTestFieldNormalizeAngle(Binary64Field.getInstance());
166 }
167
168 private <T extends CalculusFieldElement<T>> void doTestFieldNormalizeAngle(final Field<T> field) {
169 final T zero = field.getZero();
170 for (double a = -15.0; a <= 15.0; a += 0.1) {
171 for (double b = -15.0; b <= 15.0; b += 0.2) {
172 T c = MathUtils.normalizeAngle(zero.add(a), zero.add(b));
173 double cR = c.getReal();
174 Assert.assertTrue((b - FastMath.PI) <= cR);
175 Assert.assertTrue(cR <= (b + FastMath.PI));
176 double twoK = FastMath.rint((a - cR) / FastMath.PI);
177 Assert.assertEquals(cR, a - twoK * FastMath.PI, 1.0e-14);
178 }
179 }
180 }
181
182 @Test
183 public void testReduce() {
184 final double period = -12.222;
185 final double offset = 13;
186
187 final double delta = 1.5;
188
189 double orig = offset + 122456789 * period + delta;
190 double expected = delta;
191 Assert.assertEquals(expected,
192 MathUtils.reduce(orig, period, offset),
193 1e-7);
194 Assert.assertEquals(expected,
195 MathUtils.reduce(orig, -period, offset),
196 1e-7);
197
198 orig = offset - 123356789 * period - delta;
199 expected = FastMath.abs(period) - delta;
200 Assert.assertEquals(expected,
201 MathUtils.reduce(orig, period, offset),
202 1e-6);
203 Assert.assertEquals(expected,
204 MathUtils.reduce(orig, -period, offset),
205 1e-6);
206
207 orig = offset - 123446789 * period + delta;
208 expected = delta;
209 Assert.assertEquals(expected,
210 MathUtils.reduce(orig, period, offset),
211 1e-6);
212 Assert.assertEquals(expected,
213 MathUtils.reduce(orig, -period, offset),
214 1e-6);
215
216 Assert.assertTrue(Double.isNaN(MathUtils.reduce(orig, Double.NaN, offset)));
217 Assert.assertTrue(Double.isNaN(MathUtils.reduce(Double.NaN, period, offset)));
218 Assert.assertTrue(Double.isNaN(MathUtils.reduce(orig, period, Double.NaN)));
219 Assert.assertTrue(Double.isNaN(MathUtils.reduce(orig, period,
220 Double.POSITIVE_INFINITY)));
221 Assert.assertTrue(Double.isNaN(MathUtils.reduce(Double.POSITIVE_INFINITY,
222 period, offset)));
223 Assert.assertTrue(Double.isNaN(MathUtils.reduce(orig,
224 Double.POSITIVE_INFINITY, offset)));
225 Assert.assertTrue(Double.isNaN(MathUtils.reduce(orig,
226 Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY)));
227 Assert.assertTrue(Double.isNaN(MathUtils.reduce(Double.POSITIVE_INFINITY,
228 period, Double.POSITIVE_INFINITY)));
229 Assert.assertTrue(Double.isNaN(MathUtils.reduce(Double.POSITIVE_INFINITY,
230 Double.POSITIVE_INFINITY, offset)));
231 Assert.assertTrue(Double.isNaN(MathUtils.reduce(Double.POSITIVE_INFINITY,
232 Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY)));
233 }
234
235 @Test
236 public void testReduceComparedWithNormalizeAngle() {
237 final double tol = Math.ulp(1d);
238 final double period = 2 * Math.PI;
239 for (double a = -15; a <= 15; a += 0.5) {
240 for (double center = -15; center <= 15; center += 1) {
241 final double nA = MathUtils.normalizeAngle(a, center);
242 final double offset = center - Math.PI;
243 final double r = MathUtils.reduce(a, period, offset);
244 Assert.assertEquals(nA, r + offset, tol);
245 }
246 }
247 }
248
249 @Test
250 public void testSignByte() {
251 final byte one = (byte) 1;
252 Assert.assertEquals((byte) 1, MathUtils.copySign(one, (byte) 2));
253 Assert.assertEquals((byte) (-1), MathUtils.copySign(one, (byte) (-2)));
254 }
255
256 @Test
257 public void testSignInt() {
258 final int one = 1;
259 Assert.assertEquals(1, MathUtils.copySign(one, 2));
260 Assert.assertEquals((-1), MathUtils.copySign(one, -2));
261 }
262
263 @Test
264 public void testSignLong() {
265 final long one = 1L;
266 Assert.assertEquals(1L, MathUtils.copySign(one, 2L));
267 Assert.assertEquals(-1L, MathUtils.copySign(one, -2L));
268 }
269
270 @Test
271 public void testSignShort() {
272 final short one = (short) 1;
273 Assert.assertEquals((short) 1, MathUtils.copySign(one, (short) 2));
274 Assert.assertEquals((short) (-1), MathUtils.copySign(one, (short) (-2)));
275 }
276
277 @Test
278 public void testCheckFinite() {
279 try {
280 MathUtils.checkFinite(Double.POSITIVE_INFINITY);
281 Assert.fail("an exception should have been thrown");
282 } catch (MathIllegalArgumentException e) {
283 Assert.assertEquals(LocalizedCoreFormats.NOT_FINITE_NUMBER, e.getSpecifier());
284 }
285 try {
286 MathUtils.checkFinite(Double.NEGATIVE_INFINITY);
287 Assert.fail("an exception should have been thrown");
288 } catch (MathIllegalArgumentException e) {
289 Assert.assertEquals(LocalizedCoreFormats.NOT_FINITE_NUMBER, e.getSpecifier());
290 }
291 try {
292 MathUtils.checkFinite(Double.NaN);
293 Assert.fail("an exception should have been thrown");
294 } catch (MathIllegalArgumentException e) {
295 Assert.assertEquals(LocalizedCoreFormats.NOT_FINITE_NUMBER, e.getSpecifier());
296 }
297
298 try {
299 MathUtils.checkFinite(new double[] {0, -1, Double.POSITIVE_INFINITY, -2, 3});
300 Assert.fail("an exception should have been thrown");
301 } catch (MathIllegalArgumentException e) {
302 Assert.assertEquals(LocalizedCoreFormats.NOT_FINITE_NUMBER, e.getSpecifier());
303 }
304 try {
305 MathUtils.checkFinite(new double[] {1, Double.NEGATIVE_INFINITY, -2, 3});
306 Assert.fail("an exception should have been thrown");
307 } catch (MathIllegalArgumentException e) {
308 Assert.assertEquals(LocalizedCoreFormats.NOT_FINITE_NUMBER, e.getSpecifier());
309 }
310 try {
311 MathUtils.checkFinite(new double[] {4, 3, -1, Double.NaN, -2, 1});
312 Assert.fail("an exception should have been thrown");
313 } catch (MathIllegalArgumentException e) {
314 Assert.assertEquals(LocalizedCoreFormats.NOT_FINITE_NUMBER, e.getSpecifier());
315 }
316 }
317
318 @Test
319 public void testCheckNotNull1() {
320 try {
321 Object obj = null;
322 MathUtils.checkNotNull(obj);
323 } catch (NullArgumentException e) {
324
325 }
326 }
327
328 @Test
329 public void testCheckNotNull2() {
330 try {
331 double[] array = null;
332 MathUtils.checkNotNull(array, LocalizedCoreFormats.INPUT_ARRAY);
333 } catch (NullArgumentException e) {
334
335 }
336 }
337
338 @Test
339 public void testCopySignByte() {
340 byte a = MathUtils.copySign(Byte.MIN_VALUE, (byte) -1);
341 Assert.assertEquals(Byte.MIN_VALUE, a);
342
343 final byte minValuePlusOne = Byte.MIN_VALUE + (byte) 1;
344 a = MathUtils.copySign(minValuePlusOne, (byte) 1);
345 Assert.assertEquals(Byte.MAX_VALUE, a);
346
347 a = MathUtils.copySign(Byte.MAX_VALUE, (byte) -1);
348 Assert.assertEquals(minValuePlusOne, a);
349
350 final byte one = 1;
351 byte val = -2;
352 a = MathUtils.copySign(val, one);
353 Assert.assertEquals(-val, a);
354
355 final byte minusOne = -one;
356 val = 2;
357 a = MathUtils.copySign(val, minusOne);
358 Assert.assertEquals(-val, a);
359
360 val = 0;
361 a = MathUtils.copySign(val, minusOne);
362 Assert.assertEquals(val, a);
363
364 val = 0;
365 a = MathUtils.copySign(val, one);
366 Assert.assertEquals(val, a);
367 }
368
369 @Test(expected=MathRuntimeException.class)
370 public void testCopySignByte2() {
371 MathUtils.copySign(Byte.MIN_VALUE, (byte) 1);
372 }
373
374
375
376
377 @Test
378 public void testTwoSum() {
379
380
381 final double a1 = 0.1;
382 final double b1 = 0.2;
383 final SumAndResidual result1 = MathUtils.twoSum(a1, b1);
384 Assert.assertEquals(a1 + b1, result1.getSum(), 0.);
385 Assert.assertEquals(a1 + b1, result1.getSum() + result1.getResidual(), 0.);
386 Assert.assertNotEquals(0., result1.getResidual(), 0.);
387
388
389
390 final double a2 = -615.7212034581913;
391 final double b2 = -964.5993814837093;
392 final SumAndResidual result2 = MathUtils.twoSum(a2, b2);
393 Assert.assertEquals(a2 + b2, result2.getSum(), 0.);
394 Assert.assertEquals(a2 + b2, result2.getSum() + result2.getResidual(), 0.);
395 Assert.assertNotEquals(0., result2.getResidual(), 0.);
396
397
398
399 final double a3 = 60.348375484313706;
400 final double b3 = 191.5142071130258;
401 final SumAndResidual result3 = MathUtils.twoSum(a3, b3);
402 Assert.assertEquals(a3 + b3, result3.getSum(), 0.);
403 Assert.assertEquals(a3 + b3, result3.getSum() + result3.getResidual(), 0.);
404 Assert.assertNotEquals(0., result3.getResidual(), 0.);
405
406
407
408 final double a4 = 622.8314146170453;
409 final double b4 = 0.0004877004669900762;
410 final SumAndResidual result4 = MathUtils.twoSum(a4, b4);
411 Assert.assertEquals(a4 + b4, result4.getSum(), 0.);
412 Assert.assertEquals(a4 + b4, result4.getSum() + result4.getResidual(), 0.);
413 Assert.assertNotEquals(0., result4.getResidual(), 0.);
414 }
415
416
417
418
419 @Test
420 public void testTwoSumField() {
421 final Tuple a = new Tuple(0.1, -615.7212034581913, 60.348375484313706, 622.8314146170453);
422 final Tuple b = new Tuple(0.2, -964.5993814837093, 191.5142071130258, 0.0004877004669900762);
423 final FieldSumAndResidual<Tuple> result = MathUtils.twoSum(a, b);
424 for (int i = 0; i < a.getDimension(); ++i) {
425 Assert.assertEquals(a.getComponent(i) + b.getComponent(i), result.getSum().getComponent(i), 0.);
426 Assert.assertEquals(a.getComponent(i) + b.getComponent(i),
427 result.getSum().getComponent(i) + result.getResidual().getComponent(i), 0.);
428 Assert.assertNotEquals(0., result.getResidual().getComponent(i), 0.);
429 }
430 }
431
432 }