1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.hipparchus;
23
24 import org.hipparchus.random.RandomGenerator;
25 import org.hipparchus.random.Well1024a;
26 import org.hipparchus.random.Well19937a;
27 import org.hipparchus.util.FastMath;
28 import org.hipparchus.util.FieldSinCos;
29 import org.hipparchus.util.FieldSinhCosh;
30 import org.hipparchus.util.MathArrays;
31 import org.hipparchus.util.SinCos;
32 import org.junit.jupiter.api.Assertions;
33 import org.junit.jupiter.api.Test;
34
35 import java.util.function.DoubleFunction;
36
37 import static org.junit.jupiter.api.Assertions.assertEquals;
38 import static org.junit.jupiter.api.Assertions.assertTrue;
39
40 public abstract class CalculusFieldElementAbstractTest<T extends CalculusFieldElement<T>> {
41
42 protected abstract T build(double x);
43
44 @Test
45 public void testNewInstance() {
46
47 final double realZero = 0.;
48 final T expectedZero = build(realZero);
49
50 final T actualZero = expectedZero.newInstance(realZero);
51
52 assertEquals(expectedZero.getReal(), actualZero.getReal(), 0.);
53 }
54
55 @Test
56 public void testAddField() {
57 for (double x = -3; x < 3; x += 0.2) {
58 for (double y = -3; y < 3; y += 0.2) {
59 checkRelative(x + y, build(x).add(build(y)));
60 }
61 }
62 }
63
64 @Test
65 public void testAddDouble() {
66 for (double x = -3; x < 3; x += 0.2) {
67 for (double y = -3; y < 3; y += 0.2) {
68 checkRelative(x + y, build(x).add(y));
69 }
70 }
71 }
72
73 @Test
74 public void testSubtractField() {
75 for (double x = -3; x < 3; x += 0.2) {
76 for (double y = -3; y < 3; y += 0.2) {
77 checkRelative(x - y, build(x).subtract(build(y)));
78 }
79 }
80 }
81
82 @Test
83 public void testSubtractDouble() {
84 for (double x = -3; x < 3; x += 0.2) {
85 for (double y = -3; y < 3; y += 0.2) {
86 checkRelative(x - y, build(x).subtract(y));
87 }
88 }
89 }
90
91 @Test
92 public void testMultiplyField() {
93 for (double x = -3; x < 3; x += 0.2) {
94 for (double y = -3; y < 3; y += 0.2) {
95 checkRelative(x * y, build(x).multiply(build(y)));
96 }
97 }
98 }
99
100 @Test
101 public void testMultiplyDouble() {
102 for (double x = -3; x < 3; x += 0.2) {
103 for (double y = -3; y < 3; y += 0.2) {
104 checkRelative(x * y, build(x).multiply(y));
105 }
106 }
107 }
108
109 @Test
110 public void testMultiplyInt() {
111 for (double x = -3; x < 3; x += 0.2) {
112 for (int y = -10; y < 10; y += 1) {
113 checkRelative(x * y, build(x).multiply(y));
114 }
115 }
116 }
117
118 @Test
119 public void testSquare() {
120 for (double x = -3; x < 3; x += 0.2) {
121 checkRelative(x * x, build(x).square());
122 }
123 }
124
125 @Test
126 public void testDivideField() {
127 for (double x = -3; x < 3; x += 0.2) {
128 for (double y = -3; y < 3; y += 0.2) {
129 checkRelative(x / y, build(x).divide(build(y)));
130 }
131 }
132 }
133
134 @Test
135 public void testDivideDouble() {
136 for (double x = -3; x < 3; x += 0.2) {
137 for (double y = -3; y < 3; y += 0.2) {
138 checkRelative(x / y, build(x).divide(y));
139 }
140 }
141 }
142
143 @Test
144 public void testToDegrees() {
145 for (double x = -0.9; x < 0.9; x += 0.05) {
146 checkRelative(FastMath.toDegrees(x), build(x).toDegrees());
147 }
148 }
149
150 @Test
151 public void testToRadians() {
152 for (double x = -0.9; x < 0.9; x += 0.05) {
153 checkRelative(FastMath.toRadians(x), build(x).toRadians());
154 }
155 }
156
157 @Test
158 public void testCos() {
159 for (double x = -0.9; x < 0.9; x += 0.05) {
160 checkRelative(FastMath.cos(x), build(x).cos());
161 }
162 }
163
164 @Test
165 public void testAcos() {
166 for (double x = -0.9; x < 0.9; x += 0.05) {
167 checkRelative(FastMath.acos(x), build(x).acos());
168 }
169 }
170
171 @Test
172 public void testSin() {
173 for (double x = -0.9; x < 0.9; x += 0.05) {
174 checkRelative(FastMath.sin(x), build(x).sin());
175 }
176 }
177
178 @Test
179 public void testAsin() {
180 for (double x = -0.9; x < 0.9; x += 0.05) {
181 checkRelative(FastMath.asin(x), build(x).asin());
182 }
183 }
184
185 @Test
186 public void testSinCos() {
187 for (double x = -0.9; x < 0.9; x += 0.05) {
188 FieldSinCos<T> sinCos = build(x).sinCos();
189 checkRelative(FastMath.sin(x), sinCos.sin());
190 checkRelative(FastMath.cos(x), sinCos.cos());
191 }
192 }
193
194 @Test
195 public void testSinCosNaN() {
196 FieldSinCos<T> sinCos = build(Double.NaN).sinCos();
197 assertTrue(sinCos.sin().isNaN());
198 assertTrue(sinCos.cos().isNaN());
199 }
200
201 @Test
202 public void testSinCosSum() {
203 final RandomGenerator random = new Well19937a(0x4aab62a42c9eb940L);
204 for (int i = 0; i < 10000; ++i) {
205 final double alpha = 10.0 * (2.0 * random.nextDouble() - 1.0);
206 final double beta = 10.0 * (2.0 * random.nextDouble() - 1.0);
207 final T alphaT = build(alpha);
208 final T betaT = build(beta);
209 final SinCos scSum = SinCos.sum(FastMath.sinCos(alpha), FastMath.sinCos(beta));
210 final FieldSinCos<T> scSumT = FieldSinCos.sum(alphaT.sinCos(), betaT.sinCos());
211 checkRelative(scSum.sin(), scSumT.sin());
212 checkRelative(scSum.cos(), scSumT.cos());
213 }
214 }
215
216 @Test
217 public void testSinCosdifference() {
218 final RandomGenerator random = new Well19937a(0x589aaf49471b03d5L);
219 for (int i = 0; i < 10000; ++i) {
220 final double alpha = 10.0 * (2.0 * random.nextDouble() - 1.0);
221 final double beta = 10.0 * (2.0 * random.nextDouble() - 1.0);
222 final T alphaT = build(alpha);
223 final T betaT = build(beta);
224 final SinCos scDifference = SinCos.difference(FastMath.sinCos(alpha), FastMath.sinCos(beta));
225 final FieldSinCos<T> scDifferenceT = FieldSinCos.difference(alphaT.sinCos(), betaT.sinCos());
226 checkRelative(scDifference.sin(), scDifferenceT.sin());
227 checkRelative(scDifference.cos(), scDifferenceT.cos());
228 }
229 }
230
231 @Test
232 public void testTan() {
233 for (double x = -0.9; x < 0.9; x += 0.05) {
234 checkRelative(FastMath.tan(x), build(x).tan());
235 }
236 }
237
238 @Test
239 public void testAtan() {
240 for (double x = -0.9; x < 0.9; x += 0.05) {
241 checkRelative(FastMath.atan(x), build(x).atan());
242 }
243 }
244
245 @Test
246 public void testAtan2() {
247 for (double x = -3; x < 3; x += 0.2) {
248 for (double y = -3; y < 3; y += 0.2) {
249 checkRelative(FastMath.atan2(y, x), build(y).atan2(build(x)));
250 }
251 }
252 }
253
254 @Test
255 public void testAtan2SpecialCases() {
256 checkRelative(FastMath.atan2(+0.0, +0.0), build(+0.0).atan2(build(+0.0)));
257 checkRelative(FastMath.atan2(-0.0, +0.0), build(-0.0).atan2(build(+0.0)));
258 checkRelative(FastMath.atan2(+0.0, -0.0), build(+0.0).atan2(build(-0.0)));
259 checkRelative(FastMath.atan2(-0.0, -0.0), build(-0.0).atan2(build(-0.0)));
260 }
261
262 @Test
263 public void testCosh() {
264 for (double x = -0.9; x < 0.9; x += 0.05) {
265 checkRelative(FastMath.cosh(x), build(x).cosh());
266 }
267 }
268
269 @Test
270 public void testAcosh() {
271 for (double x = 1.1; x < 5.0; x += 0.05) {
272 checkRelative(FastMath.acosh(x), build(x).acosh());
273 }
274 }
275
276 @Test
277 public void testSinh() {
278 for (double x = -0.9; x < 0.9; x += 0.05) {
279 checkRelative(FastMath.sinh(x), build(x).sinh());
280 }
281 }
282
283 @Test
284 public void testAsinh() {
285 for (double x = -0.9; x < 0.9; x += 0.05) {
286 checkRelative(FastMath.asinh(x), build(x).asinh());
287 }
288 }
289
290 @Test
291 public void testSinhCosh() {
292 for (double x = -0.9; x < 0.9; x += 0.05) {
293 FieldSinhCosh<T> sinhCosh = build(x).sinhCosh();
294 checkRelative(FastMath.sinh(x), sinhCosh.sinh());
295 checkRelative(FastMath.cosh(x), sinhCosh.cosh());
296 }
297 }
298
299 @Test
300 public void testSinhCoshNaN() {
301 FieldSinhCosh<T> sinhCosh = build(Double.NaN).sinhCosh();
302 assertTrue(sinhCosh.sinh().isNaN());
303 assertTrue(sinhCosh.cosh().isNaN());
304 }
305
306 @Test
307 public void testTanh() {
308 for (double x = -0.9; x < 0.9; x += 0.05) {
309 checkRelative(FastMath.tanh(x), build(x).tanh());
310 }
311 }
312
313 @Test
314 public void testAtanh() {
315 for (double x = -0.9; x < 0.9; x += 0.05) {
316 checkRelative(FastMath.atanh(x), build(x).atanh());
317 }
318 }
319
320 @Test
321 public void testSqrt() {
322 for (double x = 0.01; x < 0.9; x += 0.05) {
323 checkRelative(FastMath.sqrt(x), build(x).sqrt());
324 }
325 }
326
327 @Test
328 public void testCbrt() {
329 for (double x = -0.9; x < 0.9; x += 0.05) {
330 checkRelative(FastMath.cbrt(x), build(x).cbrt());
331 }
332 }
333
334 @Test
335 public void testHypot() {
336 for (double x = -3; x < 3; x += 0.2) {
337 for (double y = -3; y < 3; y += 0.2) {
338 checkRelative(FastMath.hypot(x, y), build(x).hypot(build(y)));
339 }
340 }
341 }
342
343 @Test
344 public void testHypotSpecialCases() {
345 assertTrue(Double.isNaN(build(Double.NaN).hypot(build(0)).getReal()));
346 assertTrue(Double.isNaN(build(0).hypot(build(Double.NaN)).getReal()));
347 assertEquals(Double.POSITIVE_INFINITY, build(Double.POSITIVE_INFINITY).hypot(build(0)).getReal(), 1.0);
348 assertEquals(Double.POSITIVE_INFINITY, build(Double.NEGATIVE_INFINITY).hypot(build(0)).getReal(), 1.0);
349 assertEquals(Double.POSITIVE_INFINITY, build(Double.POSITIVE_INFINITY).hypot(build(Double.NaN)).getReal(), 1.0);
350 assertEquals(Double.POSITIVE_INFINITY, build(Double.NEGATIVE_INFINITY).hypot(build(Double.NaN)).getReal(), 1.0);
351 assertEquals(Double.POSITIVE_INFINITY, build(0).hypot(build(Double.POSITIVE_INFINITY)).getReal(), 1.0);
352 assertEquals(Double.POSITIVE_INFINITY, build(0).hypot(build(Double.NEGATIVE_INFINITY)).getReal(), 1.0);
353 assertEquals(Double.POSITIVE_INFINITY, build(Double.NaN).hypot(build(Double.POSITIVE_INFINITY)).getReal(), 1.0);
354 assertEquals(Double.POSITIVE_INFINITY, build(Double.NaN).hypot(build(Double.NEGATIVE_INFINITY)).getReal(), 1.0);
355 }
356
357 @Test
358 public void testRootN() {
359 for (double x = -0.9; x < 0.9; x += 0.05) {
360 for (int n = 1; n < 5; ++n) {
361 if (x < 0) {
362 if (n % 2 == 1) {
363 checkRelative(-FastMath.pow(-x, 1.0 / n), build(x).rootN(n));
364 }
365 } else {
366 checkRelative(FastMath.pow(x, 1.0 / n), build(x).rootN(n));
367 }
368 }
369 }
370 }
371
372 @Test
373 public void testPowField() {
374 for (double x = -0.9; x < 0.9; x += 0.05) {
375 for (double y = 0.1; y < 4; y += 0.2) {
376 checkRelative(FastMath.pow(x, y), build(x).pow(build(y)));
377 }
378 }
379 }
380
381 @Test
382 public void testPowDouble() {
383 for (double x = -0.9; x < 0.9; x += 0.05) {
384 for (double y = 0.1; y < 4; y += 0.2) {
385 checkRelative(FastMath.pow(x, y), build(x).pow(y));
386 }
387 checkRelative(FastMath.pow(x, 0.0), build(x).pow(0.0));
388 }
389 }
390
391 @Test
392 public void testPowInt() {
393 for (double x = -0.9; x < 0.9; x += 0.05) {
394 for (int n = 0; n < 5; ++n) {
395 checkRelative(FastMath.pow(x, n), build(x).pow(n));
396 }
397 }
398 }
399
400 @Test
401 public void testExp() {
402 for (double x = -0.9; x < 0.9; x += 0.05) {
403 checkRelative(FastMath.exp(x), build(x).exp());
404 }
405 }
406
407 @Test
408 public void testExpm1() {
409 for (double x = -0.9; x < 0.9; x += 0.05) {
410 checkRelative(FastMath.expm1(x), build(x).expm1());
411 }
412 }
413
414 @Test
415 public void testLog() {
416 for (double x = 0.01; x < 0.9; x += 0.05) {
417 checkRelative(FastMath.log(x), build(x).log());
418 }
419 }
420
421 @Test
422 public void testLog1p() {
423 for (double x = -0.9; x < 0.9; x += 0.05) {
424 checkRelative(FastMath.log1p(x), build(x).log1p());
425 }
426 }
427
428 @Test
429 public void testLog10() {
430 for (double x = -0.9; x < 0.9; x += 0.05) {
431 checkRelative(FastMath.log10(x), build(x).log10());
432 }
433 }
434
435 @Test
436 public void testScalb() {
437 for (double x = -0.9; x < 0.9; x += 0.05) {
438 for (int n = -100; n < 100; ++n) {
439 checkRelative(FastMath.scalb(x, n), build(x).scalb(n));
440 }
441 }
442 }
443
444 @Test
445 public void testUlp() {
446 final RandomGenerator random = new Well19937a(0x36d4f8862421e0e4L);
447 for (int i = -300; i < 300; ++i) {
448 final double x = FastMath.scalb(2.0 * random.nextDouble() - 1.0, i);
449 assertTrue(FastMath.ulp(x) >= build(x).ulp().getReal());
450 }
451 }
452
453 @Test
454 public void testCeil() {
455 for (double x = -0.9; x < 0.9; x += 0.05) {
456 checkRelative(FastMath.ceil(x), build(x).ceil());
457 }
458 }
459
460 @Test
461 public void testFloor() {
462 for (double x = -0.9; x < 0.9; x += 0.05) {
463 checkRelative(FastMath.floor(x), build(x).floor());
464 }
465 }
466
467 @Test
468 public void testRint() {
469 for (double x = -0.9; x < 0.9; x += 0.05) {
470 checkRelative(FastMath.rint(x), build(x).rint());
471 }
472 }
473
474 @Test
475 public void testRemainderField() {
476 for (double x = -3; x < 3; x += 0.2) {
477 for (double y = -3; y < 3; y += 0.2) {
478 checkRelative(FastMath.IEEEremainder(x, y), build(x).remainder(build(y)));
479 }
480 }
481 }
482
483 @Test
484 public void testRemainderDouble() {
485 for (double x = -3; x < 3; x += 0.2) {
486 for (double y = -3.2; y < 3.2; y += 0.25) {
487 checkRelative(FastMath.IEEEremainder(x, y), build(x).remainder(y));
488 }
489 }
490 }
491
492 @Test
493 public void testCopySignField() {
494 for (double x = -3; x < 3; x += 0.2) {
495 for (double y = -3; y < 3; y += 0.2) {
496 checkRelative(FastMath.copySign(x, y), build(x).copySign(build(y)));
497 }
498 }
499 }
500
501 @Test
502 public void testCopySignDouble() {
503 for (double x = -3; x < 3; x += 0.2) {
504 for (double y = -3; y < 3; y += 0.2) {
505 checkRelative(FastMath.copySign(x, y), build(x).copySign(y));
506 }
507 }
508 }
509
510 @Test
511 public void testCopySignSpecialField() {
512
513 assertEquals(-2.0, build(-2.0).copySign(build(-5.0)).getReal(), 1.0e-10);
514 assertEquals(-2.0, build(+2.0).copySign(build(-5.0)).getReal(), 1.0e-10);
515 assertEquals(+2.0, build(-2.0).copySign(build(+5.0)).getReal(), 1.0e-10);
516 assertEquals(+2.0, build(+2.0).copySign(build(+5.0)).getReal(), 1.0e-10);
517 assertEquals(-2.0, build(-2.0).copySign(build(Double.NEGATIVE_INFINITY)).getReal(), 1.0e-10);
518 assertEquals(-2.0, build(+2.0).copySign(build(Double.NEGATIVE_INFINITY)).getReal(), 1.0e-10);
519 assertEquals(+2.0, build(-2.0).copySign(build(Double.POSITIVE_INFINITY)).getReal(), 1.0e-10);
520 assertEquals(+2.0, build(+2.0).copySign(build(Double.POSITIVE_INFINITY)).getReal(), 1.0e-10);
521 assertEquals(+2.0, build(-2.0).copySign(build(Double.NaN)).getReal(), 1.0e-10);
522 assertEquals(+2.0, build(-2.0).copySign(build(Double.NaN)).getReal(), 1.0e-10);
523 assertEquals(+2.0, build(-2.0).copySign(build(-Double.NaN)).getReal(), 1.0e-10);
524 assertEquals(+2.0, build(-2.0).copySign(build(-Double.NaN)).getReal(), 1.0e-10);
525 assertEquals(-2.0, build(-2.0).copySign(build(-0.0)).getReal(), 1.0e-10);
526 assertEquals(-2.0, build(+2.0).copySign(build(-0.0)).getReal(), 1.0e-10);
527 assertEquals(+2.0, build(-2.0).copySign(build(+0.0)).getReal(), 1.0e-10);
528 assertEquals(+2.0, build(+2.0).copySign(build(+0.0)).getReal(), 1.0e-10);
529
530 assertEquals(-3.0, build(+3.0).copySign(build(-0.0).copySign(build(-5.0))).getReal(), 1.0e-10);
531 assertEquals(-3.0, build(+3.0).copySign(build(+0.0).copySign(build(-5.0))).getReal(), 1.0e-10);
532 assertEquals(+3.0, build(+3.0).copySign(build(-0.0).copySign(build(+5.0))).getReal(), 1.0e-10);
533 assertEquals(+3.0, build(+3.0).copySign(build(+0.0).copySign(build(+5.0))).getReal(), 1.0e-10);
534 assertEquals(-3.0, build(+3.0).copySign(build(-0.0).copySign(build(Double.NEGATIVE_INFINITY))).getReal(), 1.0e-10);
535 assertEquals(-3.0, build(+3.0).copySign(build(+0.0).copySign(build(Double.NEGATIVE_INFINITY))).getReal(), 1.0e-10);
536 assertEquals(+3.0, build(+3.0).copySign(build(-0.0).copySign(build(Double.POSITIVE_INFINITY))).getReal(), 1.0e-10);
537 assertEquals(+3.0, build(+3.0).copySign(build(+0.0).copySign(build(Double.POSITIVE_INFINITY))).getReal(), 1.0e-10);
538 assertEquals(+3.0, build(+3.0).copySign(build(-0.0).copySign(build(Double.NaN))).getReal(), 1.0e-10);
539 assertEquals(+3.0, build(+3.0).copySign(build(-0.0).copySign(build(Double.NaN))).getReal(), 1.0e-10);
540 assertEquals(+3.0, build(+3.0).copySign(build(-0.0).copySign(build(-Double.NaN))).getReal(), 1.0e-10);
541 assertEquals(+3.0, build(+3.0).copySign(build(-0.0).copySign(build(-Double.NaN))).getReal(), 1.0e-10);
542 assertEquals(-3.0, build(+3.0).copySign(build(-0.0).copySign(build(-0.0))).getReal(), 1.0e-10);
543 assertEquals(-3.0, build(+3.0).copySign(build(+0.0).copySign(build(-0.0))).getReal(), 1.0e-10);
544 assertEquals(+3.0, build(+3.0).copySign(build(-0.0).copySign(build(+0.0))).getReal(), 1.0e-10);
545 assertEquals(+3.0, build(+3.0).copySign(build(+0.0).copySign(build(+0.0))).getReal(), 1.0e-10);
546
547 }
548
549 @Test
550 public void testCopySignSpecialDouble() {
551
552 assertEquals(-2.0, build(-2.0).copySign(-5.0).getReal(), 1.0e-10);
553 assertEquals(-2.0, build(+2.0).copySign(-5.0).getReal(), 1.0e-10);
554 assertEquals(+2.0, build(-2.0).copySign(+5.0).getReal(), 1.0e-10);
555 assertEquals(+2.0, build(+2.0).copySign(+5.0).getReal(), 1.0e-10);
556 assertEquals(-2.0, build(-2.0).copySign(Double.NEGATIVE_INFINITY).getReal(), 1.0e-10);
557 assertEquals(-2.0, build(+2.0).copySign(Double.NEGATIVE_INFINITY).getReal(), 1.0e-10);
558 assertEquals(+2.0, build(-2.0).copySign(Double.POSITIVE_INFINITY).getReal(), 1.0e-10);
559 assertEquals(+2.0, build(+2.0).copySign(Double.POSITIVE_INFINITY).getReal(), 1.0e-10);
560 assertEquals(+2.0, build(-2.0).copySign(Double.NaN).getReal(), 1.0e-10);
561 assertEquals(+2.0, build(-2.0).copySign(Double.NaN).getReal(), 1.0e-10);
562 assertEquals(+2.0, build(-2.0).copySign(-Double.NaN).getReal(), 1.0e-10);
563 assertEquals(+2.0, build(-2.0).copySign(-Double.NaN).getReal(), 1.0e-10);
564 assertEquals(-2.0, build(-2.0).copySign(-0.0).getReal(), 1.0e-10);
565 assertEquals(-2.0, build(+2.0).copySign(-0.0).getReal(), 1.0e-10);
566 assertEquals(+2.0, build(-2.0).copySign(+0.0).getReal(), 1.0e-10);
567 assertEquals(+2.0, build(+2.0).copySign(+0.0).getReal(), 1.0e-10);
568
569 assertEquals(-3.0, build(+3.0).copySign(build(-0.0).copySign(-5.0)).getReal(), 1.0e-10);
570 assertEquals(-3.0, build(+3.0).copySign(build(+0.0).copySign(-5.0)).getReal(), 1.0e-10);
571 assertEquals(+3.0, build(+3.0).copySign(build(-0.0).copySign(+5.0)).getReal(), 1.0e-10);
572 assertEquals(+3.0, build(+3.0).copySign(build(+0.0).copySign(+5.0)).getReal(), 1.0e-10);
573 assertEquals(-3.0, build(+3.0).copySign(build(-0.0).copySign(Double.NEGATIVE_INFINITY)).getReal(), 1.0e-10);
574 assertEquals(-3.0, build(+3.0).copySign(build(+0.0).copySign(Double.NEGATIVE_INFINITY)).getReal(), 1.0e-10);
575 assertEquals(+3.0, build(+3.0).copySign(build(-0.0).copySign(Double.POSITIVE_INFINITY)).getReal(), 1.0e-10);
576 assertEquals(+3.0, build(+3.0).copySign(build(+0.0).copySign(Double.POSITIVE_INFINITY)).getReal(), 1.0e-10);
577 assertEquals(+3.0, build(+3.0).copySign(build(-0.0).copySign(Double.NaN)).getReal(), 1.0e-10);
578 assertEquals(+3.0, build(+3.0).copySign(build(-0.0).copySign(Double.NaN)).getReal(), 1.0e-10);
579 assertEquals(+3.0, build(+3.0).copySign(build(-0.0).copySign(-Double.NaN)).getReal(), 1.0e-10);
580 assertEquals(+3.0, build(+3.0).copySign(build(-0.0).copySign(-Double.NaN)).getReal(), 1.0e-10);
581 assertEquals(-3.0, build(+3.0).copySign(build(-0.0).copySign(-0.0)).getReal(), 1.0e-10);
582 assertEquals(-3.0, build(+3.0).copySign(build(+0.0).copySign(-0.0)).getReal(), 1.0e-10);
583 assertEquals(+3.0, build(+3.0).copySign(build(-0.0).copySign(+0.0)).getReal(), 1.0e-10);
584 assertEquals(+3.0, build(+3.0).copySign(build(+0.0).copySign(+0.0)).getReal(), 1.0e-10);
585
586 }
587
588 @Test
589 public void testSign() {
590 for (double x = -0.9; x < 0.9; x += 0.05) {
591 checkRelative(FastMath.signum(x), build(x).sign());
592 }
593 }
594
595 @Test
596 public void testLinearCombinationReference() {
597 doTestLinearCombinationReference(x -> build(x), 5.0e-16, 1.0);
598 }
599
600 protected void doTestLinearCombinationReference(final DoubleFunction<T> builder,
601 final double toleranceLinearCombination,
602 final double relativeErrorNaiveImplementation) {
603
604 final T[] a = MathArrays.buildArray(build(0).getField(), 3);
605 a[0] = builder.apply(-1321008684645961.0);
606 a[1] = builder.apply(-5774608829631843.0);
607 a[2] = builder.apply(-7645843051051357.0 / 32.0);
608 final T[] b = MathArrays.buildArray(build(0).getField(), 3);
609 b[0] = builder.apply(-5712344449280879.0 / 16.0);
610 b[1] = builder.apply(-4550117129121957.0 / 16.0);
611 b[2] = builder.apply(8846951984510141.0);
612
613 final T abSumInline = a[0].linearCombination(a[0], b[0], a[1], b[1], a[2], b[2]);
614 final T abSumArray = a[0].linearCombination(a, b);
615 final T abNaive = a[0].multiply(b[0]).add(a[1].multiply(b[1])).add(a[2].multiply(b[2]));
616
617 assertEquals(abSumInline.getReal(), abSumArray.getReal(), 0);
618 final double reference = -65271563724949.90625;
619 assertEquals(reference, abSumInline.getReal(),
620 toleranceLinearCombination * FastMath.abs(reference));
621 assertEquals(relativeErrorNaiveImplementation * FastMath.abs(reference),
622 FastMath.abs(abNaive.subtract(reference).getReal()),
623 1.0e-3 * relativeErrorNaiveImplementation * FastMath.abs(reference));
624
625 }
626
627 @Test
628 public void testLinearCombinationFaFa() {
629 RandomGenerator r = new Well1024a(0xfafaL);
630 for (int i = 0; i < 50; ++i) {
631 double[] aD = generateDouble(r, 10);
632 double[] bD = generateDouble(r, 10);
633 T[] aF = toFieldArray(aD);
634 T[] bF = toFieldArray(bD);
635 checkRelative(MathArrays.linearCombination(aD, bD),
636 aF[0].linearCombination(aF, bF));
637 }
638 }
639
640 @Test
641 public void testLinearCombinationDaFa() {
642 RandomGenerator r = new Well1024a(0xdafaL);
643 for (int i = 0; i < 50; ++i) {
644 double[] aD = generateDouble(r, 10);
645 double[] bD = generateDouble(r, 10);
646 T[] bF = toFieldArray(bD);
647 checkRelative(MathArrays.linearCombination(aD, bD),
648 bF[0].linearCombination(aD, bF));
649 }
650 }
651
652 @Test
653 public void testLinearCombinationFF2() {
654 RandomGenerator r = new Well1024a(0xff2L);
655 for (int i = 0; i < 50; ++i) {
656 double[] aD = generateDouble(r, 2);
657 double[] bD = generateDouble(r, 2);
658 T[] aF = toFieldArray(aD);
659 T[] bF = toFieldArray(bD);
660 checkRelative(MathArrays.linearCombination(aD[0], bD[0], aD[1], bD[1]),
661 aF[0].linearCombination(aF[0], bF[0], aF[1], bF[1]));
662 }
663 }
664
665 @Test
666 public void testLinearCombinationDF2() {
667 RandomGenerator r = new Well1024a(0xdf2L);
668 for (int i = 0; i < 50; ++i) {
669 double[] aD = generateDouble(r, 2);
670 double[] bD = generateDouble(r, 2);
671 T[] bF = toFieldArray(bD);
672 checkRelative(MathArrays.linearCombination(aD[0], bD[0], aD[1], bD[1]),
673 bF[0].linearCombination(aD[0], bF[0], aD[1], bF[1]));
674 }
675 }
676
677 @Test
678 public void testLinearCombinationFF3() {
679 RandomGenerator r = new Well1024a(0xff3L);
680 for (int i = 0; i < 50; ++i) {
681 double[] aD = generateDouble(r, 3);
682 double[] bD = generateDouble(r, 3);
683 T[] aF = toFieldArray(aD);
684 T[] bF = toFieldArray(bD);
685 checkRelative(MathArrays.linearCombination(aD[0], bD[0], aD[1], bD[1], aD[2], bD[2]),
686 aF[0].linearCombination(aF[0], bF[0], aF[1], bF[1], aF[2], bF[2]));
687 }
688 }
689
690 @Test
691 public void testLinearCombinationDF3() {
692 RandomGenerator r = new Well1024a(0xdf3L);
693 for (int i = 0; i < 50; ++i) {
694 double[] aD = generateDouble(r, 3);
695 double[] bD = generateDouble(r, 3);
696 T[] bF = toFieldArray(bD);
697 checkRelative(MathArrays.linearCombination(aD[0], bD[0], aD[1], bD[1], aD[2], bD[2]),
698 bF[0].linearCombination(aD[0], bF[0], aD[1], bF[1], aD[2], bF[2]));
699 }
700 }
701
702 @Test
703 public void testLinearCombinationFF4() {
704 RandomGenerator r = new Well1024a(0xff4L);
705 for (int i = 0; i < 50; ++i) {
706 double[] aD = generateDouble(r, 4);
707 double[] bD = generateDouble(r, 4);
708 T[] aF = toFieldArray(aD);
709 T[] bF = toFieldArray(bD);
710 checkRelative(MathArrays.linearCombination(aD[0], bD[0], aD[1], bD[1], aD[2], bD[2], aD[3], bD[3]),
711 aF[0].linearCombination(aF[0], bF[0], aF[1], bF[1], aF[2], bF[2], aF[3], bF[3]));
712 }
713 }
714
715 @Test
716 public void testLinearCombinationDF4() {
717 RandomGenerator r = new Well1024a(0xdf4L);
718 for (int i = 0; i < 50; ++i) {
719 double[] aD = generateDouble(r, 4);
720 double[] bD = generateDouble(r, 4);
721 T[] bF = toFieldArray(bD);
722 checkRelative(MathArrays.linearCombination(aD[0], bD[0], aD[1], bD[1], aD[2], bD[2], aD[3], bD[3]),
723 bF[0].linearCombination(aD[0], bF[0], aD[1], bF[1], aD[2], bF[2], aD[3], bF[3]));
724 }
725 }
726
727 @Test
728 public void testGetPi() {
729 checkRelative(FastMath.PI, build(-10).getPi());
730 }
731
732 @Test
733 public void testGetReal() {
734 Assertions.assertEquals( 3.25, build( 3.25).getReal(), 1.0e-15);
735 Assertions.assertEquals(-3.25, build(-3.25).getReal(), 1.0e-15);
736 Assertions.assertTrue(build(Double.NEGATIVE_INFINITY).getReal() < 0);
737 Assertions.assertTrue(Double.isInfinite(build(Double.NEGATIVE_INFINITY).getReal()));
738 Assertions.assertTrue(build(Double.POSITIVE_INFINITY).getReal() > 0);
739 Assertions.assertTrue(Double.isInfinite(build(Double.POSITIVE_INFINITY).getReal()));
740 Assertions.assertTrue(Double.isNaN(build(Double.NaN).getReal()));
741 }
742
743 @Test
744 public void testGetAddendum() {
745 checkAddendum(build( 3.25));
746 checkAddendum(build(-3.25));
747 checkAddendum(build(Double.NEGATIVE_INFINITY));
748 checkAddendum(build(Double.POSITIVE_INFINITY));
749 checkAddendum(build(Double.NaN));
750 }
751
752 protected void checkAddendum(final T t) {
753 Assertions.assertEquals(0.0, t.getAddendum().getReal(), 1.0e-15);
754 final T rebuilt = t.getAddendum().add(t.getReal());
755 if (t.isInfinite()) {
756 Assertions.assertTrue(rebuilt.isInfinite());
757 Assertions.assertTrue(t.getReal() * rebuilt.getReal() > 0);
758 } else if (t.isNaN()) {
759 Assertions.assertTrue(rebuilt.isNaN());
760 } else {
761 Assertions.assertEquals(t, rebuilt);
762 }
763 }
764
765 @Test
766 public void testGetField() {
767 checkRelative(1.0, build(-10).getField().getOne());
768 checkRelative(0.0, build(-10).getField().getZero());
769 }
770
771 @Test
772 public void testAbs() {
773 for (double x = -0.9; x < 0.9; x += 0.05) {
774 checkRelative(FastMath.abs(x), build(x).abs());
775 }
776 }
777
778 @Test
779 public void testRound() {
780 for (double x = -0.9; x < 0.9; x += 0.05) {
781 assertEquals(FastMath.round(x), build(x).round());
782 }
783 }
784
785 protected void checkRelative(double expected, T obtained) {
786 if (Double.isNaN(expected)) {
787 assertEquals(expected, obtained.getReal());
788 } else {
789 assertEquals(expected, obtained.getReal(),
790 1.0e-15 * (1 + FastMath.abs(expected)));
791 }
792 }
793
794 private double[] generateDouble (final RandomGenerator r, int n) {
795 double[] a = new double[n];
796 for (int i = 0; i < n; ++i) {
797 a[i] = r.nextDouble();
798 }
799 return a;
800 }
801
802 private T[] toFieldArray (double[] a) {
803 T[] f = MathArrays.buildArray(build(0).getField(), a.length);
804 for (int i = 0; i < a.length; ++i) {
805 f[i] = build(a[i]);
806 }
807 return f;
808 }
809
810 }