View Javadoc
1   /*
2    * Licensed to the Hipparchus project 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 Hipparchus project 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  package org.hipparchus.complex;
18  
19  import org.hipparchus.CalculusFieldElementAbstractTest;
20  import org.hipparchus.UnitTestUtils;
21  import org.hipparchus.exception.LocalizedCoreFormats;
22  import org.hipparchus.exception.MathIllegalArgumentException;
23  import org.hipparchus.exception.NullArgumentException;
24  import org.hipparchus.util.Binary64;
25  import org.hipparchus.util.Binary64Field;
26  import org.hipparchus.util.FastMath;
27  import org.hipparchus.util.MathArrays;
28  import org.hipparchus.util.MathUtils;
29  import org.hipparchus.util.Precision;
30  import org.junit.jupiter.api.Assertions;
31  import org.junit.jupiter.api.Test;
32  
33  import java.util.Arrays;
34  import java.util.List;
35  
36  import static org.junit.jupiter.api.Assertions.assertEquals;
37  import static org.junit.jupiter.api.Assertions.assertFalse;
38  import static org.junit.jupiter.api.Assertions.assertNotEquals;
39  import static org.junit.jupiter.api.Assertions.assertThrows;
40  import static org.junit.jupiter.api.Assertions.assertTrue;
41  import static org.junit.jupiter.api.Assertions.fail;
42  
43  
44  public class FieldComplexTest extends CalculusFieldElementAbstractTest<FieldComplex<Binary64>> {
45  
46  
47      private FieldComplex<Binary64> oneInf       = build(1,                        Double.POSITIVE_INFINITY);
48      private FieldComplex<Binary64> oneNegInf    = build(1,                        Double.NEGATIVE_INFINITY);
49      private FieldComplex<Binary64> infOne       = build(Double.POSITIVE_INFINITY, 1);
50      private FieldComplex<Binary64> infZero      = build(Double.POSITIVE_INFINITY, 0);
51      private FieldComplex<Binary64> infNaN       = build(Double.POSITIVE_INFINITY, Double.NaN);
52      private FieldComplex<Binary64> infNegInf    = build(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY);
53      private FieldComplex<Binary64> infInf       = build(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
54      private FieldComplex<Binary64> negInfInf    = build(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);
55      private FieldComplex<Binary64> negInfZero   = build(Double.NEGATIVE_INFINITY, 0);
56      private FieldComplex<Binary64> negInfOne    = build(Double.NEGATIVE_INFINITY, 1);
57      private FieldComplex<Binary64> negInfNaN    = build(Double.NEGATIVE_INFINITY, Double.NaN);
58      private FieldComplex<Binary64> negInfNegInf = build(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY);
59      private FieldComplex<Binary64> oneNaN       = build(1,                        Double.NaN);
60      private FieldComplex<Binary64> zeroInf      = build(0,                        Double.POSITIVE_INFINITY);
61      private FieldComplex<Binary64> zeroNaN      = build(0,                        Double.NaN);
62      private FieldComplex<Binary64> nanInf       = build(Double.NaN,               Double.POSITIVE_INFINITY);
63      private FieldComplex<Binary64> nanNegInf    = build(Double.NaN,               Double.NEGATIVE_INFINITY);
64      private FieldComplex<Binary64> nanZero      = build(Double.NaN);
65  
66      @Override
67      protected FieldComplex<Binary64> build(final double x) {
68          return build(x, 0.0);
69      }
70  
71      private FieldComplex<Binary64> build(final double real, double imaginary) {
72          return new FieldComplex<>(new Binary64(real), new Binary64(imaginary));
73      }
74  
75      @Test
76      void testConstructor() {
77          FieldComplex<Binary64> z = build(3.0, 4.0);
78          assertEquals(3.0, z.getRealPart().getReal(), 1.0e-5);
79          assertEquals(4.0, z.getImaginary().getReal(), 1.0e-5);
80          assertEquals(3.0, z.getRealPart().getReal(), 1.0e-5);
81          assertEquals(4.0, z.getImaginaryPart().getReal(), 1.0e-5);
82      }
83  
84      @Test
85      void testConstructorNaN() {
86          FieldComplex<Binary64> z = build(3.0, Double.NaN);
87          assertTrue(z.isNaN());
88  
89          z = build(Double.NaN, 4.0);
90          assertTrue(z.isNaN());
91  
92          z = build(3.0, 4.0);
93          assertFalse(z.isNaN());
94      }
95  
96      @Test
97      void testNorm() {
98          FieldComplex<Binary64> z = build(3.0, 4.0);
99          assertEquals(5.0, z.norm(), 1.0e-5);
100     }
101 
102     @Test
103     void testNormNaN() {
104         assertTrue(Double.isNaN(FieldComplex.getNaN(Binary64Field.getInstance()).norm()));
105         FieldComplex<Binary64> z = build(Double.POSITIVE_INFINITY, Double.NaN);
106         assertTrue(Double.isNaN(z.norm()));
107     }
108 
109     @Test
110     void testNormInfinite() {
111         FieldComplex<Binary64> z = FieldComplex.getNaN(Binary64Field.getInstance()).newInstance(Double.POSITIVE_INFINITY);
112         assertEquals(Double.POSITIVE_INFINITY, z.norm(), 0);
113         z = build(0, Double.NEGATIVE_INFINITY);
114         assertEquals(Double.POSITIVE_INFINITY, z.norm(), 0);
115         z = build(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY);
116         assertEquals(Double.POSITIVE_INFINITY, z.norm(), 0);
117     }
118 
119     @Test
120     void testAdd() {
121         FieldComplex<Binary64> x = build(3.0, 4.0);
122         FieldComplex<Binary64> y = build(5.0, 6.0);
123         FieldComplex<Binary64> z = x.add(y);
124         assertEquals(8.0, z.getRealPart().getReal(), 1.0e-5);
125         assertEquals(10.0, z.getImaginary().getReal(), 1.0e-5);
126     }
127 
128     @Test
129     void testAddT() {
130         FieldComplex<Binary64> z = build(3.0, 4.0).add(new Binary64(5.0));
131         assertEquals(8.0, z.getRealPart().getReal(), 1.0e-5);
132         assertEquals(4.0, z.getImaginary().getReal(), 1.0e-5);
133     }
134 
135     @Test
136     void testAddNaN() {
137         FieldComplex<Binary64> x = build(3.0, 4.0);
138         FieldComplex<Binary64> z = x.add(FieldComplex.getNaN(Binary64Field.getInstance()));
139         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), z);
140         z = build(1, Double.NaN);
141         FieldComplex<Binary64> w = x.add(z);
142         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), w);
143         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), FieldComplex.getNaN(Binary64Field.getInstance()).add(Double.NaN));
144     }
145 
146     @Test
147     void testAddInf() {
148         FieldComplex<Binary64> x = build(1, 1);
149         FieldComplex<Binary64> z = build(Double.POSITIVE_INFINITY, 0);
150         FieldComplex<Binary64> w = x.add(z);
151         assertEquals(1, w.getImaginary().getReal(), 0);
152         assertEquals(Double.POSITIVE_INFINITY, w.getRealPart().getReal(), 0);
153 
154         x = build(Double.NEGATIVE_INFINITY, 0);
155         assertTrue(Double.isNaN(x.add(z).getReal()));
156     }
157 
158     @Test
159     void testScalarAdd() {
160         FieldComplex<Binary64> x = build(3.0, 4.0);
161         double yDouble = 2.0;
162         FieldComplex<Binary64> yComplex = build(yDouble);
163         assertEquals(x.add(yComplex), x.add(yDouble));
164         assertEquals(x.add(yComplex), x.add(new Binary64(yDouble)));
165     }
166 
167     @Test
168     void testScalarAddNaN() {
169         FieldComplex<Binary64> x = build(3.0, 4.0);
170         double yDouble = Double.NaN;
171         FieldComplex<Binary64> yComplex = build(yDouble);
172         assertEquals(x.add(yComplex), x.add(yDouble));
173         assertEquals(x.add(yComplex), x.add(new Binary64(yDouble)));
174         assertTrue(build(Double.NaN).add(0).isNaN());
175         assertTrue(build(Double.NaN).add(Binary64.ZERO).isNaN());
176     }
177 
178     @Test
179     void testScalarAddInf() {
180         FieldComplex<Binary64> x = build(1, 1);
181         double yDouble = Double.POSITIVE_INFINITY;
182 
183         FieldComplex<Binary64> yComplex = build(yDouble);
184         assertEquals(x.add(yComplex), x.add(yDouble));
185         assertEquals(x.add(yComplex), x.add(new Binary64(yDouble)));
186 
187         x = build(Double.NEGATIVE_INFINITY, 0);
188         assertEquals(x.add(yComplex), x.add(yDouble));
189         assertEquals(x.add(yComplex), x.add(new Binary64(yDouble)));
190 
191     }
192 
193     @Test
194     void testConjugate() {
195         FieldComplex<Binary64> x = build(3.0, 4.0);
196         FieldComplex<Binary64> z = x.conjugate();
197         assertEquals(3.0, z.getRealPart().getReal(), 1.0e-5);
198         assertEquals(-4.0, z.getImaginaryPart().getReal(), 1.0e-5);
199     }
200 
201     @Test
202     void testConjugateNaN() {
203         FieldComplex<Binary64> z = FieldComplex.getNaN(Binary64Field.getInstance()).conjugate();
204         assertTrue(z.isNaN());
205     }
206 
207     @Test
208     void testConjugateInfiinite() {
209         FieldComplex<Binary64> z = build(0, Double.POSITIVE_INFINITY);
210         assertEquals(Double.NEGATIVE_INFINITY, z.conjugate().getImaginary().getReal(), 0);
211         z = build(0, Double.NEGATIVE_INFINITY);
212         assertEquals(Double.POSITIVE_INFINITY, z.conjugate().getImaginary().getReal(), 0);
213     }
214 
215     @Test
216     void testDivide() {
217         FieldComplex<Binary64> x = build(3.0, 4.0);
218         FieldComplex<Binary64> y = build(5.0, 6.0);
219         FieldComplex<Binary64> z = x.divide(y);
220         assertEquals(39.0 / 61.0, z.getRealPart().getReal(), 1.0e-5);
221         assertEquals(2.0 / 61.0, z.getImaginaryPart().getReal(), 1.0e-5);
222     }
223 
224     @Test
225     void testDivideReal() {
226         FieldComplex<Binary64> x = build(2d, 3d);
227         FieldComplex<Binary64> y = build(2d, 0d);
228         assertEquals(build(1d, 1.5), x.divide(y));
229 
230     }
231 
232     @Test
233     void testDivideImaginary() {
234         FieldComplex<Binary64> x = build(2d, 3d);
235         FieldComplex<Binary64> y = build(0d, 2d);
236         assertEquals(build(1.5d, -1d), x.divide(y));
237     }
238 
239     @Test
240     void testDivideInf() {
241         FieldComplex<Binary64> x = build(3, 4);
242         FieldComplex<Binary64> w = build(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);
243         assertEquals(x.divide(w), FieldComplex.getZero(Binary64Field.getInstance()));
244 
245         FieldComplex<Binary64> z = w.divide(x);
246         assertTrue(Double.isNaN(z.getReal()));
247         assertEquals(Double.POSITIVE_INFINITY, z.getImaginary().getReal(), 0);
248 
249         w = build(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
250         z = w.divide(x);
251         assertTrue(Double.isNaN(z.getImaginary().getReal()));
252         assertEquals(Double.POSITIVE_INFINITY, z.getRealPart().getReal(), 0);
253 
254         w = build(1, Double.POSITIVE_INFINITY);
255         z = w.divide(w);
256         assertTrue(Double.isNaN(z.getReal()));
257         assertTrue(Double.isNaN(z.getImaginary().getReal()));
258     }
259 
260     @Test
261     void testDivideZero() {
262         FieldComplex<Binary64> x = build(3.0, 4.0);
263         FieldComplex<Binary64> z = x.divide(FieldComplex.getZero(Binary64Field.getInstance()));
264         // Assertions.assertEquals(z, FieldComplex.getInf(Binary64Field.getInstance())); // See MATH-657
265         assertEquals(z, FieldComplex.getNaN(Binary64Field.getInstance()));
266         assertTrue(build(3.0).divide(Binary64.ZERO).isNaN());
267     }
268 
269     @Test
270     void testDivideZeroZero() {
271         FieldComplex<Binary64> x = build(0.0, 0.0);
272         FieldComplex<Binary64> z = x.divide(FieldComplex.getZero(Binary64Field.getInstance()));
273         assertEquals(z, FieldComplex.getNaN(Binary64Field.getInstance()));
274     }
275 
276     @Test
277     void testDivideNaN() {
278         FieldComplex<Binary64> x = build(3.0, 4.0);
279         FieldComplex<Binary64> z = x.divide(FieldComplex.getNaN(Binary64Field.getInstance()));
280         assertTrue(z.isNaN());
281         assertTrue(x.divide(Binary64.NAN).isNaN());
282         assertTrue(FieldComplex.getNaN(Binary64Field.getInstance()).divide(Binary64.ONE).isNaN());
283         assertTrue(FieldComplex.getNaN(Binary64Field.getInstance()).divide(FieldComplex.getNaN(Binary64Field.getInstance())).isNaN());
284     }
285 
286     @Test
287     void testDivideNaNInf() {
288        FieldComplex<Binary64> z = oneInf.divide(FieldComplex.getOne(Binary64Field.getInstance()));
289        assertTrue(Double.isNaN(z.getReal()));
290        assertEquals(Double.POSITIVE_INFINITY, z.getImaginary().getReal(), 0);
291 
292        z = negInfNegInf.divide(oneNaN);
293        assertTrue(Double.isNaN(z.getReal()));
294        assertTrue(Double.isNaN(z.getImaginary().getReal()));
295 
296        z = negInfInf.divide(FieldComplex.getOne(Binary64Field.getInstance()));
297        assertTrue(Double.isNaN(z.getReal()));
298        assertTrue(Double.isNaN(z.getImaginary().getReal()));
299     }
300 
301     @Test
302     void testScalarDivide() {
303         FieldComplex<Binary64> x = build(3.0, 4.0);
304         double yDouble = 2.0;
305         FieldComplex<Binary64> yComplex = build(yDouble);
306         assertEquals(x.divide(yComplex), x.divide(yDouble));
307         assertEquals(x.divide(yComplex), x.divide(new Binary64(yDouble)));
308     }
309 
310     @Test
311     void testScalarDivideNaN() {
312         FieldComplex<Binary64> x = build(3.0, 4.0);
313         double yDouble = Double.NaN;
314         FieldComplex<Binary64> yComplex = build(yDouble);
315         assertEquals(x.divide(yComplex), x.divide(yDouble));
316         assertEquals(x.divide(yComplex), x.divide(new Binary64(yDouble)));
317         assertTrue(FieldComplex.getNaN(Binary64Field.getInstance()).divide(Double.NaN).isNaN());
318     }
319 
320     @Test
321     void testScalarDivideInf() {
322         FieldComplex<Binary64> x = build(1,1);
323         double yDouble = Double.POSITIVE_INFINITY;
324         FieldComplex<Binary64> yComplex = build(yDouble);
325         UnitTestUtils.customAssertEquals(x.divide(yComplex), x.divide(yDouble), 0);
326         UnitTestUtils.customAssertEquals(x.divide(yComplex), x.divide(new Binary64(yDouble)), 0);
327 
328         yDouble = Double.NEGATIVE_INFINITY;
329         yComplex = build(yDouble);
330         UnitTestUtils.customAssertEquals(x.divide(yComplex), x.divide(yDouble), 0);
331         UnitTestUtils.customAssertEquals(x.divide(yComplex), x.divide(new Binary64(yDouble)), 0);
332 
333         x = build(1, Double.NEGATIVE_INFINITY);
334         UnitTestUtils.customAssertEquals(x.divide(yComplex), x.divide(yDouble), 0);
335         UnitTestUtils.customAssertEquals(x.divide(yComplex), x.divide(new Binary64(yDouble)), 0);
336 
337     }
338 
339     @Test
340     void testScalarDivideZero() {
341         FieldComplex<Binary64> x = build(1,1);
342         UnitTestUtils.customAssertEquals(x.divide(FieldComplex.getZero(Binary64Field.getInstance())), x.divide(0), 0);
343         UnitTestUtils.customAssertEquals(x.divide(FieldComplex.getZero(Binary64Field.getInstance())), x.divide(new Binary64(0)), 0);
344     }
345 
346     @Test
347     void testReciprocal() {
348         FieldComplex<Binary64> z = build(5.0, 6.0);
349         FieldComplex<Binary64> act = z.reciprocal();
350         double expRe = 5.0 / 61.0;
351         double expIm = -6.0 / 61.0;
352         assertEquals(expRe, act.getRealPart().getReal(), FastMath.ulp(expRe));
353         assertEquals(expIm, act.getImaginaryPart().getReal(), FastMath.ulp(expIm));
354     }
355 
356     @Test
357     void testReciprocalReal() {
358         FieldComplex<Binary64> z = build(-2.0, 0.0);
359         assertTrue(FieldComplex.equals(build(-0.5, 0.0), z.reciprocal()));
360     }
361 
362     @Test
363     void testReciprocalImaginary() {
364         FieldComplex<Binary64> z = build(0.0, -2.0);
365         assertEquals(build(0.0, 0.5), z.reciprocal());
366     }
367 
368     @Test
369     void testReciprocalInf() {
370         FieldComplex<Binary64> z = build(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);
371         assertEquals(z.reciprocal(), FieldComplex.getZero(Binary64Field.getInstance()));
372 
373         z = build(1, Double.POSITIVE_INFINITY).reciprocal();
374         assertEquals(z, FieldComplex.getZero(Binary64Field.getInstance()));
375     }
376 
377     @Test
378     void testReciprocalZero() {
379         assertEquals(FieldComplex.getZero(Binary64Field.getInstance()).reciprocal(), FieldComplex.getInf(Binary64Field.getInstance()));
380     }
381 
382     @Test
383     void testReciprocalNaN() {
384         assertTrue(FieldComplex.getNaN(Binary64Field.getInstance()).reciprocal().isNaN());
385     }
386 
387     @Test
388     void testMultiply() {
389         FieldComplex<Binary64> x = build(3.0, 4.0);
390         FieldComplex<Binary64> y = build(5.0, 6.0);
391         FieldComplex<Binary64> z = x.multiply(y);
392         assertEquals(-9.0, z.getRealPart().getReal(), 1.0e-5);
393         assertEquals(38.0, z.getImaginaryPart().getReal(), 1.0e-5);
394     }
395 
396     @Test
397     void testMultiplyT() {
398         FieldComplex<Binary64> z = build(3.0, 4.0).multiply(new Binary64(5.0));
399         assertEquals(15.0, z.getRealPart().getReal(), 1.0e-5);
400         assertEquals(20.0, z.getImaginaryPart().getReal(), 1.0e-5);
401     }
402 
403     @Test
404     void testMultiplyNaN() {
405         FieldComplex<Binary64> x = build(3.0, 4.0);
406         FieldComplex<Binary64> z = x.multiply(FieldComplex.getNaN(Binary64Field.getInstance()));
407         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), z);
408         z = FieldComplex.getNaN(Binary64Field.getInstance()).multiply(5);
409         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), z);
410     }
411 
412     @Test
413     void testMultiplyInfInf() {
414         // Assertions.assertTrue(infInf.multiply(infInf).isNaN()); // MATH-620
415         assertTrue(infInf.multiply(infInf).isInfinite());
416     }
417 
418     @Test
419     void testMultiplyNaNInf() {
420         FieldComplex<Binary64> z = build(1,1);
421         FieldComplex<Binary64> w = z.multiply(infOne);
422         assertEquals(Double.POSITIVE_INFINITY, w.getRealPart().getReal(), 0);
423         assertEquals(Double.POSITIVE_INFINITY, w.getImaginaryPart().getReal(), 0);
424 
425         // [MATH-164]
426         assertEquals(build(1, 0).multiply(infInf), FieldComplex.getInf(Binary64Field.getInstance()));
427         assertEquals(build(-1, 0).multiply(infInf), FieldComplex.getInf(Binary64Field.getInstance()));
428         assertEquals(build(1, 0).multiply(negInfZero), FieldComplex.getInf(Binary64Field.getInstance()));
429 
430         w = oneInf.multiply(oneNegInf);
431         assertEquals(Double.POSITIVE_INFINITY, w.getRealPart().getReal(), 0);
432         assertEquals(Double.POSITIVE_INFINITY, w.getImaginaryPart().getReal(), 0);
433 
434         w = negInfNegInf.multiply(oneNaN);
435         assertTrue(w.getRealPart().isNaN());
436         assertTrue(w.getImaginaryPart().isNaN());
437 
438         z = build(1, Double.NEGATIVE_INFINITY);
439         UnitTestUtils.customAssertSame(FieldComplex.getInf(Binary64Field.getInstance()), z.square());
440     }
441 
442     @Test
443     void testScalarMultiply() {
444         FieldComplex<Binary64> x = build(3.0, 4.0);
445         double yDouble = 2.0;
446         FieldComplex<Binary64> yComplex = build(yDouble);
447         assertEquals(x.multiply(yComplex), x.multiply(yDouble));
448         assertEquals(x.multiply(yComplex), x.multiply(new Binary64(yDouble)));
449         int zInt = -5;
450         FieldComplex<Binary64> zComplex = build(zInt);
451         assertEquals(x.multiply(zComplex), x.multiply(zInt));
452     }
453 
454     @Test
455     void testScalarMultiplyNaN() {
456         FieldComplex<Binary64> x = build(3.0, 4.0);
457         double yDouble = Double.NaN;
458         FieldComplex<Binary64> yComplex = build(yDouble);
459         assertEquals(x.multiply(yComplex), x.multiply(yDouble));
460         assertEquals(x.multiply(yComplex), x.multiply(new Binary64(yDouble)));
461         assertTrue(build(Double.NaN, 0).multiply(5).isNaN());
462         assertTrue(build(Double.NaN, 0).multiply(new Binary64(5)).isNaN());
463         assertTrue(build(0, Double.NaN).multiply(5).isNaN());
464         assertTrue(build(0, Double.NaN).multiply(new Binary64(5)).isNaN());
465         assertTrue(FieldComplex.getNaN(Binary64Field.getInstance()).multiply(5).isNaN());
466         assertTrue(FieldComplex.getNaN(Binary64Field.getInstance()).multiply(new Binary64(5)).isNaN());
467         assertTrue(build(Double.NaN, 0).multiply(5.0).isNaN());
468         assertTrue(build(Double.NaN, 0).multiply(new Binary64(5)).isNaN());
469         assertTrue(build(0, Double.NaN).multiply(5.0).isNaN());
470         assertTrue(build(0, Double.NaN).multiply(new Binary64(5)).isNaN());
471         assertTrue(FieldComplex.getNaN(Binary64Field.getInstance()).multiply(5.0).isNaN());
472         assertTrue(FieldComplex.getNaN(Binary64Field.getInstance()).multiply(new Binary64(5.0)).isNaN());
473         assertTrue(FieldComplex.getOne(Binary64Field.getInstance()).multiply(Double.NaN).isNaN());
474         assertTrue(FieldComplex.getOne(Binary64Field.getInstance()).multiply(new Binary64(Double.NaN)).isNaN());
475     }
476 
477     @Test
478     void testScalarMultiplyInf() {
479         FieldComplex<Binary64> x = build(1, 1);
480         double yDouble = Double.POSITIVE_INFINITY;
481         FieldComplex<Binary64> yComplex = build(yDouble);
482         assertEquals(x.multiply(yComplex), x.multiply(yDouble));
483         assertEquals(x.multiply(yComplex), x.multiply(new Binary64(yDouble)));
484 
485         yDouble = Double.NEGATIVE_INFINITY;
486         yComplex = build(yDouble);
487         assertEquals(x.multiply(yComplex), x.multiply(yDouble));
488         assertEquals(x.multiply(yComplex), x.multiply(new Binary64(yDouble)));
489 
490         assertTrue(build(Double.POSITIVE_INFINITY, 0).multiply(5).isInfinite());
491         assertTrue(build(Double.POSITIVE_INFINITY, 0).multiply(new Binary64(5)).isInfinite());
492         assertTrue(build(0, Double.POSITIVE_INFINITY).multiply(5).isInfinite());
493         assertTrue(build(0, Double.POSITIVE_INFINITY).multiply(new Binary64(5)).isInfinite());
494         assertTrue(FieldComplex.getInf(Binary64Field.getInstance()).multiply(5).isInfinite());
495         assertTrue(FieldComplex.getInf(Binary64Field.getInstance()).multiply(new Binary64(5)).isInfinite());
496         assertTrue(build(Double.POSITIVE_INFINITY, 0).multiply(5.0).isInfinite());
497         assertTrue(build(Double.POSITIVE_INFINITY, 0).multiply(new Binary64(5.0)).isInfinite());
498         assertTrue(build(0, Double.POSITIVE_INFINITY).multiply(5.0).isInfinite());
499         assertTrue(build(0, Double.POSITIVE_INFINITY).multiply(new Binary64(5.0)).isInfinite());
500         assertTrue(FieldComplex.getInf(Binary64Field.getInstance()).multiply(5.0).isInfinite());
501         assertTrue(FieldComplex.getInf(Binary64Field.getInstance()).multiply(new Binary64(5.0)).isInfinite());
502         assertTrue(FieldComplex.getOne(Binary64Field.getInstance()).multiply(Double.POSITIVE_INFINITY).isInfinite());
503         assertTrue(FieldComplex.getOne(Binary64Field.getInstance()).multiply(new Binary64(Double.POSITIVE_INFINITY)).isInfinite());
504     }
505 
506     @Test
507     void testNegate() {
508         FieldComplex<Binary64> x = build(3.0, 4.0);
509         FieldComplex<Binary64> z = x.negate();
510         assertEquals(-3.0, z.getRealPart().getReal(), 1.0e-5);
511         assertEquals(-4.0, z.getImaginaryPart().getReal(), 1.0e-5);
512     }
513 
514     @Test
515     void testNegateNaN() {
516         FieldComplex<Binary64> z = FieldComplex.getNaN(Binary64Field.getInstance()).negate();
517         assertTrue(z.isNaN());
518     }
519 
520     @Test
521     void testSubtract() {
522         FieldComplex<Binary64> x = build(3.0, 4.0);
523         FieldComplex<Binary64> y = build(5.0, 6.0);
524         FieldComplex<Binary64> z = x.subtract(y);
525         assertEquals(-2.0, z.getRealPart().getReal(), 1.0e-5);
526         assertEquals(-2.0, z.getImaginaryPart().getReal(), 1.0e-5);
527     }
528 
529     @Test
530     void testSubtractT() {
531         FieldComplex<Binary64> z = build(3.0, 4.0).subtract(new Binary64(5.0));
532         assertEquals(-2.0, z.getRealPart().getReal(), 1.0e-5);
533         assertEquals( 4.0, z.getImaginary().getReal(), 1.0e-5);
534     }
535 
536     @Test
537     void testSubtractNaN() {
538         FieldComplex<Binary64> x = build(3.0, 4.0);
539         FieldComplex<Binary64> z = x.subtract(FieldComplex.getNaN(Binary64Field.getInstance()));
540         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), z);
541         z = build(1, Double.NaN);
542         FieldComplex<Binary64> w = x.subtract(z);
543         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), w);
544         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), FieldComplex.getNaN(Binary64Field.getInstance()).subtract(FieldComplex.getNaN(Binary64Field.getInstance())));
545         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), FieldComplex.getNaN(Binary64Field.getInstance()).subtract(Double.NaN));
546     }
547 
548     @Test
549     void testSubtractInf() {
550         FieldComplex<Binary64> x = build(1, 1);
551         FieldComplex<Binary64> z = build(Double.NEGATIVE_INFINITY, 0);
552         FieldComplex<Binary64> w = x.subtract(z);
553         assertEquals(1, w.getImaginaryPart().getReal(), 0);
554         assertEquals(Double.POSITIVE_INFINITY, w.getRealPart().getReal(), 0);
555 
556         x = build(Double.NEGATIVE_INFINITY, 0);
557         assertTrue(Double.isNaN(x.subtract(z).getReal()));
558     }
559 
560     @Test
561     void testScalarSubtract() {
562         FieldComplex<Binary64> x = build(3.0, 4.0);
563         double yDouble = 2.0;
564         FieldComplex<Binary64> yComplex = build(yDouble);
565         assertEquals(x.subtract(yComplex), x.subtract(yDouble));
566         assertEquals(x.subtract(yComplex), x.subtract(new Binary64(yDouble)));
567     }
568 
569     @Test
570     void testScalarSubtractNaN() {
571         FieldComplex<Binary64> x = build(3.0, 4.0);
572         double yDouble = Double.NaN;
573         FieldComplex<Binary64> yComplex = build(yDouble);
574         assertEquals(x.subtract(yComplex), x.subtract(yDouble));
575         assertEquals(x.subtract(yComplex), x.subtract(new Binary64(yDouble)));
576         assertTrue(build(Double.NaN).subtract(0).isNaN());
577         assertTrue(build(Double.NaN).subtract(Binary64.ZERO).isNaN());
578     }
579 
580     @Test
581     void testScalarSubtractInf() {
582         FieldComplex<Binary64> x = build(1, 1);
583         double yDouble = Double.POSITIVE_INFINITY;
584         FieldComplex<Binary64> yComplex = build(yDouble);
585         assertEquals(x.subtract(yComplex), x.subtract(yDouble));
586         assertEquals(x.subtract(yComplex), x.subtract(new Binary64(yDouble)));
587 
588         x = build(Double.NEGATIVE_INFINITY, 0);
589         assertEquals(x.subtract(yComplex), x.subtract(yDouble));
590         assertEquals(x.subtract(yComplex), x.subtract(new Binary64(yDouble)));
591     }
592 
593     @Test
594     void testEqualsNull() {
595         FieldComplex<Binary64> x = build(3.0, 4.0);
596         assertNotEquals(null, x);
597     }
598 
599     @Test
600     void testFloatingPointEqualsPrecondition1() {
601         assertThrows(NullPointerException.class, () -> {
602             FieldComplex.equals(build(3.0, 4.0), null, 3);
603         });
604     }
605 
606     @Test
607     void testFloatingPointEqualsPrecondition2() {
608         assertThrows(NullPointerException.class, () -> {
609             FieldComplex.equals(null, build(3.0, 4.0), 3);
610         });
611     }
612 
613     @SuppressWarnings("unlikely-arg-type")
614     @Test
615     void testEqualsClass() {
616         FieldComplex<Binary64> x = build(3.0, 4.0);
617         assertNotEquals(x, this);
618     }
619 
620     @Test
621     void testEqualsSame() {
622         FieldComplex<Binary64> x = build(3.0, 4.0);
623         assertEquals(x, x);
624     }
625 
626     @Test
627     void testFloatingPointEquals() {
628         double re = -3.21;
629         double im = 456789e10;
630 
631         final FieldComplex<Binary64> x = build(re, im);
632         FieldComplex<Binary64> y = build(re, im);
633 
634         assertEquals(x, y);
635         assertTrue(FieldComplex.equals(x, y));
636 
637         final int maxUlps = 5;
638         for (int i = 0; i < maxUlps; i++) {
639             re = FastMath.nextUp(re);
640             im = FastMath.nextUp(im);
641         }
642         y = build(re, im);
643         assertTrue(FieldComplex.equals(x, y, maxUlps));
644 
645         re = FastMath.nextUp(re);
646         im = FastMath.nextUp(im);
647         y = build(re, im);
648         assertFalse(FieldComplex.equals(x, y, maxUlps));
649     }
650 
651     @Test
652     void testFloatingPointEqualsNaN() {
653         FieldComplex<Binary64> c = build(Double.NaN, 1);
654         assertFalse(FieldComplex.equals(c, c));
655 
656         c = build(1, Double.NaN);
657         assertFalse(FieldComplex.equals(c, c));
658     }
659 
660     @Test
661     void testFloatingPointEqualsWithAllowedDelta() {
662         final double re = 153.0000;
663         final double im = 152.9375;
664         final double tol1 = 0.0625;
665         final FieldComplex<Binary64> x = build(re, im);
666         final FieldComplex<Binary64> y = build(re + tol1, im + tol1);
667         assertTrue(FieldComplex.equals(x, y, tol1));
668 
669         final double tol2 = 0.0624;
670         assertFalse(FieldComplex.equals(x, y, tol2));
671     }
672 
673     @Test
674     void testFloatingPointEqualsWithAllowedDeltaNaN() {
675         final FieldComplex<Binary64> x = build(0, Double.NaN);
676         final FieldComplex<Binary64> y = build(Double.NaN, 0);
677         assertFalse(FieldComplex.equals(x, FieldComplex.getZero(Binary64Field.getInstance()), 0.1));
678         assertFalse(FieldComplex.equals(x, x, 0.1));
679         assertFalse(FieldComplex.equals(x, y, 0.1));
680     }
681 
682     @Test
683     void testFloatingPointEqualsWithRelativeTolerance() {
684         final double tol = 1e-4;
685         final double re = 1;
686         final double im = 1e10;
687 
688         final double f = 1 + tol;
689         final FieldComplex<Binary64> x = build(re, im);
690         final FieldComplex<Binary64> y = build(re * f, im * f);
691         assertTrue(FieldComplex.equalsWithRelativeTolerance(x, y, tol));
692     }
693 
694     @Test
695     void testFloatingPointEqualsWithRelativeToleranceNaN() {
696         final FieldComplex<Binary64> x = build(0, Double.NaN);
697         final FieldComplex<Binary64> y = build(Double.NaN, 0);
698         assertFalse(FieldComplex.equalsWithRelativeTolerance(x, FieldComplex.getZero(Binary64Field.getInstance()), 0.1));
699         assertFalse(FieldComplex.equalsWithRelativeTolerance(x, x, 0.1));
700         assertFalse(FieldComplex.equalsWithRelativeTolerance(x, y, 0.1));
701     }
702 
703     @Test
704     void testEqualsTrue() {
705         FieldComplex<Binary64> x = build(3.0, 4.0);
706         FieldComplex<Binary64> y = build(3.0, 4.0);
707         assertEquals(x, y);
708     }
709 
710     @Test
711     void testEqualsRealDifference() {
712         FieldComplex<Binary64> x = build(0.0, 0.0);
713         FieldComplex<Binary64> y = build(0.0 + Double.MIN_VALUE, 0.0);
714         assertNotEquals(x, y);
715     }
716 
717     @Test
718     void testEqualsImaginaryDifference() {
719         FieldComplex<Binary64> x = build(0.0, 0.0);
720         FieldComplex<Binary64> y = build(0.0, 0.0 + Double.MIN_VALUE);
721         assertNotEquals(x, y);
722     }
723 
724     @Test
725     void testEqualsNaN() {
726         FieldComplex<Binary64> realNaN = build(Double.NaN, 0.0);
727         FieldComplex<Binary64> imaginaryNaN = build(0.0, Double.NaN);
728         FieldComplex<Binary64> complexNaN = FieldComplex.getNaN(Binary64Field.getInstance());
729         assertEquals(realNaN, imaginaryNaN);
730         assertEquals(imaginaryNaN, complexNaN);
731         assertEquals(realNaN, complexNaN);
732     }
733 
734     @Test
735     void testHashCode() {
736         FieldComplex<Binary64> x = build(0.0, 0.0);
737         FieldComplex<Binary64> y = build(0.0, 0.0 + Double.MIN_VALUE);
738         assertFalse(x.hashCode()==y.hashCode());
739         y = build(0.0 + Double.MIN_VALUE, 0.0);
740         assertFalse(x.hashCode()==y.hashCode());
741         FieldComplex<Binary64> realNaN = build(Double.NaN, 0.0);
742         FieldComplex<Binary64> imaginaryNaN = build(0.0, Double.NaN);
743         assertEquals(realNaN.hashCode(), imaginaryNaN.hashCode());
744         assertEquals(imaginaryNaN.hashCode(), FieldComplex.getNaN(Binary64Field.getInstance()).hashCode());
745 
746         // MATH-1118
747         // "equals" and "hashCode" must be compatible: if two objects have
748         // different hash codes, "equals" must return false.
749         final String msg = "'equals' not compatible with 'hashCode'";
750 
751         x = build(0.0, 0.0);
752         y = build(0.0, -0.0);
753         assertTrue(x.hashCode() != y.hashCode());
754         assertNotEquals(x, y, msg);
755 
756         x = build(0.0, 0.0);
757         y = build(-0.0, 0.0);
758         assertTrue(x.hashCode() != y.hashCode());
759         assertNotEquals(x, y, msg);
760     }
761 
762     @Test
763     void testToDegreesComplex() {
764         FieldComplex<Binary64> z = build(3, 4);
765         FieldComplex<Binary64> expected = build(FastMath.toDegrees(z.getRealPart().getReal()), FastMath.toDegrees(z.getImaginaryPart().getReal()));
766         UnitTestUtils.customAssertEquals(expected, z.toDegrees(), 1.0e-15);
767     }
768 
769     @Test
770     void testToRadiansComplex() {
771         FieldComplex<Binary64> z = build(3, 4);
772         FieldComplex<Binary64> expected = build(FastMath.toRadians(z.getRealPart().getReal()), FastMath.toRadians(z.getImaginaryPart().getReal()));
773         UnitTestUtils.customAssertEquals(expected, z.toRadians(), 1.0e-15);
774     }
775 
776     @Test
777     void testAcosComplex() {
778         FieldComplex<Binary64> z = build(3, 4);
779         FieldComplex<Binary64> expected = build(0.936812, -2.30551);
780         UnitTestUtils.customAssertEquals(expected, z.acos(), 1.0e-5);
781         UnitTestUtils.customAssertEquals(build(FastMath.acos(0), 0),
782                                          FieldComplex.getZero(Binary64Field.getInstance()).acos(), 1.0e-12);
783     }
784 
785     @Test
786     void testAcosNaN() {
787         assertTrue(FieldComplex.getNaN(Binary64Field.getInstance()).acos().isNaN());
788     }
789 
790     @Test
791     void testAcosInf() {
792         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), oneInf.acos());
793         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), oneNegInf.acos());
794         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), infOne.acos());
795         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), negInfOne.acos());
796         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), infInf.acos());
797         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), infNegInf.acos());
798         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), negInfInf.acos());
799         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), negInfNegInf.acos());
800     }
801 
802     @Test
803     void testAcosBranchCuts() {
804         UnitTestUtils.customAssertEquals(build(3.141592653589793238462, -0.76103968373182660633),
805                                          FastMath.acos(build(-1.3038404810405297, +0.0)),
806                                          1.0e-14);
807         UnitTestUtils.customAssertEquals(build(3.141592653589793238462, +0.76103968373182660633),
808                                          FastMath.acos(build(-1.3038404810405297, -0.0)),
809                                          1.0e-14);
810         UnitTestUtils.customAssertEquals(build(0.0, -0.76103968373182660633),
811                                          FastMath.acos(build(1.3038404810405297, +0.0)),
812                                          1.0e-14);
813         UnitTestUtils.customAssertEquals(build(0.0, +0.76103968373182660633),
814                                          FastMath.acos(build(1.3038404810405297, -0.0)),
815                                          1.0e-14);
816     }
817 
818     @Test
819     void testAsinComplex() {
820         FieldComplex<Binary64> z = build(3, 4);
821         FieldComplex<Binary64> expected = build(0.633984, 2.30551);
822         UnitTestUtils.customAssertEquals(expected, z.asin(), 1.0e-5);
823     }
824 
825     @Test
826     void testAsinNaN() {
827         assertTrue(FieldComplex.getNaN(Binary64Field.getInstance()).asin().isNaN());
828     }
829 
830     @Test
831     void testAsinInf() {
832         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), oneInf.asin());
833         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), oneNegInf.asin());
834         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), infOne.asin());
835         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), negInfOne.asin());
836         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), infInf.asin());
837         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), infNegInf.asin());
838         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), negInfInf.asin());
839         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), negInfNegInf.asin());
840     }
841 
842     @Test
843     void testAsinBranchCuts() {
844         UnitTestUtils.customAssertEquals(build(-1.57079632679489661923, +0.76103968373182660633),
845                                          FastMath.asin(build(-1.3038404810405297, +0.0)),
846                                          1.0e-14);
847         UnitTestUtils.customAssertEquals(build(-1.57079632679489661923, -0.76103968373182660633),
848                                          FastMath.asin(build(-1.3038404810405297, -0.0)),
849                                          1.0e-14);
850         UnitTestUtils.customAssertEquals(build(1.57079632679489661923, +0.76103968373182660633),
851                                          FastMath.asin(build(1.3038404810405297, +0.0)),
852                                          1.0e-14);
853         UnitTestUtils.customAssertEquals(build(1.57079632679489661923, -0.76103968373182660633),
854                                          FastMath.asin(build(1.3038404810405297, -0.0)),
855                                          1.0e-14);
856     }
857 
858     @Test
859     void testAtanComplex() {
860         FieldComplex<Binary64> z = build(3, 4);
861         FieldComplex<Binary64> expected = build(1.44831, 0.158997);
862         UnitTestUtils.customAssertEquals(expected, z.atan(), 1.0e-5);
863     }
864 
865     @Test
866     void testAtanInf() {
867         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), oneInf.atan());
868         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), oneNegInf.atan());
869         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), infOne.atan());
870         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), negInfOne.atan());
871         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), infInf.atan());
872         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), infNegInf.atan());
873         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), negInfInf.atan());
874         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), negInfNegInf.atan());
875     }
876 
877     @Test
878     void testAtanI() {
879         assertTrue(FieldComplex.getI(Binary64Field.getInstance()).atan().isNaN());
880     }
881 
882     @Test
883     void testAtanNaN() {
884         assertTrue(FieldComplex.getNaN(Binary64Field.getInstance()).atan().isNaN());
885     }
886 
887     @Test
888     void testAtanBranchCuts() {
889         UnitTestUtils.customAssertEquals(build(+1.5707963267948966192, +1.0986122886681096913),
890                                          FastMath.atan(build(+0.0, 1.25)),
891                                          1.0e-14);
892         UnitTestUtils.customAssertEquals(build(-1.5707963267948966192, +1.0986122886681096913),
893                                          FastMath.atan(build(-0.0, 1.25)),
894                                          1.0e-14);
895         UnitTestUtils.customAssertEquals(build(+1.5707963267948966192, -1.0986122886681096913),
896                                          FastMath.atan(build(+0.0, -1.25)),
897                                          1.0e-14);
898         UnitTestUtils.customAssertEquals(build(-1.5707963267948966192, -1.0986122886681096913),
899                                          FastMath.atan(build(-0.0, -1.25)),
900                                          1.0e-14);
901         UnitTestUtils.customAssertEquals(build(0.0, +0.25541281188299534160),
902                                          FastMath.atan(build(+0.0, 0.25)),
903                                          1.0e-14);
904         assertTrue(FastMath.copySign(1.0, FastMath.atan(build(+0.0, 0.25)).getReal()) > 0.0);
905         UnitTestUtils.customAssertEquals(build(0.0, +0.25541281188299534160),
906                                          FastMath.atan(build(-0.0, 0.25)),
907                                          1.0e-14);
908         assertTrue(FastMath.copySign(1.0, FastMath.atan(build(-0.0, 0.25)).getReal()) < 0.0);
909         UnitTestUtils.customAssertEquals(build(0.0, -0.25541281188299534160),
910                                          FastMath.atan(build(+0.0, -0.25)),
911                                          1.0e-14);
912         assertTrue(FastMath.copySign(1.0, FastMath.atan(build(+0.0, -0.25)).getReal()) > 0.0);
913         UnitTestUtils.customAssertEquals(build(0.0, -0.25541281188299534160),
914                                          FastMath.atan(build(-0.0, -0.25)),
915                                          1.0e-14);
916         assertTrue(FastMath.copySign(1.0, FastMath.atan(build(-0.0, -0.25)).getReal()) < 0.0);
917     }
918 
919     @Test
920     public void testAtanReal() {
921         final FieldComplex<Binary64> zP = build(0.8734729023516287, 0.0);
922         final FieldComplex<Binary64> aP = build(0.717964439926383,  0.0);
923         Assertions.assertEquals(aP, zP.atan());
924         Assertions.assertEquals(1.0, FastMath.copySign(new Binary64(1.0), zP.atan().getImaginary()).getReal(), 1.0e-15);
925         final FieldComplex<Binary64> zM = build(0.8734729023516287, -0.0);
926         final FieldComplex<Binary64> aM = build(0.717964439926383,  -0.0);
927         Assertions.assertEquals(aM, zM.atan());
928         Assertions.assertEquals(-1.0, FastMath.copySign(new Binary64(1.0), zM.atan().getImaginary()).getReal(), 1.0e-15);
929     }
930 
931     @Test
932     @Override
933     public void testAtan2() {
934         for (double x = -3; x < 3; x += 0.2) {
935             for (double y = -3; y < 3; y += 0.2) {
936                 final FieldComplex<Binary64> z = build(x).atan2(build(y));
937                 final double  r = FastMath.atan2(x, y);
938                 checkRelative(r, build(MathUtils.normalizeAngle(z.getRealPart().getReal(), r), z.getImaginaryPart().getReal()));
939             }
940         }
941     }
942 
943     @Test
944     void testAtan2Complex() {
945         for (double r1 : Arrays.asList(-3, 3)) {
946             for (double i1 : Arrays.asList(-2, 0, 2)) {
947                 final FieldComplex<Binary64> c1 = build(r1, i1);
948                 for (double r2 : Arrays.asList(-1, 1)) {
949                     for (double i2 : Arrays.asList(-5, 0, 5)) {
950                         final FieldComplex<Binary64> c2 = build(r2, i2);
951                         UnitTestUtils.customAssertEquals(c1.divide(c2), c1.atan2(c2).tan(), 1.0e-14);
952                         final FieldComplex<Binary64> atan   = c1.divide(c2).atan();
953                         final FieldComplex<Binary64> atan2  = c1.atan2(c2);
954                         final double  deltaR = FastMath.abs(atan.getReal() - atan2.getReal()) / FastMath.PI;
955                         assertTrue(FastMath.abs(deltaR - FastMath.rint(deltaR)) < 1.0e-14);
956                         assertEquals(atan.getImaginaryPart().getReal(), atan2.getImaginaryPart().getReal(), 1.0e-14);
957                     }
958                 }
959             }
960         }
961     }
962 
963     @Test
964     void testAtan2Real() {
965         for (double r1 : Arrays.asList(-3, 3)) {
966             final FieldComplex<Binary64> c1 = build(r1, 0);
967             for (double r2 : Arrays.asList(-1, 1)) {
968                 final FieldComplex<Binary64> c2 = build(r2, 0);
969                 assertEquals(FastMath.atan2(r1, r2),
970                                     MathUtils.normalizeAngle(c1.atan2(c2).getRealPart().getReal(), 0.0),
971                                     1.0e-14);
972             }
973         }
974     }
975 
976     @Override
977     @Test
978     public void testAtan2SpecialCases() {
979         assertTrue(build(+0.0).atan2(build(+0.0)).isNaN());
980         assertTrue(build(-0.0).atan2(build(+0.0)).isNaN());
981         assertTrue(build(+0.0).atan2(build(-0.0)).isNaN());
982         assertTrue(build(-0.0).atan2(build(-0.0)).isNaN());
983     }
984 
985     @Test
986     void testCosComplex() {
987         FieldComplex<Binary64> z = build(3, 4);
988         FieldComplex<Binary64> expected = build(-27.03495, -3.851153);
989         UnitTestUtils.customAssertEquals(expected, z.cos(), 1.0e-5);
990     }
991 
992     @Test
993     void testCosNaN() {
994         assertTrue(FieldComplex.getNaN(Binary64Field.getInstance()).cos().isNaN());
995     }
996 
997     @Test
998     void testCosInf() {
999         UnitTestUtils.customAssertSame(infNegInf, oneInf.cos());
1000         UnitTestUtils.customAssertSame(infInf, oneNegInf.cos());
1001         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), infOne.cos());
1002         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), negInfOne.cos());
1003         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), infInf.cos());
1004         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), infNegInf.cos());
1005         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), negInfInf.cos());
1006         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), negInfNegInf.cos());
1007     }
1008 
1009     @Test
1010     void testCoshComplex() {
1011         FieldComplex<Binary64> z = build(3, 4);
1012         FieldComplex<Binary64> expected = build(-6.58066, -7.58155);
1013         UnitTestUtils.customAssertEquals(expected, z.cosh(), 1.0e-5);
1014     }
1015 
1016     @Test
1017     void testCoshNaN() {
1018         assertTrue(FieldComplex.getNaN(Binary64Field.getInstance()).cosh().isNaN());
1019     }
1020 
1021     @Test
1022     void testCoshInf() {
1023         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), oneInf.cosh());
1024         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), oneNegInf.cosh());
1025         UnitTestUtils.customAssertSame(infInf, infOne.cosh());
1026         UnitTestUtils.customAssertSame(infNegInf, negInfOne.cosh());
1027         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), infInf.cosh());
1028         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), infNegInf.cosh());
1029         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), negInfInf.cosh());
1030         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), negInfNegInf.cosh());
1031     }
1032 
1033     @Test
1034     void testExpComplex() {
1035         FieldComplex<Binary64> z = build(3, 4);
1036         FieldComplex<Binary64> expected = build(-13.12878, -15.20078);
1037         UnitTestUtils.customAssertEquals(expected, z.exp(), 1.0e-5);
1038         UnitTestUtils.customAssertEquals(FieldComplex.getOne(Binary64Field.getInstance()),
1039                                          FieldComplex.getZero(Binary64Field.getInstance()).exp(), 10e-12);
1040         FieldComplex<Binary64> iPi = FieldComplex.getI(Binary64Field.getInstance()).multiply(build(FastMath.PI, 0));
1041         UnitTestUtils.customAssertEquals(FieldComplex.getOne(Binary64Field.getInstance()).negate(),
1042                                          iPi.exp(), 10e-12);
1043     }
1044 
1045     @Test
1046     void testExpNaN() {
1047         assertTrue(FieldComplex.getNaN(Binary64Field.getInstance()).exp().isNaN());
1048     }
1049 
1050     @Test
1051     void testExpInf1() {
1052         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), oneInf.exp());
1053     }
1054 
1055     @Test
1056     void testExpInf2() {
1057         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), oneNegInf.exp());
1058     }
1059 
1060     @Test
1061     void testExpInf3() {
1062         UnitTestUtils.customAssertSame(infInf, infOne.exp());
1063     }
1064 
1065     @Test
1066     void testExpInf4() {
1067         final FieldComplex<Binary64> exp = negInfOne.exp();
1068         UnitTestUtils.customAssertSame(FieldComplex.getZero(Binary64Field.getInstance()), exp);
1069     }
1070 
1071     @Test
1072     void testExpInf5() {
1073         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), infInf.exp());
1074     }
1075 
1076     @Test
1077     void testExpInf6() {
1078         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), infNegInf.exp());
1079     }
1080 
1081     @Test
1082     void testExpInf7() {
1083         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), negInfInf.exp());
1084     }
1085 
1086     @Test
1087     void testExpInf8() {
1088         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), negInfNegInf.exp());
1089     }
1090 
1091     @Test
1092     void testExpM1() {
1093         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), FieldComplex.getNaN(Binary64Field.getInstance()).expm1());
1094         final double testValue = FastMath.scalb(1.0, -30);
1095         assertEquals(FastMath.expm1(testValue), build(testValue, 0).expm1().getRealPart().getReal(), 1.0e-30);
1096         assertTrue(FastMath.expm1(testValue) - build(testValue).exp().subtract(1.0).getReal() > 4.0e-19);
1097         assertEquals(0.0, build(0, testValue).expm1().getRealPart().getReal(), 1.0e-30);
1098         assertEquals(0.0, build(0, testValue).expm1().getImaginaryPart().getReal(), 1.0e-30);
1099     }
1100 
1101     @Test
1102     void testLogComplex() {
1103         FieldComplex<Binary64> z = build(3, 4);
1104         FieldComplex<Binary64> expected = build(1.60944, 0.927295);
1105         UnitTestUtils.customAssertEquals(expected, z.log(), 1.0e-5);
1106     }
1107 
1108     @Test
1109     void testLogNaN() {
1110         assertTrue(FieldComplex.getNaN(Binary64Field.getInstance()).log().isNaN());
1111     }
1112 
1113     @Test
1114     void testLogInf() {
1115         UnitTestUtils.customAssertEquals(build(Double.POSITIVE_INFINITY, FastMath.PI / 2),
1116                                          oneInf.log(), 10e-12);
1117         UnitTestUtils.customAssertEquals(build(Double.POSITIVE_INFINITY, -FastMath.PI / 2),
1118                                          oneNegInf.log(), 10e-12);
1119         UnitTestUtils.customAssertEquals(infZero, infOne.log(), 10e-12);
1120         UnitTestUtils.customAssertEquals(build(Double.POSITIVE_INFINITY, FastMath.PI),
1121                                          negInfOne.log(), 10e-12);
1122         UnitTestUtils.customAssertEquals(build(Double.POSITIVE_INFINITY, FastMath.PI / 4),
1123                                          infInf.log(), 10e-12);
1124         UnitTestUtils.customAssertEquals(build(Double.POSITIVE_INFINITY, -FastMath.PI / 4),
1125                                          infNegInf.log(), 10e-12);
1126         UnitTestUtils.customAssertEquals(build(Double.POSITIVE_INFINITY, 3d * FastMath.PI / 4),
1127                                          negInfInf.log(), 10e-12);
1128         UnitTestUtils.customAssertEquals(build(Double.POSITIVE_INFINITY, - 3d * FastMath.PI / 4),
1129                                          negInfNegInf.log(), 10e-12);
1130     }
1131 
1132     @Test
1133     void testLogZero() {
1134         UnitTestUtils.customAssertSame(negInfZero, FieldComplex.getZero(Binary64Field.getInstance()).log());
1135     }
1136 
1137     @Test
1138     void testLog1P() {
1139         FieldComplex<Binary64> z = build(2, 4);
1140         FieldComplex<Binary64> expected = build(1.60944, 0.927295);
1141         UnitTestUtils.customAssertEquals(expected, z.log1p(), 1.0e-5);
1142     }
1143 
1144     @Test
1145     void testLog10Complex() {
1146         UnitTestUtils.customAssertEquals(build(2.0, 0.0), build(100, 0).log10(), 1.0e-15);
1147         UnitTestUtils.customAssertEquals(build(2.0, 0.5 * FastMath.PI / FastMath.log(10)), build(0, 100).log10(), 1.0e-15);
1148     }
1149 
1150     @Test
1151     @Override
1152     public void testLog10() {
1153         for (double x = -0.9; x < 0.9; x += 0.05) {
1154             if (x < 0) {
1155                 // special case for Complex
1156                 assertTrue(Double.isNaN(FastMath.log10(x)));
1157                 assertFalse(build(x).log10().isNaN());
1158             } else {
1159                 checkRelative(FastMath.log10(x), build(x).log10());
1160             }
1161         }
1162     }
1163 
1164     @Test
1165     @Override
1166     public void testPowField() {
1167         for (double x = -0.9; x < 0.9; x += 0.05) {
1168             for (double y = 0.1; y < 4; y += 0.2) {
1169                 if ( x < 0) {
1170                     // special case for Complex
1171                     assertTrue(Double.isNaN(FastMath.pow(x, y)));
1172                     assertFalse(build(x).pow(build(y)).isNaN());
1173                 } else {
1174                     checkRelative(FastMath.pow(x, y), build(x).pow(build(y)));
1175                 }
1176             }
1177         }
1178     }
1179 
1180     @Test
1181     @Override
1182     public void testPowDouble() {
1183         for (double x = -0.9; x < 0.9; x += 0.05) {
1184             for (double y = 0.1; y < 4; y += 0.2) {
1185                 if ( x < 0) {
1186                     // special case for Complex
1187                     assertTrue(Double.isNaN(FastMath.pow(x, y)));
1188                     assertFalse(build(x).pow(y).isNaN());
1189                 } else {
1190                     checkRelative(FastMath.pow(x, y), build(x).pow(y));
1191                 }
1192             }
1193         }
1194     }
1195 
1196     public void testPowT() {
1197         for (double x = -0.9; x < 0.9; x += 0.05) {
1198             for (double y = 0.1; y < 4; y += 0.2) {
1199                 if ( x < 0) {
1200                     // special case for Complex
1201                     assertTrue(Double.isNaN(FastMath.pow(x, y)));
1202                     assertFalse(build(x).pow(new Binary64(y)).isNaN());
1203                 } else {
1204                     checkRelative(FastMath.pow(x, y), build(x).pow(new Binary64(y)));
1205                 }
1206             }
1207         }
1208     }
1209 
1210     @Test
1211     void testPow() {
1212         FieldComplex<Binary64> x = build(3, 4);
1213         FieldComplex<Binary64> y = build(5, 6);
1214         FieldComplex<Binary64> expected = build(-1.860893, 11.83677);
1215         UnitTestUtils.customAssertEquals(expected, x.pow(y), 1.0e-5);
1216         UnitTestUtils.customAssertEquals(build(-46, 9).divide(2197), build(2, -3).pow(build(-3, 0)), 1.0e-15);
1217         UnitTestUtils.customAssertEquals(build(-1, 0).divide(8), build(-2, 0).pow(build(-3, 0)), 1.0e-15);
1218         UnitTestUtils.customAssertEquals(build(0, 2),
1219                                          build(-4, 0).pow(build(0.5, 0)),
1220                                          1.0e-15);
1221     }
1222 
1223     @Test
1224     void testPowNaNBase() {
1225         FieldComplex<Binary64> x = build(3, 4);
1226         assertTrue(FieldComplex.getNaN(Binary64Field.getInstance()).pow(x).isNaN());
1227     }
1228 
1229     @Test
1230     void testPowNaNExponent() {
1231         FieldComplex<Binary64> x = build(3, 4);
1232         assertTrue(x.pow(FieldComplex.getNaN(Binary64Field.getInstance())).isNaN());
1233     }
1234 
1235     @Test
1236     void testPowInf() {
1237         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), FieldComplex.getOne(Binary64Field.getInstance()).pow(oneInf));
1238         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), FieldComplex.getOne(Binary64Field.getInstance()).pow(oneNegInf));
1239         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), FieldComplex.getOne(Binary64Field.getInstance()).pow(infOne));
1240         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), FieldComplex.getOne(Binary64Field.getInstance()).pow(infInf));
1241         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), FieldComplex.getOne(Binary64Field.getInstance()).pow(infNegInf));
1242         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), FieldComplex.getOne(Binary64Field.getInstance()).pow(negInfInf));
1243         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), FieldComplex.getOne(Binary64Field.getInstance()).pow(negInfNegInf));
1244         UnitTestUtils.customAssertSame(FieldComplex.getInf(Binary64Field.getInstance()), infOne.pow(FieldComplex.getOne(Binary64Field.getInstance())));
1245         UnitTestUtils.customAssertSame(FieldComplex.getInf(Binary64Field.getInstance()), negInfOne.pow(FieldComplex.getOne(Binary64Field.getInstance())));
1246         UnitTestUtils.customAssertSame(FieldComplex.getInf(Binary64Field.getInstance()), infInf.pow(FieldComplex.getOne(Binary64Field.getInstance())));
1247         UnitTestUtils.customAssertSame(FieldComplex.getInf(Binary64Field.getInstance()), infNegInf.pow(FieldComplex.getOne(Binary64Field.getInstance())));
1248         UnitTestUtils.customAssertSame(FieldComplex.getInf(Binary64Field.getInstance()), negInfInf.pow(FieldComplex.getOne(Binary64Field.getInstance())));
1249         UnitTestUtils.customAssertSame(FieldComplex.getInf(Binary64Field.getInstance()), negInfNegInf.pow(FieldComplex.getOne(Binary64Field.getInstance())));
1250         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), negInfNegInf.pow(infNegInf));
1251         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), negInfNegInf.pow(negInfNegInf));
1252         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), negInfNegInf.pow(infInf));
1253         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), infInf.pow(infNegInf));
1254         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), infInf.pow(negInfNegInf));
1255         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), infInf.pow(infInf));
1256         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), infNegInf.pow(infNegInf));
1257         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), infNegInf.pow(negInfNegInf));
1258         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), infNegInf.pow(infInf));
1259     }
1260 
1261     @Test
1262     void testPowZero() {
1263         UnitTestUtils.customAssertEquals(FieldComplex.getZero(Binary64Field.getInstance()),
1264                                          FieldComplex.getZero(Binary64Field.getInstance()).pow(FieldComplex.getOne(Binary64Field.getInstance())), 1.0e-12);
1265         UnitTestUtils.customAssertSame(FieldComplex.getOne(Binary64Field.getInstance()),
1266                                        FieldComplex.getZero(Binary64Field.getInstance()).pow(FieldComplex.getZero(Binary64Field.getInstance())));
1267         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()),
1268                                        FieldComplex.getZero(Binary64Field.getInstance()).pow(FieldComplex.getI(Binary64Field.getInstance())));
1269         UnitTestUtils.customAssertEquals(FieldComplex.getOne(Binary64Field.getInstance()),
1270                                          FieldComplex.getOne(Binary64Field.getInstance()).pow(FieldComplex.getZero(Binary64Field.getInstance())), 10e-12);
1271         UnitTestUtils.customAssertEquals(FieldComplex.getOne(Binary64Field.getInstance()),
1272                                          FieldComplex.getI(Binary64Field.getInstance()).pow(FieldComplex.getZero(Binary64Field.getInstance())), 10e-12);
1273         UnitTestUtils.customAssertEquals(FieldComplex.getOne(Binary64Field.getInstance()),
1274                                          build(-1, 3).pow(FieldComplex.getZero(Binary64Field.getInstance())), 10e-12);
1275     }
1276 
1277     @Test
1278     void testZeroPow() {
1279         UnitTestUtils.customAssertEquals(FieldComplex.getZero(Binary64Field.getInstance()), FieldComplex.getZero(Binary64Field.getInstance()).pow(2.0), 1.0e-5);
1280     }
1281 
1282     @Test
1283     void testScalarPow() {
1284         FieldComplex<Binary64> x = build(3, 4);
1285         double yDouble = 5.0;
1286         FieldComplex<Binary64> yComplex = build(yDouble);
1287         assertEquals(x.pow(yComplex), x.pow(yDouble));
1288         assertEquals(x.pow(yComplex), x.pow(new Binary64(yDouble)));
1289         UnitTestUtils.customAssertEquals(FieldComplex.getOne(Binary64Field.getInstance()).negate(),
1290                                          FieldComplex.getOne(Binary64Field.getInstance()).negate().pow(0.5).pow(2),
1291                                          1.0e-15);
1292         UnitTestUtils.customAssertEquals(FieldComplex.getOne(Binary64Field.getInstance()).negate(),
1293                                          FieldComplex.getOne(Binary64Field.getInstance()).negate().pow(new Binary64(0.5)).pow(new Binary64(2)),
1294                                          1.0e-15);
1295         UnitTestUtils.customAssertEquals(build(2, 0), build(4, 0).pow(0.5), 1.0e-15);
1296         UnitTestUtils.customAssertEquals(build(2, 0), build(4, 0).pow(new Binary64(0.5)), 1.0e-15);
1297         UnitTestUtils.customAssertEquals(build(2, 0), build(4, 0).pow(build(0.5, 0)), 1.0e-15);
1298     }
1299 
1300     @Test
1301     void testScalarPowNaNBase() {
1302         FieldComplex<Binary64> x = FieldComplex.getNaN(Binary64Field.getInstance());
1303         double yDouble = 5.0;
1304         FieldComplex<Binary64> yComplex = build(yDouble);
1305         assertEquals(x.pow(yComplex), x.pow(yDouble));
1306         assertEquals(x.pow(yComplex), x.pow(new Binary64(yDouble)));
1307     }
1308 
1309     @Test
1310     void testScalarPowNaNExponent() {
1311         FieldComplex<Binary64> x = build(3, 4);
1312         double yDouble = Double.NaN;
1313         FieldComplex<Binary64> yComplex = build(yDouble);
1314         assertEquals(x.pow(yComplex), x.pow(yDouble));
1315         assertEquals(x.pow(yComplex), x.pow(new Binary64(yDouble)));
1316     }
1317 
1318     @Test
1319     void testScalarPowInf() {
1320        UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), FieldComplex.getOne(Binary64Field.getInstance()).pow(Double.POSITIVE_INFINITY));
1321        UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), FieldComplex.getOne(Binary64Field.getInstance()).pow(new Binary64(Double.POSITIVE_INFINITY)));
1322        UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), FieldComplex.getOne(Binary64Field.getInstance()).pow(Double.NEGATIVE_INFINITY));
1323        UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), FieldComplex.getOne(Binary64Field.getInstance()).pow(new Binary64(Double.NEGATIVE_INFINITY)));
1324        UnitTestUtils.customAssertSame(FieldComplex.getInf(Binary64Field.getInstance()), infOne.pow(1.0));
1325        UnitTestUtils.customAssertSame(FieldComplex.getInf(Binary64Field.getInstance()), infOne.pow(new Binary64(1.0)));
1326        UnitTestUtils.customAssertSame(FieldComplex.getInf(Binary64Field.getInstance()), negInfOne.pow(1.0));
1327        UnitTestUtils.customAssertSame(FieldComplex.getInf(Binary64Field.getInstance()), negInfOne.pow(new Binary64(1.0)));
1328        UnitTestUtils.customAssertSame(FieldComplex.getInf(Binary64Field.getInstance()), infInf.pow(1.0));
1329        UnitTestUtils.customAssertSame(FieldComplex.getInf(Binary64Field.getInstance()), infInf.pow(new Binary64(1.0)));
1330        UnitTestUtils.customAssertSame(FieldComplex.getInf(Binary64Field.getInstance()), infNegInf.pow(1.0));
1331        UnitTestUtils.customAssertSame(FieldComplex.getInf(Binary64Field.getInstance()), infNegInf.pow(new Binary64(1.0)));
1332        UnitTestUtils.customAssertSame(FieldComplex.getInf(Binary64Field.getInstance()), negInfInf.pow(10));
1333        UnitTestUtils.customAssertSame(FieldComplex.getInf(Binary64Field.getInstance()), negInfInf.pow(new Binary64(10)));
1334        UnitTestUtils.customAssertSame(FieldComplex.getInf(Binary64Field.getInstance()), negInfNegInf.pow(1.0));
1335        UnitTestUtils.customAssertSame(FieldComplex.getInf(Binary64Field.getInstance()), negInfNegInf.pow(new Binary64(1.0)));
1336        UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), negInfNegInf.pow(Double.POSITIVE_INFINITY));
1337        UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), negInfNegInf.pow(new Binary64(Double.POSITIVE_INFINITY)));
1338        UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), negInfNegInf.pow(Double.POSITIVE_INFINITY));
1339        UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), negInfNegInf.pow(new Binary64(Double.POSITIVE_INFINITY)));
1340        UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), infInf.pow(Double.POSITIVE_INFINITY));
1341        UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), infInf.pow(new Binary64(Double.POSITIVE_INFINITY)));
1342        UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), infInf.pow(Double.NEGATIVE_INFINITY));
1343        UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), infInf.pow(new Binary64(Double.NEGATIVE_INFINITY)));
1344        UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), infNegInf.pow(Double.NEGATIVE_INFINITY));
1345        UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), infNegInf.pow(new Binary64(Double.NEGATIVE_INFINITY)));
1346        UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), infNegInf.pow(Double.POSITIVE_INFINITY));
1347        UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), infNegInf.pow(new Binary64(Double.POSITIVE_INFINITY)));
1348    }
1349 
1350     @Test
1351     void testScalarPowZero() {
1352        UnitTestUtils.customAssertEquals(FieldComplex.getZero(Binary64Field.getInstance()), FieldComplex.getZero(Binary64Field.getInstance()).pow(1.0), 1.0e-12);
1353        UnitTestUtils.customAssertEquals(FieldComplex.getZero(Binary64Field.getInstance()), FieldComplex.getZero(Binary64Field.getInstance()).pow(new Binary64(1.0)), 1.0e-12);
1354        UnitTestUtils.customAssertSame(FieldComplex.getOne(Binary64Field.getInstance()), FieldComplex.getZero(Binary64Field.getInstance()).pow(0.0));
1355        UnitTestUtils.customAssertSame(FieldComplex.getOne(Binary64Field.getInstance()), FieldComplex.getZero(Binary64Field.getInstance()).pow(new Binary64(0.0)));
1356        UnitTestUtils.customAssertEquals(FieldComplex.getOne(Binary64Field.getInstance()), FieldComplex.getOne(Binary64Field.getInstance()).pow(0.0), 10e-12);
1357        UnitTestUtils.customAssertEquals(FieldComplex.getOne(Binary64Field.getInstance()), FieldComplex.getOne(Binary64Field.getInstance()).pow(new Binary64(0.0)), 10e-12);
1358        UnitTestUtils.customAssertEquals(FieldComplex.getOne(Binary64Field.getInstance()), FieldComplex.getI(Binary64Field.getInstance()).pow(0.0), 10e-12);
1359        UnitTestUtils.customAssertEquals(FieldComplex.getOne(Binary64Field.getInstance()), FieldComplex.getI(Binary64Field.getInstance()).pow(new Binary64(0.0)), 10e-12);
1360        UnitTestUtils.customAssertEquals(FieldComplex.getOne(Binary64Field.getInstance()), build(-1, 3).pow(0.0), 10e-12);
1361        UnitTestUtils.customAssertEquals(FieldComplex.getOne(Binary64Field.getInstance()), build(-1, 3).pow(new Binary64(0.0)), 10e-12);
1362    }
1363 
1364     @Test
1365     void testpowNull() {
1366         assertThrows(NullArgumentException.class, () -> {
1367             FieldComplex.getOne(Binary64Field.getInstance()).pow((FieldComplex<Binary64>) null);
1368         });
1369     }
1370 
1371     @Test
1372     void testSinComplex() {
1373         FieldComplex<Binary64> z = build(3, 4);
1374         FieldComplex<Binary64> expected = build(3.853738, -27.01681);
1375         UnitTestUtils.customAssertEquals(expected, z.sin(), 1.0e-5);
1376     }
1377 
1378     @Test
1379     void testSinInf() {
1380         UnitTestUtils.customAssertSame(infInf, oneInf.sin());
1381         UnitTestUtils.customAssertSame(infNegInf, oneNegInf.sin());
1382         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), infOne.sin());
1383         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), negInfOne.sin());
1384         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), infInf.sin());
1385         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), infNegInf.sin());
1386         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), negInfInf.sin());
1387         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), negInfNegInf.sin());
1388     }
1389 
1390     @Test
1391     void testSinNaN() {
1392         assertTrue(FieldComplex.getNaN(Binary64Field.getInstance()).sin().isNaN());
1393     }
1394 
1395     @Test
1396     void testSinhComplex() {
1397         FieldComplex<Binary64> z = build(3, 4);
1398         FieldComplex<Binary64> expected = build(-6.54812, -7.61923);
1399         UnitTestUtils.customAssertEquals(expected, z.sinh(), 1.0e-5);
1400     }
1401 
1402     @Test
1403     void testSinhNaN() {
1404         assertTrue(FieldComplex.getNaN(Binary64Field.getInstance()).sinh().isNaN());
1405     }
1406 
1407     @Test
1408     void testSinhInf() {
1409         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), oneInf.sinh());
1410         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), oneNegInf.sinh());
1411         UnitTestUtils.customAssertSame(infInf, infOne.sinh());
1412         UnitTestUtils.customAssertSame(negInfInf, negInfOne.sinh());
1413         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), infInf.sinh());
1414         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), infNegInf.sinh());
1415         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), negInfInf.sinh());
1416         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), negInfNegInf.sinh());
1417     }
1418 
1419     @Test
1420     void testAsinhComplex() {
1421         for (double x = -2; x <= 2; x += 0.125) {
1422             for (double y = -2; y <= 2; y += 0.125) {
1423                 final FieldComplex<Binary64> z = build(x, y);
1424                 UnitTestUtils.customAssertEquals(z, z.asinh().sinh(), 1.0e-14);
1425             }
1426         }
1427     }
1428 
1429     @Test
1430     void testAsinhBranchCuts() {
1431         UnitTestUtils.customAssertEquals(build(FastMath.log(2 + FastMath.sqrt(3)), 0.5 * FastMath.PI),
1432                                          build(+0.0, 2.0).asinh(),
1433                                          1.0e-14);
1434         UnitTestUtils.customAssertEquals(build(-FastMath.log(2 + FastMath.sqrt(3)), 0.5 * FastMath.PI),
1435                                          build(-0.0, 2.0).asinh(),
1436                                          1.0e-14);
1437     }
1438 
1439     @Test
1440     void testAcoshComplex() {
1441         for (double x = -2; x <= 2; x += 0.125) {
1442             for (double y = -2; y <= 2; y += 0.125) {
1443                 final FieldComplex<Binary64> z = build(x, y);
1444                 UnitTestUtils.customAssertEquals(z, z.acosh().cosh(), 1.0e-14);
1445             }
1446         }
1447     }
1448 
1449     @Test
1450     void testAcoshBranchCuts() {
1451         UnitTestUtils.customAssertEquals(build(FastMath.log(2 + FastMath.sqrt(3)), +FastMath.PI),
1452                                          build(-2.0, +0.0).acosh(),
1453                                          1.0e-14);
1454         UnitTestUtils.customAssertEquals(build(FastMath.log(2 + FastMath.sqrt(3)), -FastMath.PI),
1455                                          build(-2.0, -0.0).acosh(),
1456                                          1.0e-14);
1457     }
1458 
1459     @Test
1460     void testAtanhComplex() {
1461         for (double x = -2; x <= 2; x += 0.125) {
1462             for (double y = -2; y <= 2; y += 0.125) {
1463                 final FieldComplex<Binary64> z = build(x, y);
1464                 if (FastMath.abs(x) == 1.0 && y == 0.0) {
1465                     assertTrue(z.atanh().isInfinite());
1466                 } else {
1467                     UnitTestUtils.customAssertEquals(z, z.atanh().tanh(), 1.0e-14);
1468                 }
1469             }
1470         }
1471     }
1472 
1473     @Test
1474     void testAtanhBranchCuts() {
1475         UnitTestUtils.customAssertEquals(build(-0.5 * FastMath.log(3), +0.5 * FastMath.PI),
1476                                          build(-2.0, +0.0).atanh(),
1477                                          1.0e-14);
1478         UnitTestUtils.customAssertEquals(build(-0.5 * FastMath.log(3), -0.5 * FastMath.PI),
1479                                          build(-2.0, -0.0).atanh(),
1480                                          1.0e-14);
1481     }
1482 
1483     @Test
1484     void testSqrtRealPositive() {
1485         FieldComplex<Binary64> z = build(3, 4);
1486         FieldComplex<Binary64> expected = build(2, 1);
1487         UnitTestUtils.customAssertEquals(expected, z.sqrt(), 1.0e-5);
1488     }
1489 
1490     @Test
1491     void testSqrtRealZero() {
1492         FieldComplex<Binary64> z = build(0.0, 4);
1493         FieldComplex<Binary64> expected = build(1.41421, 1.41421);
1494         UnitTestUtils.customAssertEquals(expected, z.sqrt(), 1.0e-5);
1495     }
1496 
1497     @Test
1498     void testSqrtZero() {
1499         UnitTestUtils.customAssertEquals(FieldComplex.getZero(Binary64Field.getInstance()), FieldComplex.getZero(Binary64Field.getInstance()).sqrt(), 1.0e-15);
1500     }
1501 
1502     @Test
1503     void testSqrtRealNegative() {
1504         FieldComplex<Binary64> z = build(-3.0, 4);
1505         FieldComplex<Binary64> expected = build(1, 2);
1506         UnitTestUtils.customAssertEquals(expected, z.sqrt(), 1.0e-5);
1507     }
1508 
1509     @Test
1510     void testSqrtImaginaryZero() {
1511         FieldComplex<Binary64> z = build(-3.0, 0.0);
1512         FieldComplex<Binary64> expected = build(0.0, 1.73205);
1513         UnitTestUtils.customAssertEquals(expected, z.sqrt(), 1.0e-5);
1514     }
1515 
1516     @Test
1517     void testSqrtImaginaryNegative() {
1518         FieldComplex<Binary64> z = build(-3.0, -4.0);
1519         FieldComplex<Binary64> expected = build(1.0, -2.0);
1520         UnitTestUtils.customAssertEquals(expected, z.sqrt(), 1.0e-5);
1521     }
1522 
1523     @Test
1524     void testSqrtPolar() {
1525         Binary64 r = Binary64.ONE;
1526         for (int i = 0; i < 5; i++) {
1527             r = r.add(i);
1528             Binary64 theta = Binary64.ZERO;
1529             for (int j =0; j < 11; j++) {
1530                 theta = theta.add(FastMath.PI / 12);
1531                 FieldComplex<Binary64> z = ComplexUtils.polar2Complex(r, theta);
1532                 FieldComplex<Binary64> sqrtz = ComplexUtils.polar2Complex(FastMath.sqrt(r), theta.divide(2));
1533                 UnitTestUtils.customAssertEquals(sqrtz, z.sqrt(), 10e-12);
1534             }
1535         }
1536     }
1537 
1538     @Test
1539     void testSqrtNaN() {
1540         assertTrue(FieldComplex.getNaN(Binary64Field.getInstance()).sqrt().isNaN());
1541     }
1542 
1543     @Test
1544     void testSqrtInf() {
1545         UnitTestUtils.customAssertSame(infNaN, oneInf.sqrt());
1546         UnitTestUtils.customAssertSame(infNaN, oneNegInf.sqrt());
1547         UnitTestUtils.customAssertSame(infZero, infOne.sqrt());
1548         UnitTestUtils.customAssertSame(zeroInf, negInfOne.sqrt());
1549         UnitTestUtils.customAssertSame(infNaN, infInf.sqrt());
1550         UnitTestUtils.customAssertSame(infNaN, infNegInf.sqrt());
1551         UnitTestUtils.customAssertSame(nanInf, negInfInf.sqrt());
1552         UnitTestUtils.customAssertSame(nanNegInf, negInfNegInf.sqrt());
1553     }
1554 
1555     @Test
1556     void testSqrt1z() {
1557         FieldComplex<Binary64> z = build(3, 4);
1558         FieldComplex<Binary64> expected = build(4.08033, -2.94094);
1559         UnitTestUtils.customAssertEquals(expected, z.sqrt1z(), 1.0e-5);
1560     }
1561 
1562     @Test
1563     void testSqrt1zNaN() {
1564         assertTrue(FieldComplex.getNaN(Binary64Field.getInstance()).sqrt1z().isNaN());
1565     }
1566 
1567     @Test
1568     @Override
1569     public void testCbrt() {
1570         for (double x = -0.9; x < 0.9; x += 0.05) {
1571             if ( x < 0) {
1572                 // special case for Complex
1573                 assertTrue(FastMath.cbrt(x) < 0);
1574                 assertEquals(FastMath.PI / 3, build(x).cbrt().getArgument().getReal(), 1.0e-15);
1575             } else {
1576                 checkRelative(FastMath.cbrt(x), build(x).cbrt());
1577             }
1578         }
1579     }
1580 
1581     @Test
1582     void testCbrtComplex() {
1583         FieldComplex<Binary64> z = build(15, 2);
1584         UnitTestUtils.customAssertEquals(z, z.square().multiply(z).cbrt(), 1.0e-14);
1585         FieldComplex<Binary64> branchCutPlus = build(-8.0, +0.0);
1586         FieldComplex<Binary64> cbrtPlus = branchCutPlus.cbrt();
1587         UnitTestUtils.customAssertEquals(branchCutPlus, cbrtPlus.multiply(cbrtPlus).multiply(cbrtPlus), 1.0e-14);
1588         assertEquals(1.0, cbrtPlus.getRealPart().getReal(), 1.0e-15);
1589         assertEquals(FastMath.sqrt(3.0), cbrtPlus.getImaginaryPart().getReal(), 1.0e-15);
1590         FieldComplex<Binary64> branchCutMinus = build(-8.0, -0.0);
1591         FieldComplex<Binary64> cbrtMinus = branchCutMinus.cbrt();
1592         UnitTestUtils.customAssertEquals(branchCutMinus, cbrtMinus.multiply(cbrtMinus).multiply(cbrtMinus), 1.0e-14);
1593         assertEquals(1.0, cbrtMinus.getRealPart().getReal(), 1.0e-15);
1594         assertEquals(-FastMath.sqrt(3.0), cbrtMinus.getImaginaryPart().getReal(), 1.0e-15);
1595     }
1596 
1597     @Test
1598     @Override
1599     public void testRootN() {
1600         for (double x = -0.9; x < 0.9; x += 0.05) {
1601             for (int n = 1; n < 5; ++n) {
1602                 if (x < 0) {
1603                     // special case for Complex
1604                     final double doubleRoot = new Binary64(x).rootN(n).getReal();
1605                     if (n % 2 == 0) {
1606                         assertTrue(Double.isNaN(doubleRoot));
1607                     } else {
1608                         assertTrue(doubleRoot < 0);
1609                     }
1610                     assertEquals(FastMath.PI / n, build(x).rootN(n).getArgument().getReal(), 1.0e-15);
1611                 } else {
1612                     checkRelative(FastMath.pow(x, 1.0 / n), build(x).rootN(n));
1613                 }
1614             }
1615         }
1616     }
1617 
1618     @Test
1619     void testRootNComplex() {
1620         FieldComplex<Binary64> z = build(15, 2);
1621         UnitTestUtils.customAssertEquals(z, z.square().multiply(z).rootN(3), 1.0e-14);
1622         FieldComplex<Binary64> branchCutPlus = build(-8.0, +0.0);
1623         FieldComplex<Binary64> cbrtPlus = branchCutPlus.rootN(3);
1624         UnitTestUtils.customAssertEquals(branchCutPlus, cbrtPlus.multiply(cbrtPlus).multiply(cbrtPlus), 1.0e-14);
1625         assertEquals(1.0, cbrtPlus.getRealPart().getReal(), 1.0e-15);
1626         assertEquals(FastMath.sqrt(3.0), cbrtPlus.getImaginaryPart().getReal(), 1.0e-15);
1627         FieldComplex<Binary64> branchCutMinus = build(-8.0, -0.0);
1628         FieldComplex<Binary64> cbrtMinus = branchCutMinus.rootN(3);
1629         UnitTestUtils.customAssertEquals(branchCutMinus, cbrtMinus.multiply(cbrtMinus).multiply(cbrtMinus), 1.0e-14);
1630         assertEquals(1.0, cbrtMinus.getRealPart().getReal(), 1.0e-15);
1631         assertEquals(-FastMath.sqrt(3.0), cbrtMinus.getImaginaryPart().getReal(), 1.0e-15);
1632     }
1633 
1634     @Test
1635     void testTanComplex() {
1636         FieldComplex<Binary64> z = build(3, 4);
1637         FieldComplex<Binary64> expected = build(-0.000187346, 0.999356);
1638         UnitTestUtils.customAssertEquals(expected, z.tan(), 1.0e-5);
1639         /* Check that no overflow occurs (MATH-722) */
1640         FieldComplex<Binary64> actual = build(3.0, 1E10).tan();
1641         expected = build(0, 1);
1642         UnitTestUtils.customAssertEquals(expected, actual, 1.0e-5);
1643         actual = build(3.0, -1E10).tan();
1644         expected = build(0, -1);
1645         UnitTestUtils.customAssertEquals(expected, actual, 1.0e-5);
1646     }
1647 
1648     @Test
1649     void testTanNaN() {
1650         assertTrue(FieldComplex.getNaN(Binary64Field.getInstance()).tan().isNaN());
1651     }
1652 
1653     @Test
1654     void testTanInf() {
1655         UnitTestUtils.customAssertSame(FieldComplex.valueOf(new Binary64(0.0), new Binary64(1.0)), oneInf.tan());
1656         UnitTestUtils.customAssertSame(FieldComplex.valueOf(new Binary64(0.0), new Binary64(-1.0)), oneNegInf.tan());
1657         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), infOne.tan());
1658         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), negInfOne.tan());
1659         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), infInf.tan());
1660         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), infNegInf.tan());
1661         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), negInfInf.tan());
1662         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), negInfNegInf.tan());
1663     }
1664 
1665     @Test
1666     void testTanCritical() {
1667         UnitTestUtils.customAssertSame(infNaN, build(MathUtils.SEMI_PI, 0).tan());
1668         UnitTestUtils.customAssertSame(negInfNaN, build(-MathUtils.SEMI_PI, 0).tan());
1669     }
1670 
1671     @Test
1672     void testTanhComplex() {
1673         FieldComplex<Binary64> z = build(3, 4);
1674         FieldComplex<Binary64> expected = build(1.00071, 0.00490826);
1675         UnitTestUtils.customAssertEquals(expected, z.tanh(), 1.0e-5);
1676         /* Check that no overflow occurs (MATH-722) */
1677         FieldComplex<Binary64> actual = build(1E10, 3.0).tanh();
1678         expected = build(1, 0);
1679         UnitTestUtils.customAssertEquals(expected, actual, 1.0e-5);
1680         actual = build(-1E10, 3.0).tanh();
1681         expected = build(-1, 0);
1682         UnitTestUtils.customAssertEquals(expected, actual, 1.0e-5);
1683     }
1684 
1685     @Test
1686     void testTanhNaN() {
1687         assertTrue(FieldComplex.getNaN(Binary64Field.getInstance()).tanh().isNaN());
1688     }
1689 
1690     @Test
1691     void testTanhInf() {
1692         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), oneInf.tanh());
1693         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), oneNegInf.tanh());
1694         UnitTestUtils.customAssertSame(FieldComplex.valueOf(new Binary64(1.0), new Binary64(0.0)), infOne.tanh());
1695         UnitTestUtils.customAssertSame(FieldComplex.valueOf(new Binary64(-1.0), new Binary64(0.0)), negInfOne.tanh());
1696         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), infInf.tanh());
1697         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), infNegInf.tanh());
1698         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), negInfInf.tanh());
1699         UnitTestUtils.customAssertSame(FieldComplex.getNaN(Binary64Field.getInstance()), negInfNegInf.tanh());
1700     }
1701 
1702     @Test
1703     void testTanhCritical() {
1704         UnitTestUtils.customAssertSame(nanInf, build(0, MathUtils.SEMI_PI).tanh());
1705     }
1706 
1707     /** test issue MATH-221 */
1708     @Test
1709     void testMath221() {
1710         assertTrue(FieldComplex.equals(build(0,-1), build(0,1).multiply(build(-1,0))));
1711     }
1712 
1713     /**
1714      * Test: computing <b>third roots</b> of z.
1715      * <pre>
1716      * <code>
1717      * <b>z = -2 + 2 * i</b>
1718      *   ⇒ z_0 =  1      +          i
1719      *   ⇒ z_1 = -1.3660 + 0.3660 * i
1720      *   ⇒ z_2 =  0.3660 - 1.3660 * i
1721      * </code>
1722      * </pre>
1723      */
1724     @Test
1725     void testNthRoot_normal_thirdRoot() {
1726         // The complex number we want to compute all third-roots for.
1727         FieldComplex<Binary64> z = build(-2,2);
1728         // The List holding all third roots
1729         List<FieldComplex<Binary64>> thirdRootsOfZ = z.nthRoot(3);
1730         // Returned Collection must not be empty!
1731         assertEquals(3, thirdRootsOfZ.size());
1732         // test z_0
1733         assertEquals(1.0,                  thirdRootsOfZ.get(0).getRealPart().getReal(),      1.0e-5);
1734         assertEquals(1.0,                  thirdRootsOfZ.get(0).getImaginaryPart().getReal(), 1.0e-5);
1735         // test z_1
1736         assertEquals(-1.3660254037844386,  thirdRootsOfZ.get(1).getRealPart().getReal(),      1.0e-5);
1737         assertEquals(0.36602540378443843,  thirdRootsOfZ.get(1).getImaginaryPart().getReal(), 1.0e-5);
1738         // test z_2
1739         assertEquals(0.366025403784439,    thirdRootsOfZ.get(2).getRealPart().getReal(),      1.0e-5);
1740         assertEquals(-1.3660254037844384,  thirdRootsOfZ.get(2).getImaginaryPart().getReal(), 1.0e-5);
1741     }
1742 
1743 
1744     /**
1745      * Test: computing <b>fourth roots</b> of z.
1746      * <pre>
1747      * <code>
1748      * <b>z = 5 - 2 * i</b>
1749      *   ⇒ z_0 =  1.5164 - 0.1446 * i
1750      *   ⇒ z_1 =  0.1446 + 1.5164 * i
1751      *   ⇒ z_2 = -1.5164 + 0.1446 * i
1752      *   ⇒ z_3 = -1.5164 - 0.1446 * i
1753      * </code>
1754      * </pre>
1755      */
1756     @Test
1757     void testNthRoot_normal_fourthRoot() {
1758         // The complex number we want to compute all third-roots for.
1759         FieldComplex<Binary64> z = build(5,-2);
1760         // The List holding all fourth roots
1761         List<FieldComplex<Binary64>> fourthRootsOfZ = z.nthRoot(4);
1762         // Returned Collection must not be empty!
1763         assertEquals(4, fourthRootsOfZ.size());
1764         // test z_0
1765         assertEquals(1.5164629308487783,     fourthRootsOfZ.get(0).getRealPart().getReal(),      1.0e-5);
1766         assertEquals(-0.14469266210702247,   fourthRootsOfZ.get(0).getImaginaryPart().getReal(), 1.0e-5);
1767         // test z_1
1768         assertEquals(0.14469266210702256,    fourthRootsOfZ.get(1).getRealPart().getReal(),      1.0e-5);
1769         assertEquals(1.5164629308487783,     fourthRootsOfZ.get(1).getImaginaryPart().getReal(), 1.0e-5);
1770         // test z_2
1771         assertEquals(-1.5164629308487783,    fourthRootsOfZ.get(2).getRealPart().getReal(),      1.0e-5);
1772         assertEquals(0.14469266210702267,    fourthRootsOfZ.get(2).getImaginaryPart().getReal(), 1.0e-5);
1773         // test z_3
1774         assertEquals(-0.14469266210702275,   fourthRootsOfZ.get(3).getRealPart().getReal(),      1.0e-5);
1775         assertEquals(-1.5164629308487783,    fourthRootsOfZ.get(3).getImaginaryPart().getReal(), 1.0e-5);
1776     }
1777 
1778     /**
1779      * Test: computing <b>third roots</b> of z.
1780      * <pre>
1781      * <code>
1782      * <b>z = 8</b>
1783      *   ⇒ z_0 =  2
1784      *   ⇒ z_1 = -1 + 1.73205 * i
1785      *   ⇒ z_2 = -1 - 1.73205 * i
1786      * </code>
1787      * </pre>
1788      */
1789     @Test
1790     void testNthRoot_cornercase_thirdRoot_imaginaryPartEmpty() {
1791         // The number 8 has three third roots. One we all already know is the number 2.
1792         // But there are two more complex roots.
1793         FieldComplex<Binary64> z = build(8,0);
1794         // The List holding all third roots
1795         List<FieldComplex<Binary64>> thirdRootsOfZ = z.nthRoot(3);
1796         // Returned Collection must not be empty!
1797         assertEquals(3, thirdRootsOfZ.size());
1798         // test z_0
1799         assertEquals(2.0,                thirdRootsOfZ.get(0).getRealPart().getReal(),      1.0e-5);
1800         assertEquals(0.0,                thirdRootsOfZ.get(0).getImaginaryPart().getReal(), 1.0e-5);
1801         // test z_1
1802         assertEquals(-1.0,               thirdRootsOfZ.get(1).getRealPart().getReal(),      1.0e-5);
1803         assertEquals(1.7320508075688774, thirdRootsOfZ.get(1).getImaginaryPart().getReal(), 1.0e-5);
1804         // test z_2
1805         assertEquals(-1.0,               thirdRootsOfZ.get(2).getRealPart().getReal(),      1.0e-5);
1806         assertEquals(-1.732050807568877, thirdRootsOfZ.get(2).getImaginaryPart().getReal(), 1.0e-5);
1807     }
1808 
1809     /**
1810      * Test: computing <b>third roots</b> of z with real part 0.
1811      * <pre>
1812      * <code>
1813      * <b>z = 2 * i</b>
1814      *   ⇒ z_0 =  1.0911 + 0.6299 * i
1815      *   ⇒ z_1 = -1.0911 + 0.6299 * i
1816      *   ⇒ z_2 = -2.3144 - 1.2599 * i
1817      * </code>
1818      * </pre>
1819      */
1820     @Test
1821     void testNthRoot_cornercase_thirdRoot_realPartZero() {
1822         // complex number with only imaginary part
1823         FieldComplex<Binary64> z = build(0,2);
1824         // The List holding all third roots
1825         List<FieldComplex<Binary64>> thirdRootsOfZ = z.nthRoot(3);
1826         // Returned Collection must not be empty!
1827         assertEquals(3, thirdRootsOfZ.size());
1828         // test z_0
1829         assertEquals(1.0911236359717216,      thirdRootsOfZ.get(0).getRealPart().getReal(),      1.0e-5);
1830         assertEquals(0.6299605249474365,      thirdRootsOfZ.get(0).getImaginaryPart().getReal(), 1.0e-5);
1831         // test z_1
1832         assertEquals(-1.0911236359717216,     thirdRootsOfZ.get(1).getRealPart().getReal(),      1.0e-5);
1833         assertEquals(0.6299605249474365,      thirdRootsOfZ.get(1).getImaginaryPart().getReal(), 1.0e-5);
1834         // test z_2
1835         assertEquals(-2.3144374213981936E-16, thirdRootsOfZ.get(2).getRealPart().getReal(),      1.0e-5);
1836         assertEquals(-1.2599210498948732,     thirdRootsOfZ.get(2).getImaginaryPart().getReal(), 1.0e-5);
1837     }
1838 
1839     /**
1840      * Test cornercases with NaN and Infinity.
1841      */
1842     @Test
1843     void testNthRoot_cornercase_NAN_Inf() {
1844         // NaN + finite -> NaN
1845         List<FieldComplex<Binary64>> roots = oneNaN.nthRoot(3);
1846         assertEquals(1,roots.size());
1847         assertEquals(FieldComplex.getNaN(Binary64Field.getInstance()), roots.get(0));
1848 
1849         roots = nanZero.nthRoot(3);
1850         assertEquals(1,roots.size());
1851         assertEquals(FieldComplex.getNaN(Binary64Field.getInstance()), roots.get(0));
1852 
1853         // NaN + infinite -> NaN
1854         roots = nanInf.nthRoot(3);
1855         assertEquals(1,roots.size());
1856         assertEquals(FieldComplex.getNaN(Binary64Field.getInstance()), roots.get(0));
1857 
1858         // finite + infinite -> Inf
1859         roots = oneInf.nthRoot(3);
1860         assertEquals(1,roots.size());
1861         assertEquals(FieldComplex.getInf(Binary64Field.getInstance()), roots.get(0));
1862 
1863         // infinite + infinite -> Inf
1864         roots = negInfInf.nthRoot(3);
1865         assertEquals(1,roots.size());
1866         assertEquals(FieldComplex.getInf(Binary64Field.getInstance()), roots.get(0));
1867     }
1868 
1869     @Test
1870     void testNthRootError() {
1871         try {
1872             FieldComplex.getOne(Binary64Field.getInstance()).nthRoot(-1);
1873             fail("an exception should have been thrown");
1874         } catch (MathIllegalArgumentException miae) {
1875             assertEquals(LocalizedCoreFormats.CANNOT_COMPUTE_NTH_ROOT_FOR_NEGATIVE_N,
1876                                 miae.getSpecifier());
1877         }
1878     }
1879 
1880     @Test
1881     void testIsMathematicalInteger() {
1882         doTestIsMathmeaticalInteger(-0.0, true);
1883         doTestIsMathmeaticalInteger(+0.0, true);
1884         doTestIsMathmeaticalInteger(-0.5, false);
1885         doTestIsMathmeaticalInteger(+0.5, false);
1886         doTestIsMathmeaticalInteger(Double.NaN, false);
1887         doTestIsMathmeaticalInteger(Double.POSITIVE_INFINITY, false);
1888         doTestIsMathmeaticalInteger(Double.NEGATIVE_INFINITY, false);
1889         doTestIsMathmeaticalInteger(Double.MIN_NORMAL, false);
1890         doTestIsMathmeaticalInteger(Double.MIN_VALUE, false);
1891     }
1892 
1893     private void doTestIsMathmeaticalInteger(double imaginary, boolean expectedForInteger) {
1894         assertFalse(build(Double.NaN, imaginary).isMathematicalInteger());
1895         assertFalse(build(Double.POSITIVE_INFINITY, imaginary).isMathematicalInteger());
1896         assertFalse(build(Double.NEGATIVE_INFINITY, imaginary).isMathematicalInteger());
1897         assertFalse(build(Double.MIN_NORMAL, imaginary).isMathematicalInteger());
1898         assertFalse(build(Double.MIN_VALUE, imaginary).isMathematicalInteger());
1899 
1900         assertEquals(expectedForInteger, build(-0.0, imaginary).isMathematicalInteger());
1901         assertEquals(expectedForInteger, build(+0.0, imaginary).isMathematicalInteger());
1902 
1903         for (int i = -1000; i < 1000; ++i) {
1904             final double d = i;
1905             assertEquals(expectedForInteger, build(d, imaginary).isMathematicalInteger());
1906             assertFalse(build(FastMath.nextAfter(d, Double.POSITIVE_INFINITY), imaginary).isMathematicalInteger());
1907             assertFalse(build(FastMath.nextAfter(d, Double.NEGATIVE_INFINITY), imaginary).isMathematicalInteger());
1908         }
1909 
1910         double minNoFractional = 0x1l << 52;
1911         assertEquals(expectedForInteger, build(minNoFractional, imaginary).isMathematicalInteger());
1912         assertFalse(build(minNoFractional - 0.5, imaginary).isMathematicalInteger());
1913         assertEquals(expectedForInteger, build(minNoFractional + 0.5, imaginary).isMathematicalInteger());
1914 
1915     }
1916 
1917     /**
1918      * Test standard values
1919      */
1920     @Test
1921     void testGetArgument() {
1922         FieldComplex<Binary64> z = build(1, 0);
1923         assertEquals(0.0, z.getArgument().getReal(), 1.0e-12);
1924 
1925         z = build(1, 1);
1926         assertEquals(FastMath.PI/4, z.getArgument().getReal(), 1.0e-12);
1927 
1928         z = build(0, 1);
1929         assertEquals(FastMath.PI/2, z.getArgument().getReal(), 1.0e-12);
1930 
1931         z = build(-1, 1);
1932         assertEquals(3 * FastMath.PI/4, z.getArgument().getReal(), 1.0e-12);
1933 
1934         z = build(-1, 0);
1935         assertEquals(FastMath.PI, z.getArgument().getReal(), 1.0e-12);
1936 
1937         z = build(-1, -1);
1938         assertEquals(-3 * FastMath.PI/4, z.getArgument().getReal(), 1.0e-12);
1939 
1940         z = build(0, -1);
1941         assertEquals(-FastMath.PI/2, z.getArgument().getReal(), 1.0e-12);
1942 
1943         z = build(1, -1);
1944         assertEquals(-FastMath.PI/4, z.getArgument().getReal(), 1.0e-12);
1945 
1946     }
1947 
1948     /**
1949      * Verify atan2-style handling of infinite parts
1950      */
1951     @Test
1952     void testGetArgumentInf() {
1953         assertEquals(FastMath.PI/4, infInf.getArgument().getReal(), 1.0e-12);
1954         assertEquals(FastMath.PI/2, oneInf.getArgument().getReal(), 1.0e-12);
1955         assertEquals(0.0, infOne.getArgument().getReal(), 1.0e-12);
1956         assertEquals(FastMath.PI/2, zeroInf.getArgument().getReal(), 1.0e-12);
1957         assertEquals(0.0, infZero.getArgument().getReal(), 1.0e-12);
1958         assertEquals(FastMath.PI, negInfOne.getArgument().getReal(), 1.0e-12);
1959         assertEquals(-3.0*FastMath.PI/4, negInfNegInf.getArgument().getReal(), 1.0e-12);
1960         assertEquals(-FastMath.PI/2, oneNegInf.getArgument().getReal(), 1.0e-12);
1961     }
1962 
1963     /**
1964      * Verify that either part NaN results in NaN
1965      */
1966     @Test
1967     void testGetArgumentNaN() {
1968         assertTrue(Double.isNaN(nanZero.getArgument().getReal()));
1969         assertTrue(Double.isNaN(zeroNaN.getArgument().getReal()));
1970         assertTrue(Double.isNaN(FieldComplex.getNaN(Binary64Field.getInstance()).getArgument().getReal()));
1971     }
1972 
1973     @Test
1974     void testValueOf() {
1975         assertEquals(2.0, FieldComplex.valueOf(new Binary64(2.0)).getRealPart().getReal(), 1.0e-15);
1976         assertEquals(0.0, FieldComplex.valueOf(new Binary64(2.0)).getImaginaryPart().getReal(), 1.0e-15);
1977         assertTrue(FieldComplex.valueOf(new Binary64(Double.NaN)).isNaN());
1978         assertTrue(FieldComplex.valueOf(new Binary64(Double.POSITIVE_INFINITY)).isInfinite());
1979         assertEquals( 2.0, FieldComplex.valueOf(new Binary64(2.0), new Binary64(-1.0)).getRealPart().getReal(), 1.0e-15);
1980         assertEquals(-1.0, FieldComplex.valueOf(new Binary64(2.0), new Binary64(-1.0)).getImaginaryPart().getReal(), 1.0e-15);
1981         assertTrue(FieldComplex.valueOf(new Binary64(Double.NaN), new Binary64(0.0)).isNaN());
1982         assertTrue(FieldComplex.valueOf(new Binary64(Double.POSITIVE_INFINITY), new Binary64(0.0)).isInfinite());
1983         assertTrue(FieldComplex.valueOf(new Binary64(Double.NaN), new Binary64(-1.0)).isNaN());
1984         assertTrue(FieldComplex.valueOf(new Binary64(Double.POSITIVE_INFINITY), new Binary64(-1.0)).isInfinite());
1985         assertTrue(FieldComplex.valueOf(new Binary64(0.0), new Binary64(Double.NaN)).isNaN());
1986         assertTrue(FieldComplex.valueOf(new Binary64(0.0), new Binary64(Double.POSITIVE_INFINITY)).isInfinite());
1987         assertTrue(FieldComplex.valueOf(new Binary64(-1.0), new Binary64(Double.NaN)).isNaN());
1988         assertTrue(FieldComplex.valueOf(new Binary64(-1.0), new Binary64(Double.POSITIVE_INFINITY)).isInfinite());
1989     }
1990 
1991     @Test
1992     void testField() {
1993         assertEquals(FieldComplexField.getField(Binary64Field.getInstance()),
1994                             FieldComplex.getZero(Binary64Field.getInstance()).getField());
1995     }
1996 
1997     @Test
1998     void testToString() {
1999         assertEquals("(1.0, -2.0)", build(1, -2).toString());
2000     }
2001 
2002     @Test
2003     void testScalbComplex() {
2004         assertEquals(0.125,  build(2.0, 1.0).scalb(-4).getRealPart().getReal(), 1.0e-15);
2005         assertEquals(0.0625, build(2.0, 1.0).scalb(-4).getImaginaryPart().getReal(), 1.0e-15);
2006     }
2007 
2008     @Test
2009     void testHypotComplex() {
2010         assertEquals(5.8269600298808519855, build(3, 4).hypot(build(5, 6)).getRealPart().getReal(), 1.0e-15);
2011         assertEquals(7.2078750814528590485, build(3, 4).hypot(build(5, 6)).getImaginaryPart().getReal(), 1.0e-15);
2012     }
2013 
2014     @Test
2015     void testCeilComplex() {
2016         for (double x = -3.9; x < 3.9; x += 0.05) {
2017             for (double y = -3.9; y < 3.9; y += 0.05) {
2018                 final FieldComplex<Binary64> z = build(x, y);
2019                 assertEquals(FastMath.ceil(x), z.ceil().getRealPart().getReal(), 1.0e-15);
2020                 assertEquals(FastMath.ceil(y), z.ceil().getImaginaryPart().getReal(), 1.0e-15);
2021             }
2022         }
2023     }
2024 
2025     @Test
2026     void testFloorComplex() {
2027         for (double x = -3.9; x < 3.9; x += 0.05) {
2028             for (double y = -3.9; y < 3.9; y += 0.05) {
2029                 final FieldComplex<Binary64> z = build(x, y);
2030                 assertEquals(FastMath.floor(x), z.floor().getRealPart().getReal(), 1.0e-15);
2031                 assertEquals(FastMath.floor(y), z.floor().getImaginaryPart().getReal(), 1.0e-15);
2032             }
2033         }
2034     }
2035 
2036     @Test
2037     void testRintComplex() {
2038         for (double x = -3.9; x < 3.9; x += 0.05) {
2039             for (double y = -3.9; y < 3.9; y += 0.05) {
2040                 final FieldComplex<Binary64> z = build(x, y);
2041                 assertEquals(FastMath.rint(x), z.rint().getRealPart().getReal(), 1.0e-15);
2042                 assertEquals(FastMath.rint(y), z.rint().getImaginaryPart().getReal(), 1.0e-15);
2043             }
2044         }
2045     }
2046 
2047     @Test
2048     void testRemainderComplexComplex() {
2049         for (double x1 = -3.9; x1 < 3.9; x1 += 0.125) {
2050             for (double y1 = -3.9; y1 < 3.9; y1 += 0.125) {
2051                 final FieldComplex<Binary64> z1 = build(x1, y1);
2052                 for (double x2 = -3.92; x2 < 3.9; x2 += 0.125) {
2053                     for (double y2 = -3.92; y2 < 3.9; y2 += 0.125) {
2054                         final FieldComplex<Binary64> z2 = build(x2, y2);
2055                         final FieldComplex<Binary64> r  = z1.remainder(z2);
2056                         final FieldComplex<Binary64> q  = z1.subtract(r).divide(z2);
2057                         assertTrue(r.norm() <= z2.norm());
2058                         assertEquals(FastMath.rint(q.getRealPart().getReal()), q.getRealPart().getReal(), 2.0e-14);
2059                         assertEquals(FastMath.rint(q.getImaginaryPart().getReal()), q.getImaginaryPart().getReal(), 2.0e-14);
2060                     }
2061                 }
2062             }
2063         }
2064     }
2065 
2066     @Test
2067     void testRemainderComplexDouble() {
2068         for (double x1 = -3.9; x1 < 3.9; x1 += 0.125) {
2069             for (double y1 = -3.9; y1 < 3.9; y1 += 0.125) {
2070                 final FieldComplex<Binary64> z1 = build(x1, y1);
2071                 for (double a = -3.92; a < 3.9; a += 0.125) {
2072                         final FieldComplex<Binary64> r  = z1.remainder(a);
2073                         final FieldComplex<Binary64> q  = z1.subtract(r).divide(a);
2074                         assertTrue(r.norm() <= FastMath.abs(a));
2075                         assertEquals(FastMath.rint(q.getRealPart().getReal()), q.getRealPart().getReal(), 2.0e-14);
2076                         assertEquals(FastMath.rint(q.getImaginaryPart().getReal()), q.getImaginaryPart().getReal(), 2.0e-14);
2077                 }
2078             }
2079         }
2080     }
2081 
2082     @Test
2083     void testRemainderAxKr() {
2084         checkRemainder(build(14, -5), build(3, 4), build(-1.0,  0.0));
2085         checkRemainder(build(26, 120), build(37, 226), build(-11.0, -106.0));
2086         checkRemainder(build(9.4, 6), build(1.0, 1.0), build(-0.6, 0.0));
2087         checkRemainder(build(-5.89, 0.33), build(2.4, -0.123), build(-1.09, 0.084));
2088     }
2089 
2090     private void checkRemainder(final FieldComplex<Binary64> c1, final FieldComplex<Binary64> c2, final FieldComplex<Binary64> expectedRemainder) {
2091 
2092         final FieldComplex<Binary64> remainder = c1.remainder(c2);
2093         assertEquals(expectedRemainder.getRealPart().getReal(),      remainder.getRealPart().getReal(),      1.0e-15);
2094         assertEquals(expectedRemainder.getImaginaryPart().getReal(), remainder.getImaginaryPart().getReal(), 1.0e-15);
2095 
2096         final FieldComplex<Binary64> crossCheck = c1.subtract(remainder).divide(c2);
2097         assertTrue(Precision.isMathematicalInteger(crossCheck.getRealPart().getReal()));
2098         assertTrue(Precision.isMathematicalInteger(crossCheck.getImaginaryPart().getReal()));
2099 
2100     }
2101 
2102     @Test
2103     void testCopySignFieldComplex() {
2104         for (double x1 = -3.9; x1 < 3.9; x1 += 0.08) {
2105             for (double y1 = -3.9; y1 < 3.9; y1 += 0.08) {
2106                 final FieldComplex<Binary64> z1 = build(x1, y1);
2107                 for (double x2 = -3.9; x2 < 3.9; x2 += 0.08) {
2108                     for (double y2 = -3.9; y2 < 3.9; y2 += 0.08) {
2109                         final FieldComplex<Binary64> z2 = build(x2, y2);
2110                         assertEquals(FastMath.copySign(x1, x2), z1.copySign(z2).getRealPart().getReal(), 1.0e-15);
2111                         assertEquals(FastMath.copySign(y1, y2), z1.copySign(z2).getImaginaryPart().getReal(), 1.0e-15);
2112                     }
2113                 }
2114             }
2115         }
2116     }
2117 
2118     @Test
2119     void testCopySignDoubleComplex() {
2120         for (double x1 = -3.9; x1 < 3.9; x1 += 0.05) {
2121             for (double y1 = -3.9; y1 < 3.9; y1 += 0.05) {
2122                 final FieldComplex<Binary64> z1 = build(x1, y1);
2123                 for (double r = -3.9; r < 3.9; r += 0.05) {
2124                     assertEquals(FastMath.copySign(x1, r), z1.copySign(r).getRealPart().getReal(), 1.0e-15);
2125                     assertEquals(FastMath.copySign(y1, r), z1.copySign(r).getImaginaryPart().getReal(), 1.0e-15);
2126                 }
2127             }
2128         }
2129     }
2130 
2131     @Test
2132     void testSignumComplex() {
2133         for (double x = -3.9; x < 3.9; x += 0.05) {
2134             for (double y = -3.9; y < 3.9; y += 0.05) {
2135                 final FieldComplex<Binary64> z = build(x, y);
2136                 assertEquals(1.0, z.sign().norm(), 1.0e-15);
2137                 assertEquals(FastMath.copySign(1, FastMath.signum(x)), FastMath.copySign(Binary64.ONE, z.sign().getRealPart()).getReal(), 1.0e-15);
2138                 assertEquals(FastMath.copySign(1, FastMath.signum(y)), FastMath.copySign(Binary64.ONE, z.sign().getImaginaryPart()).getReal(), 1.0e-15);
2139             }
2140         }
2141         assertTrue(Complex.NaN.sign().isNaN());
2142         for (int sR : Arrays.asList(-1, +1)) {
2143             for (int sI : Arrays.asList(-1, +1)) {
2144                 FieldComplex<Binary64> z = build(FastMath.copySign(0, sR), FastMath.copySign(0, sI));
2145                 assertTrue(z.isZero());
2146                 FieldComplex<Binary64> zSign = z.sign();
2147                 assertTrue(zSign.isZero());
2148                 assertEquals(sR, FastMath.copySign(Binary64.ONE, zSign.getRealPart()).getReal(), 1.0e-15);
2149                 assertEquals(sI, FastMath.copySign(Binary64.ONE, zSign.getImaginaryPart()).getReal(), 1.0e-15);
2150             }
2151         }
2152     }
2153 
2154     @Test
2155     void testLinearCombination1() {
2156         final FieldComplex<Binary64>[] a = MathArrays.buildArray(build(0.0).getField(), 2);
2157         a[0] = build(-1321008684645961.0 / 268435456.0, +5774608829631843.0 / 268435456.0);
2158         a[1] = build(-7645843051051357.0 / 8589934592.0, 0.0);
2159         final FieldComplex<Binary64>[] b = MathArrays.buildArray(build(0.0).getField(), 2);
2160         b[0] = build(-5712344449280879.0 / 2097152.0, -4550117129121957.0 / 2097152.0);
2161         b[1] = build(8846951984510141.0 / 131072.0, 0.0);
2162 
2163         final FieldComplex<Binary64> abSumInline = FieldComplex.getZero(Binary64Field.getInstance()).linearCombination(a[0], b[0],
2164                                                                                                                          a[1], b[1]);
2165         final FieldComplex<Binary64> abSumArray = FieldComplex.getZero(Binary64Field.getInstance()).linearCombination(a, b);
2166 
2167         UnitTestUtils.customAssertEquals(abSumInline, abSumArray, 0);
2168         UnitTestUtils.customAssertEquals(-1.8551294182586248737720779899, abSumInline.getRealPart().getReal(), 1.0e-15);
2169 
2170         final FieldComplex<Binary64> naive = a[0].multiply(b[0]).add(a[1].multiply(b[1]));
2171         assertTrue(naive.subtract(abSumInline).norm() > 1.5);
2172 
2173     }
2174 
2175     @Test
2176     void testSignedZeroEquality() {
2177 
2178         assertFalse(build(-0.0, 1.0).isZero());
2179         assertFalse(build(+0.0, 1.0).isZero());
2180         assertFalse(build( 1.0, -0.0).isZero());
2181         assertFalse(build( 1.0, +0.0).isZero());
2182 
2183         assertTrue(build(-0.0, -0.0).isZero());
2184         assertTrue(build(-0.0, +0.0).isZero());
2185         assertTrue(build(+0.0, -0.0).isZero());
2186         assertTrue(build(+0.0, +0.0).isZero());
2187 
2188         assertNotEquals(build(-0.0, -0.0), FieldComplex.getZero(Binary64Field.getInstance()));
2189         assertNotEquals(build(-0.0, +0.0), FieldComplex.getZero(Binary64Field.getInstance()));
2190         assertNotEquals(build(+0.0, -0.0), FieldComplex.getZero(Binary64Field.getInstance()));
2191         assertEquals(build(+0.0, +0.0), FieldComplex.getZero(Binary64Field.getInstance()));
2192 
2193     }
2194 
2195     /**
2196      * Class to test extending Complex
2197      */
2198     public static class TestComplex extends FieldComplex<Binary64> {
2199 
2200         public TestComplex(Binary64 real, Binary64 imaginary) {
2201             super(real, imaginary);
2202         }
2203 
2204         public TestComplex(FieldComplex<Binary64> other) {
2205             this(other.getRealPart(), other.getImaginaryPart());
2206         }
2207 
2208         @Override
2209         protected TestComplex createComplex(Binary64 real, Binary64 imaginary) {
2210             return new TestComplex(real, imaginary);
2211         }
2212 
2213     }
2214 }