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