View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements. See the NOTICE file distributed with this
4    * work for additional information regarding copyright ownership. The ASF
5    * licenses this file to You under the Apache License, Version 2.0 (the
6    * "License"); you may not use this file except in compliance with the License.
7    * You may obtain a copy of the License at
8    * https://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
9    * or agreed to in writing, software distributed under the License is
10   * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
11   * KIND, either express or implied. See the License for the specific language
12   * governing permissions and limitations under the License.
13   */
14  package org.hipparchus.util;
15  
16  import org.hipparchus.UnitTestUtils;
17  import org.hipparchus.complex.Complex;
18  import org.hipparchus.exception.MathIllegalArgumentException;
19  import org.hipparchus.exception.MathRuntimeException;
20  import org.hipparchus.exception.NullArgumentException;
21  import org.hipparchus.random.Well1024a;
22  import org.junit.jupiter.api.Test;
23  
24  import java.util.Arrays;
25  
26  import static org.junit.jupiter.api.Assertions.assertArrayEquals;
27  import static org.junit.jupiter.api.Assertions.assertEquals;
28  import static org.junit.jupiter.api.Assertions.assertFalse;
29  import static org.junit.jupiter.api.Assertions.assertNull;
30  import static org.junit.jupiter.api.Assertions.assertSame;
31  import static org.junit.jupiter.api.Assertions.assertThrows;
32  import static org.junit.jupiter.api.Assertions.assertTrue;
33  import static org.junit.jupiter.api.Assertions.fail;
34  
35  /**
36   * Test cases for the {@link MathArrays} class.
37   */
38  public class MathArraysTest {
39  
40      private double[] testArray = {0, 1, 2, 3, 4, 5};
41      private double[] testWeightsArray = {0.3, 0.2, 1.3, 1.1, 1.0, 1.8};
42      private double[] testNegativeWeightsArray = {-0.3, 0.2, -1.3, 1.1, 1.0, 1.8};
43      private double[] nullArray = null;
44      private double[] singletonArray = {0};
45  
46      @Test
47      void testScale() {
48          final double[] test = new double[] { -2.5, -1, 0, 1, 2.5 };
49          final double[] correctTest = test.clone();
50          final double[] correctScaled = new double[]{5.25, 2.1, 0, -2.1, -5.25};
51  
52          final double[] scaled = MathArrays.scale(-2.1, test);
53  
54          // Make sure test has not changed
55          for (int i = 0; i < test.length; i++) {
56              assertEquals(correctTest[i], test[i], 0);
57          }
58  
59          // Test scaled values
60          for (int i = 0; i < scaled.length; i++) {
61              assertEquals(correctScaled[i], scaled[i], 0);
62          }
63      }
64  
65      @Test
66      void testScaleInPlace() {
67          final double[] test = new double[] { -2.5, -1, 0, 1, 2.5 };
68          final double[] correctScaled = new double[]{5.25, 2.1, 0, -2.1, -5.25};
69          MathArrays.scaleInPlace(-2.1, test);
70  
71          // Make sure test has changed
72          for (int i = 0; i < test.length; i++) {
73              assertEquals(correctScaled[i], test[i], 0);
74          }
75      }
76  
77      @Test
78      void testEbeAddPrecondition() {
79          assertThrows(MathIllegalArgumentException.class, () -> {
80              MathArrays.ebeAdd(new double[3], new double[4]);
81          });
82      }
83  
84      @Test
85      void testEbeSubtractPrecondition() {
86          assertThrows(MathIllegalArgumentException.class, () -> {
87              MathArrays.ebeSubtract(new double[3], new double[4]);
88          });
89      }
90  
91      @Test
92      void testEbeMultiplyPrecondition() {
93          assertThrows(MathIllegalArgumentException.class, () -> {
94              MathArrays.ebeMultiply(new double[3], new double[4]);
95          });
96      }
97  
98      @Test
99      void testEbeDividePrecondition() {
100         assertThrows(MathIllegalArgumentException.class, () -> {
101             MathArrays.ebeDivide(new double[3], new double[4]);
102         });
103     }
104 
105     @Test
106     void testEbeAdd() {
107         final double[] a = { 0, 1, 2 };
108         final double[] b = { 3, 5, 7 };
109         final double[] r = MathArrays.ebeAdd(a, b);
110 
111         for (int i = 0; i < a.length; i++) {
112             assertEquals(a[i] + b[i], r[i], 0);
113         }
114     }
115 
116     @Test
117     void testEbeSubtract() {
118         final double[] a = { 0, 1, 2 };
119         final double[] b = { 3, 5, 7 };
120         final double[] r = MathArrays.ebeSubtract(a, b);
121 
122         for (int i = 0; i < a.length; i++) {
123             assertEquals(a[i] - b[i], r[i], 0);
124         }
125     }
126 
127     @Test
128     void testEbeMultiply() {
129         final double[] a = { 0, 1, 2 };
130         final double[] b = { 3, 5, 7 };
131         final double[] r = MathArrays.ebeMultiply(a, b);
132 
133         for (int i = 0; i < a.length; i++) {
134             assertEquals(a[i] * b[i], r[i], 0);
135         }
136     }
137 
138     @Test
139     void testEbeDivide() {
140         final double[] a = { 0, 1, 2 };
141         final double[] b = { 3, 5, 7 };
142         final double[] r = MathArrays.ebeDivide(a, b);
143 
144         for (int i = 0; i < a.length; i++) {
145             assertEquals(a[i] / b[i], r[i], 0);
146         }
147     }
148 
149     @Test
150     void testL1DistanceDouble() {
151         double[] p1 = { 2.5,  0.0 };
152         double[] p2 = { -0.5, 4.0 };
153         assertTrue(Precision.equals(7.0, MathArrays.distance1(p1, p2), 1));
154     }
155 
156     @Test
157     void testL1DistanceInt() {
158         int[] p1 = { 3, 0 };
159         int[] p2 = { 0, 4 };
160         assertEquals(7, MathArrays.distance1(p1, p2));
161     }
162 
163     @Test
164     void testL2DistanceDouble() {
165         double[] p1 = { 2.5,  0.0 };
166         double[] p2 = { -0.5, 4.0 };
167         assertTrue(Precision.equals(5.0, MathArrays.distance(p1, p2), 1));
168     }
169 
170     @Test
171     void testL2DistanceInt() {
172         int[] p1 = { 3, 0 };testArrayEquals();
173         int[] p2 = { 0, 4 };
174         assertTrue(Precision.equals(5, MathArrays.distance(p1, p2), 1));
175     }
176 
177     @Test
178     void testLInfDistanceDouble() {
179         double[] p1 = { 2.5,  0.0 };
180         double[] p2 = { -0.5, 4.0 };
181         assertTrue(Precision.equals(4.0, MathArrays.distanceInf(p1, p2), 1));
182     }
183 
184     @Test
185     void testLInfDistanceInt() {
186         int[] p1 = { 3, 0 };
187         int[] p2 = { 0, 4 };
188         assertEquals(4, MathArrays.distanceInf(p1, p2));
189     }
190 
191     @Test
192     void testCosAngle2D() {
193         double expected;
194 
195         final double[] v1 = { 1, 0 };
196         expected = 1;
197         assertEquals(expected, MathArrays.cosAngle(v1, v1), 0d);
198 
199         final double[] v2 = { 0, 1 };
200         expected = 0;
201         assertEquals(expected, MathArrays.cosAngle(v1, v2), 0d);
202 
203         final double[] v3 = { 7, 7 };
204         expected = Math.sqrt(2) / 2;
205         assertEquals(expected, MathArrays.cosAngle(v1, v3), 1e-15);
206         assertEquals(expected, MathArrays.cosAngle(v3, v2), 1e-15);
207 
208         final double[] v4 = { -5, 0 };
209         expected = -1;
210         assertEquals(expected, MathArrays.cosAngle(v1, v4), 0);
211 
212         final double[] v5 = { -100, 100 };
213         expected = 0;
214         assertEquals(expected, MathArrays.cosAngle(v3, v5), 0);
215     }
216 
217     @Test
218     void testCosAngle3D() {
219         double expected;
220 
221         final double[] v1 = { 1, 1, 0 };
222         expected = 1;
223         assertEquals(expected, MathArrays.cosAngle(v1, v1), 1e-15);
224 
225         final double[] v2 = { 1, 1, 1 };
226         expected = Math.sqrt(2) / Math.sqrt(3);
227         assertEquals(expected, MathArrays.cosAngle(v1, v2), 1e-15);
228     }
229 
230     @Test
231     void testCosAngleExtreme() {
232         double expected;
233 
234         final double tiny = 1e-200;
235         final double[] v1 = { tiny, tiny };
236         final double big = 1e200;
237         final double[] v2 = { -big, -big };
238         expected = -1;
239         assertEquals(expected, MathArrays.cosAngle(v1, v2), 1e-15);
240 
241         final double[] v3 = { big, -big };
242         expected = 0;
243         assertEquals(expected, MathArrays.cosAngle(v1, v3), 1e-15);
244     }
245 
246     @Test
247     void testCheckOrder() {
248         MathArrays.checkOrder(new double[] {-15, -5.5, -1, 2, 15},
249                              MathArrays.OrderDirection.INCREASING, true);
250         MathArrays.checkOrder(new double[] {-15, -5.5, -1, 2, 2},
251                              MathArrays.OrderDirection.INCREASING, false);
252         MathArrays.checkOrder(new double[] {3, -5.5, -11, -27.5},
253                              MathArrays.OrderDirection.DECREASING, true);
254         MathArrays.checkOrder(new double[] {3, 0, 0, -5.5, -11, -27.5},
255                              MathArrays.OrderDirection.DECREASING, false);
256 
257         try {
258             MathArrays.checkOrder(new double[] {-15, -5.5, -1, -1, 2, 15},
259                                  MathArrays.OrderDirection.INCREASING, true);
260             fail("an exception should have been thrown");
261         } catch (MathIllegalArgumentException e) {
262             // Expected
263         }
264         try {
265             MathArrays.checkOrder(new double[] {-15, -5.5, -1, -2, 2},
266                                  MathArrays.OrderDirection.INCREASING, false);
267             fail("an exception should have been thrown");
268         } catch (MathIllegalArgumentException e) {
269             // Expected
270         }
271         try {
272             MathArrays.checkOrder(new double[] {3, 3, -5.5, -11, -27.5},
273                                  MathArrays.OrderDirection.DECREASING, true);
274             fail("an exception should have been thrown");
275         } catch (MathIllegalArgumentException e) {
276             // Expected
277         }
278         try {
279             MathArrays.checkOrder(new double[] {3, -1, 0, -5.5, -11, -27.5},
280                                  MathArrays.OrderDirection.DECREASING, false);
281             fail("an exception should have been thrown");
282         } catch (MathIllegalArgumentException e) {
283             // Expected
284         }
285         try {
286             MathArrays.checkOrder(new double[] {3, 0, -5.5, -11, -10},
287                                  MathArrays.OrderDirection.DECREASING, false);
288             fail("an exception should have been thrown");
289         } catch (MathIllegalArgumentException e) {
290             // Expected
291         }
292     }
293 
294     @Test
295     void testIsMonotonic() {
296         assertFalse(MathArrays.isMonotonic(new double[] { -15, -5.5, -1, -1, 2, 15 },
297                                                   MathArrays.OrderDirection.INCREASING, true));
298         assertTrue(MathArrays.isMonotonic(new double[] { -15, -5.5, -1, 0, 2, 15 },
299                                                  MathArrays.OrderDirection.INCREASING, true));
300         assertFalse(MathArrays.isMonotonic(new double[] { -15, -5.5, -1, -2, 2 },
301                                                   MathArrays.OrderDirection.INCREASING, false));
302         assertTrue(MathArrays.isMonotonic(new double[] { -15, -5.5, -1, -1, 2 },
303                                                  MathArrays.OrderDirection.INCREASING, false));
304         assertFalse(MathArrays.isMonotonic(new double[] { 3, 3, -5.5, -11, -27.5 },
305                                                   MathArrays.OrderDirection.DECREASING, true));
306         assertTrue(MathArrays.isMonotonic(new double[] { 3, 2, -5.5, -11, -27.5 },
307                                                  MathArrays.OrderDirection.DECREASING, true));
308         assertFalse(MathArrays.isMonotonic(new double[] { 3, -1, 0, -5.5, -11, -27.5 },
309                                                   MathArrays.OrderDirection.DECREASING, false));
310         assertTrue(MathArrays.isMonotonic(new double[] { 3, 0, 0, -5.5, -11, -27.5 },
311                                                  MathArrays.OrderDirection.DECREASING, false));
312     }
313 
314     @Test
315     void testIsMonotonicComparable() {
316         assertFalse(MathArrays.isMonotonic(new Double[] { Double.valueOf(-15),
317                                                                  Double.valueOf(-5.5),
318                                                                  Double.valueOf(-1),
319                                                                  Double.valueOf(-1),
320                                                                  Double.valueOf(2),
321                                                                  Double.valueOf(15) },
322                 MathArrays.OrderDirection.INCREASING, true));
323         assertTrue(MathArrays.isMonotonic(new Double[] { Double.valueOf(-15),
324                                                                 Double.valueOf(-5.5),
325                                                                 Double.valueOf(-1),
326                                                                 Double.valueOf(0),
327                                                                 Double.valueOf(2),
328                                                                 Double.valueOf(15) },
329                 MathArrays.OrderDirection.INCREASING, true));
330         assertFalse(MathArrays.isMonotonic(new Double[] { Double.valueOf(-15),
331                                                                  Double.valueOf(-5.5),
332                                                                  Double.valueOf(-1),
333                                                                  Double.valueOf(-2),
334                                                                  Double.valueOf(2) },
335                 MathArrays.OrderDirection.INCREASING, false));
336         assertTrue(MathArrays.isMonotonic(new Double[] { Double.valueOf(-15),
337                                                                 Double.valueOf(-5.5),
338                                                                 Double.valueOf(-1),
339                                                                 Double.valueOf(-1),
340                                                                 Double.valueOf(2) },
341                 MathArrays.OrderDirection.INCREASING, false));
342         assertFalse(MathArrays.isMonotonic(new Double[] { Double.valueOf(3),
343                                                                  Double.valueOf(3),
344                                                                  Double.valueOf(-5.5),
345                                                                  Double.valueOf(-11),
346                                                                  Double.valueOf(-27.5) },
347                 MathArrays.OrderDirection.DECREASING, true));
348         assertTrue(MathArrays.isMonotonic(new Double[] { Double.valueOf(3),
349                                                                 Double.valueOf(2),
350                                                                 Double.valueOf(-5.5),
351                                                                 Double.valueOf(-11),
352                                                                 Double.valueOf(-27.5) },
353                 MathArrays.OrderDirection.DECREASING, true));
354         assertFalse(MathArrays.isMonotonic(new Double[] { Double.valueOf(3),
355                                                                  Double.valueOf(-1),
356                                                                  Double.valueOf(0),
357                                                                  Double.valueOf(-5.5),
358                                                                  Double.valueOf(-11),
359                                                                  Double.valueOf(-27.5) },
360                 MathArrays.OrderDirection.DECREASING, false));
361         assertTrue(MathArrays.isMonotonic(new Double[] { Double.valueOf(3),
362                                                                 Double.valueOf(0),
363                                                                 Double.valueOf(0),
364                                                                 Double.valueOf(-5.5),
365                                                                 Double.valueOf(-11),
366                                                                 Double.valueOf(-27.5) },
367                 MathArrays.OrderDirection.DECREASING, false));
368     }
369 
370     @Test
371     void testCheckRectangular() {
372         final long[][] rect = new long[][] {{0, 1}, {2, 3}};
373         final long[][] ragged = new long[][] {{0, 1}, {2}};
374         final long[][] nullArray = null;
375         final long[][] empty = new long[][] {};
376         MathArrays.checkRectangular(rect);
377         MathArrays.checkRectangular(empty);
378         try {
379             MathArrays.checkRectangular(ragged);
380             fail("Expecting MathIllegalArgumentException");
381         } catch (MathIllegalArgumentException ex) {
382             // Expected
383         }
384         try {
385             MathArrays.checkRectangular(nullArray);
386             fail("Expecting NullArgumentException");
387         } catch (NullArgumentException ex) {
388             // Expected
389         }
390     }
391 
392     @Test
393     void testCheckPositive() {
394         final double[] positive = new double[] {1, 2, 3};
395         final double[] nonNegative = new double[] {0, 1, 2};
396         final double[] nullArray = null;
397         final double[] empty = new double[] {};
398         MathArrays.checkPositive(positive);
399         MathArrays.checkPositive(empty);
400         try {
401             MathArrays.checkPositive(nullArray);
402             fail("Expecting NullPointerException");
403         } catch (NullPointerException ex) {
404             // Expected
405         }
406         try {
407             MathArrays.checkPositive(nonNegative);
408             fail("Expecting MathIllegalArgumentException");
409         } catch (MathIllegalArgumentException ex) {
410             // Expected
411         }
412     }
413 
414     @Test
415     void testCheckNonNegative() {
416         final long[] nonNegative = new long[] {0, 1};
417         final long[] hasNegative = new long[] {-1};
418         final long[] nullArray = null;
419         final long[] empty = new long[] {};
420         MathArrays.checkNonNegative(nonNegative);
421         MathArrays.checkNonNegative(empty);
422         try {
423             MathArrays.checkNonNegative(nullArray);
424             fail("Expecting NullPointerException");
425         } catch (NullPointerException ex) {
426             // Expected
427         }
428         try {
429             MathArrays.checkNonNegative(hasNegative);
430             fail("Expecting MathIllegalArgumentException");
431         } catch (MathIllegalArgumentException ex) {
432             // Expected
433         }
434     }
435 
436     @Test
437     void testCheckNonNegative2D() {
438         final long[][] nonNegative = new long[][] {{0, 1}, {1, 0}};
439         final long[][] hasNegative = new long[][] {{-1}, {0}};
440         final long[][] nullArray = null;
441         final long[][] empty = new long[][] {};
442         MathArrays.checkNonNegative(nonNegative);
443         MathArrays.checkNonNegative(empty);
444         try {
445             MathArrays.checkNonNegative(nullArray);
446             fail("Expecting NullPointerException");
447         } catch (NullPointerException ex) {
448             // Expected
449         }
450         try {
451             MathArrays.checkNonNegative(hasNegative);
452             fail("Expecting MathIllegalArgumentException");
453         } catch (MathIllegalArgumentException ex) {
454             // Expected
455         }
456     }
457 
458     @Test
459     void testCheckNotNaN() {
460         final double[] withoutNaN = { Double.NEGATIVE_INFINITY,
461                                       -Double.MAX_VALUE,
462                                       -1, 0,
463                                       Double.MIN_VALUE,
464                                       FastMath.ulp(1d),
465                                       1, 3, 113, 4769,
466                                       Double.MAX_VALUE,
467                                       Double.POSITIVE_INFINITY };
468 
469         final double[] withNaN = { Double.NEGATIVE_INFINITY,
470                                    -Double.MAX_VALUE,
471                                    -1, 0,
472                                    Double.MIN_VALUE,
473                                    FastMath.ulp(1d),
474                                    1, 3, 113, 4769,
475                                    Double.MAX_VALUE,
476                                    Double.POSITIVE_INFINITY,
477                                    Double.NaN };
478 
479 
480         final double[] nullArray = null;
481         final double[] empty = new double[] {};
482         MathArrays.checkNotNaN(withoutNaN);
483         MathArrays.checkNotNaN(empty);
484         try {
485             MathArrays.checkNotNaN(nullArray);
486             fail("Expecting NullPointerException");
487         } catch (NullPointerException ex) {
488             // Expected
489         }
490         try {
491             MathArrays.checkNotNaN(withNaN);
492             fail("Expecting MathIllegalArgumentException");
493         } catch (MathIllegalArgumentException ex) {
494             // Expected
495         }
496     }
497 
498     @Test
499     void testCheckEqualLength1() {
500         assertThrows(MathIllegalArgumentException.class, () -> {
501             MathArrays.checkEqualLength(new double[]{1, 2, 3},
502                 new double[]{1, 2, 3, 4});
503         });
504     }
505 
506     @Test
507     void testCheckEqualLength2() {
508         final double[] a = new double[] {-1, -12, -23, -34};
509         final double[] b = new double[] {56, 67, 78, 89};
510         assertTrue(MathArrays.checkEqualLength(a, b, false));
511     }
512 
513     @Test
514     void testSortInPlace() {
515         final double[] x1 = {2,   5,  -3, 1,  4};
516         final double[] x2 = {4,  25,   9, 1, 16};
517         final double[] x3 = {8, 125, -27, 1, 64};
518 
519         MathArrays.sortInPlace(x1, x2, x3);
520 
521         assertEquals(-3,  x1[0], FastMath.ulp(1d));
522         assertEquals(9,   x2[0], FastMath.ulp(1d));
523         assertEquals(-27, x3[0], FastMath.ulp(1d));
524 
525         assertEquals(1, x1[1], FastMath.ulp(1d));
526         assertEquals(1, x2[1], FastMath.ulp(1d));
527         assertEquals(1, x3[1], FastMath.ulp(1d));
528 
529         assertEquals(2, x1[2], FastMath.ulp(1d));
530         assertEquals(4, x2[2], FastMath.ulp(1d));
531         assertEquals(8, x3[2], FastMath.ulp(1d));
532 
533         assertEquals(4,  x1[3], FastMath.ulp(1d));
534         assertEquals(16, x2[3], FastMath.ulp(1d));
535         assertEquals(64, x3[3], FastMath.ulp(1d));
536 
537         assertEquals(5,   x1[4], FastMath.ulp(1d));
538         assertEquals(25,  x2[4], FastMath.ulp(1d));
539         assertEquals(125, x3[4], FastMath.ulp(1d));
540     }
541 
542     @Test
543     void testSortInPlaceDecresasingOrder() {
544         final double[] x1 = {2,   5,  -3, 1,  4};
545         final double[] x2 = {4,  25,   9, 1, 16};
546         final double[] x3 = {8, 125, -27, 1, 64};
547 
548         MathArrays.sortInPlace(x1,
549                                MathArrays.OrderDirection.DECREASING,
550                                x2, x3);
551 
552         assertEquals(-3,  x1[4], FastMath.ulp(1d));
553         assertEquals(9,   x2[4], FastMath.ulp(1d));
554         assertEquals(-27, x3[4], FastMath.ulp(1d));
555 
556         assertEquals(1, x1[3], FastMath.ulp(1d));
557         assertEquals(1, x2[3], FastMath.ulp(1d));
558         assertEquals(1, x3[3], FastMath.ulp(1d));
559 
560         assertEquals(2, x1[2], FastMath.ulp(1d));
561         assertEquals(4, x2[2], FastMath.ulp(1d));
562         assertEquals(8, x3[2], FastMath.ulp(1d));
563 
564         assertEquals(4,  x1[1], FastMath.ulp(1d));
565         assertEquals(16, x2[1], FastMath.ulp(1d));
566         assertEquals(64, x3[1], FastMath.ulp(1d));
567 
568         assertEquals(5,   x1[0], FastMath.ulp(1d));
569         assertEquals(25,  x2[0], FastMath.ulp(1d));
570         assertEquals(125, x3[0], FastMath.ulp(1d));
571     }
572 
573     /** Example in javadoc */
574     @Test
575     void testSortInPlaceExample() {
576         final double[] x = {3, 1, 2};
577         final double[] y = {1, 2, 3};
578         final double[] z = {0, 5, 7};
579         MathArrays.sortInPlace(x, y, z);
580         final double[] sx = {1, 2, 3};
581         final double[] sy = {2, 3, 1};
582         final double[] sz = {5, 7, 0};
583         assertTrue(Arrays.equals(sx, x));
584         assertTrue(Arrays.equals(sy, y));
585         assertTrue(Arrays.equals(sz, z));
586     }
587 
588     @Test
589     void testSortInPlaceFailures() {
590         final double[] nullArray = null;
591         final double[] one = {1};
592         final double[] two = {1, 2};
593         final double[] onep = {2};
594         try {
595             MathArrays.sortInPlace(one, two);
596             fail("Expecting MathIllegalArgumentException");
597         } catch (MathIllegalArgumentException ex) {
598             // expected
599         }
600         try {
601             MathArrays.sortInPlace(one, nullArray);
602             fail("Expecting NullArgumentException");
603         } catch (NullArgumentException ex) {
604             // expected
605         }
606         try {
607             MathArrays.sortInPlace(one, onep, nullArray);
608             fail("Expecting NullArgumentException");
609         } catch (NullArgumentException ex) {
610             // expected
611         }
612     }
613 
614     // MATH-1005
615     @Test
616     void testLinearCombinationWithSingleElementArray() {
617         final double[] a = { 1.23456789 };
618         final double[] b = { 98765432.1 };
619 
620         assertEquals(a[0] * b[0], MathArrays.linearCombination(a, b), 0d);
621     }
622 
623     @Test
624     void testLinearCombination1() {
625         final double[] a = new double[] {
626             -1321008684645961.0 / 268435456.0,
627             -5774608829631843.0 / 268435456.0,
628             -7645843051051357.0 / 8589934592.0
629         };
630         final double[] b = new double[] {
631             -5712344449280879.0 / 2097152.0,
632             -4550117129121957.0 / 2097152.0,
633             8846951984510141.0 / 131072.0
634         };
635 
636         final double abSumInline = MathArrays.linearCombination(a[0], b[0],
637                                                                 a[1], b[1],
638                                                                 a[2], b[2]);
639         final double abSumArray = MathArrays.linearCombination(a, b);
640 
641         assertEquals(abSumInline, abSumArray, 0);
642         assertEquals(-1.8551294182586248737720779899, abSumInline, 1.0e-15);
643 
644         final double naive = a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
645         assertTrue(FastMath.abs(naive - abSumInline) > 1.5);
646 
647     }
648 
649     @Test
650     void testLinearCombinationSignedZero() {
651         assertTrue(FastMath.copySign(1, MathArrays.linearCombination(+0.0, 1.0, +0.0, 1.0)) > 0);
652         assertTrue(FastMath.copySign(1, MathArrays.linearCombination(-0.0, 1.0, -0.0, 1.0)) < 0);
653         assertTrue(FastMath.copySign(1, MathArrays.linearCombination(+0.0, 1.0, +0.0, 1.0, +0.0, 1.0)) > 0);
654         assertTrue(FastMath.copySign(1, MathArrays.linearCombination(-0.0, 1.0, -0.0, 1.0, -0.0, 1.0)) < 0);
655         assertTrue(FastMath.copySign(1, MathArrays.linearCombination(+0.0, 1.0, +0.0, 1.0, +0.0, 1.0)) > 0);
656         assertTrue(FastMath.copySign(1, MathArrays.linearCombination(-0.0, 1.0, -0.0, 1.0, -0.0, 1.0)) < 0);
657         assertTrue(FastMath.copySign(1, MathArrays.linearCombination(+0.0, 1.0, +0.0, 1.0, +0.0, 1.0, +0.0, 1.0)) > 0);
658         assertTrue(FastMath.copySign(1, MathArrays.linearCombination(-0.0, 1.0, -0.0, 1.0, -0.0, 1.0, -0.0, 1.0)) < 0);
659         assertTrue(FastMath.copySign(1, MathArrays.linearCombination(new double[] {+0.0, +0.0}, new double[] {1.0, 1.0})) > 0);
660         assertTrue(FastMath.copySign(1, MathArrays.linearCombination(new double[] {-0.0, -0.0}, new double[] {1.0, 1.0})) < 0);
661     }
662 
663     @Test
664     void testLinearCombination2() {
665         // we compare accurate versus naive dot product implementations
666         // on regular vectors (i.e. not extreme cases like in the previous test)
667         Well1024a random = new Well1024a(553267312521321234l);
668 
669         for (int i = 0; i < 10000; ++i) {
670             final double ux = 1e17 * random.nextDouble();
671             final double uy = 1e17 * random.nextDouble();
672             final double uz = 1e17 * random.nextDouble();
673             final double vx = 1e17 * random.nextDouble();
674             final double vy = 1e17 * random.nextDouble();
675             final double vz = 1e17 * random.nextDouble();
676             final double sInline = MathArrays.linearCombination(ux, vx,
677                                                                 uy, vy,
678                                                                 uz, vz);
679             final double sArray = MathArrays.linearCombination(new double[] {ux, uy, uz},
680                                                                new double[] {vx, vy, vz});
681             assertEquals(sInline, sArray, 0);
682         }
683     }
684 
685     @Test
686     void testLinearCombinationHuge() {
687         int scale = 971;
688         final double[] a = new double[] {
689                                          -1321008684645961.0 / 268435456.0,
690                                          -5774608829631843.0 / 268435456.0,
691                                          -7645843051051357.0 / 8589934592.0
692                                      };
693         final double[] b = new double[] {
694                                          -5712344449280879.0 / 2097152.0,
695                                          -4550117129121957.0 / 2097152.0,
696                                           8846951984510141.0 / 131072.0
697                                      };
698 
699         double[] scaledA = new double[a.length];
700         double[] scaledB = new double[b.length];
701         for (int i = 0; i < scaledA.length; ++i) {
702             scaledA[i] = FastMath.scalb(a[i], -scale);
703             scaledB[i] = FastMath.scalb(b[i], +scale);
704         }
705         final double abSumInline = MathArrays.linearCombination(scaledA[0], scaledB[0],
706                                                                 scaledA[1], scaledB[1],
707                                                                 scaledA[2], scaledB[2]);
708         final double abSumArray = MathArrays.linearCombination(scaledA, scaledB);
709 
710         assertEquals(abSumInline, abSumArray, 0);
711         assertEquals(-1.8551294182586248737720779899, abSumInline, 1.0e-15);
712 
713         final double naive = scaledA[0] * scaledB[0] + scaledA[1] * scaledB[1] + scaledA[2] * scaledB[2];
714         assertTrue(FastMath.abs(naive - abSumInline) > 1.5);
715 
716     }
717 
718     @Test
719     void testLinearCombinationInfinite() {
720         final double[][] a = new double[][] {
721             { 1, 2, 3, 4},
722             { 1, Double.POSITIVE_INFINITY, 3, 4},
723             { 1, 2, Double.POSITIVE_INFINITY, 4},
724             { 1, Double.POSITIVE_INFINITY, 3, Double.NEGATIVE_INFINITY},
725             { 1, 2, 3, 4},
726             { 1, 2, 3, 4},
727             { 1, 2, 3, 4},
728             { 1, 2, 3, 4}
729         };
730         final double[][] b = new double[][] {
731             { 1, -2, 3, 4},
732             { 1, -2, 3, 4},
733             { 1, -2, 3, 4},
734             { 1, -2, 3, 4},
735             { 1, Double.POSITIVE_INFINITY, 3, 4},
736             { 1, -2, Double.POSITIVE_INFINITY, 4},
737             { 1, Double.POSITIVE_INFINITY, 3, Double.NEGATIVE_INFINITY},
738             { Double.NaN, -2, 3, 4}
739         };
740 
741         assertEquals(-3,
742                             MathArrays.linearCombination(a[0][0], b[0][0],
743                                                          a[0][1], b[0][1]),
744                             1.0e-10);
745         assertEquals(6,
746                             MathArrays.linearCombination(a[0][0], b[0][0],
747                                                          a[0][1], b[0][1],
748                                                          a[0][2], b[0][2]),
749                             1.0e-10);
750         assertEquals(22,
751                             MathArrays.linearCombination(a[0][0], b[0][0],
752                                                          a[0][1], b[0][1],
753                                                          a[0][2], b[0][2],
754                                                          a[0][3], b[0][3]),
755                             1.0e-10);
756         assertEquals(22, MathArrays.linearCombination(a[0], b[0]), 1.0e-10);
757 
758         assertEquals(Double.NEGATIVE_INFINITY,
759                             MathArrays.linearCombination(a[1][0], b[1][0],
760                                                          a[1][1], b[1][1]),
761                             1.0e-10);
762         assertEquals(Double.NEGATIVE_INFINITY,
763                             MathArrays.linearCombination(a[1][0], b[1][0],
764                                                          a[1][1], b[1][1],
765                                                          a[1][2], b[1][2]),
766                             1.0e-10);
767         assertEquals(Double.NEGATIVE_INFINITY,
768                             MathArrays.linearCombination(a[1][0], b[1][0],
769                                                          a[1][1], b[1][1],
770                                                          a[1][2], b[1][2],
771                                                          a[1][3], b[1][3]),
772                             1.0e-10);
773         assertEquals(Double.NEGATIVE_INFINITY, MathArrays.linearCombination(a[1], b[1]), 1.0e-10);
774 
775         assertEquals(-3,
776                             MathArrays.linearCombination(a[2][0], b[2][0],
777                                                          a[2][1], b[2][1]),
778                             1.0e-10);
779         assertEquals(Double.POSITIVE_INFINITY,
780                             MathArrays.linearCombination(a[2][0], b[2][0],
781                                                          a[2][1], b[2][1],
782                                                          a[2][2], b[2][2]),
783                             1.0e-10);
784         assertEquals(Double.POSITIVE_INFINITY,
785                             MathArrays.linearCombination(a[2][0], b[2][0],
786                                                          a[2][1], b[2][1],
787                                                          a[2][2], b[2][2],
788                                                          a[2][3], b[2][3]),
789                             1.0e-10);
790         assertEquals(Double.POSITIVE_INFINITY, MathArrays.linearCombination(a[2], b[2]), 1.0e-10);
791 
792         assertEquals(Double.NEGATIVE_INFINITY,
793                             MathArrays.linearCombination(a[3][0], b[3][0],
794                                                          a[3][1], b[3][1]),
795                             1.0e-10);
796         assertEquals(Double.NEGATIVE_INFINITY,
797                             MathArrays.linearCombination(a[3][0], b[3][0],
798                                                          a[3][1], b[3][1],
799                                                          a[3][2], b[3][2]),
800                             1.0e-10);
801         assertEquals(Double.NEGATIVE_INFINITY,
802                             MathArrays.linearCombination(a[3][0], b[3][0],
803                                                          a[3][1], b[3][1],
804                                                          a[3][2], b[3][2],
805                                                          a[3][3], b[3][3]),
806                             1.0e-10);
807         assertEquals(Double.NEGATIVE_INFINITY, MathArrays.linearCombination(a[3], b[3]), 1.0e-10);
808 
809         assertEquals(Double.POSITIVE_INFINITY,
810                             MathArrays.linearCombination(a[4][0], b[4][0],
811                                                          a[4][1], b[4][1]),
812                             1.0e-10);
813         assertEquals(Double.POSITIVE_INFINITY,
814                             MathArrays.linearCombination(a[4][0], b[4][0],
815                                                          a[4][1], b[4][1],
816                                                          a[4][2], b[4][2]),
817                             1.0e-10);
818         assertEquals(Double.POSITIVE_INFINITY,
819                             MathArrays.linearCombination(a[4][0], b[4][0],
820                                                          a[4][1], b[4][1],
821                                                          a[4][2], b[4][2],
822                                                          a[4][3], b[4][3]),
823                             1.0e-10);
824         assertEquals(Double.POSITIVE_INFINITY, MathArrays.linearCombination(a[4], b[4]), 1.0e-10);
825 
826         assertEquals(-3,
827                             MathArrays.linearCombination(a[5][0], b[5][0],
828                                                          a[5][1], b[5][1]),
829                             1.0e-10);
830         assertEquals(Double.POSITIVE_INFINITY,
831                             MathArrays.linearCombination(a[5][0], b[5][0],
832                                                          a[5][1], b[5][1],
833                                                          a[5][2], b[5][2]),
834                             1.0e-10);
835         assertEquals(Double.POSITIVE_INFINITY,
836                             MathArrays.linearCombination(a[5][0], b[5][0],
837                                                          a[5][1], b[5][1],
838                                                          a[5][2], b[5][2],
839                                                          a[5][3], b[5][3]),
840                             1.0e-10);
841         assertEquals(Double.POSITIVE_INFINITY, MathArrays.linearCombination(a[5], b[5]), 1.0e-10);
842 
843         assertEquals(Double.POSITIVE_INFINITY,
844                             MathArrays.linearCombination(a[6][0], b[6][0],
845                                                          a[6][1], b[6][1]),
846                             1.0e-10);
847         assertEquals(Double.POSITIVE_INFINITY,
848                             MathArrays.linearCombination(a[6][0], b[6][0],
849                                                          a[6][1], b[6][1],
850                                                          a[6][2], b[6][2]),
851                             1.0e-10);
852         assertTrue(Double.isNaN(MathArrays.linearCombination(a[6][0], b[6][0],
853                                                                     a[6][1], b[6][1],
854                                                                     a[6][2], b[6][2],
855                                                                     a[6][3], b[6][3])));
856         assertTrue(Double.isNaN(MathArrays.linearCombination(a[6], b[6])));
857 
858         assertTrue(Double.isNaN(MathArrays.linearCombination(a[7][0], b[7][0],
859                                                                     a[7][1], b[7][1])));
860         assertTrue(Double.isNaN(MathArrays.linearCombination(a[7][0], b[7][0],
861                                                                     a[7][1], b[7][1],
862                                                                     a[7][2], b[7][2])));
863         assertTrue(Double.isNaN(MathArrays.linearCombination(a[7][0], b[7][0],
864                                                                     a[7][1], b[7][1],
865                                                                     a[7][2], b[7][2],
866                                                                     a[7][3], b[7][3])));
867         assertTrue(Double.isNaN(MathArrays.linearCombination(a[7], b[7])));
868     }
869 
870     @Test
871     void testArrayEquals() {
872         assertFalse(MathArrays.equals(new double[] { 1d }, null));
873         assertFalse(MathArrays.equals(null, new double[] { 1d }));
874         assertTrue(MathArrays.equals((double[]) null, (double[]) null));
875 
876         assertFalse(MathArrays.equals(new double[] { 1d }, new double[0]));
877         assertTrue(MathArrays.equals(new double[] { 1d }, new double[] { 1d }));
878         assertTrue(MathArrays.equals(new double[] { Double.POSITIVE_INFINITY,
879                                                            Double.NEGATIVE_INFINITY, 1d, 0d },
880                                             new double[] { Double.POSITIVE_INFINITY,
881                                                            Double.NEGATIVE_INFINITY, 1d, 0d }));
882         assertFalse(MathArrays.equals(new double[] { Double.NaN },
883                                              new double[] { Double.NaN }));
884         assertFalse(MathArrays.equals(new double[] { Double.POSITIVE_INFINITY },
885                                              new double[] { Double.NEGATIVE_INFINITY }));
886         assertFalse(MathArrays.equals(new double[] { 1d },
887                                              new double[] { FastMath.nextAfter(FastMath.nextAfter(1d, 2d), 2d) }));
888 
889     }
890 
891     @Test
892     void testArrayEqualsIncludingNaN() {
893         assertFalse(MathArrays.equalsIncludingNaN(new double[] { 1d }, null));
894         assertFalse(MathArrays.equalsIncludingNaN(null, new double[] { 1d }));
895         assertTrue(MathArrays.equalsIncludingNaN((double[]) null, (double[]) null));
896 
897         assertFalse(MathArrays.equalsIncludingNaN(new double[] { 1d }, new double[0]));
898         assertTrue(MathArrays.equalsIncludingNaN(new double[] { 1d }, new double[] { 1d }));
899         assertTrue(MathArrays.equalsIncludingNaN(new double[] { Double.NaN, Double.POSITIVE_INFINITY,
900                                                                        Double.NEGATIVE_INFINITY, 1d, 0d },
901                                                         new double[] { Double.NaN, Double.POSITIVE_INFINITY,
902                                                                        Double.NEGATIVE_INFINITY, 1d, 0d }));
903         assertFalse(MathArrays.equalsIncludingNaN(new double[] { Double.POSITIVE_INFINITY },
904                                                          new double[] { Double.NEGATIVE_INFINITY }));
905         assertFalse(MathArrays.equalsIncludingNaN(new double[] { 1d },
906                                                          new double[] { FastMath.nextAfter(FastMath.nextAfter(1d, 2d), 2d) }));
907     }
908 
909     @Test
910     void testLongArrayEquals() {
911         assertFalse(MathArrays.equals(new long[] { 1L }, null));
912         assertFalse(MathArrays.equals(null, new long[] { 1L }));
913         assertTrue(MathArrays.equals((long[]) null, (long[]) null));
914 
915         assertFalse(MathArrays.equals(new long[] { 1L }, new long[0]));
916         assertTrue(MathArrays.equals(new long[] { 1L }, new long[] { 1L }));
917         assertTrue(MathArrays.equals(new long[] { 0x7ff0000000000000L,
918                                                            0xfff0000000000000L, 1L, 0L },
919                                             new long[] { 0x7ff0000000000000L,
920                                                            0xfff0000000000000L, 1L, 0L }));
921         assertFalse(MathArrays.equals(new long[] { 0x7ff0000000000000L },
922                                              new long[] { 0xfff0000000000000L }));
923 
924     }
925 
926     @Test
927     void testIntArrayEquals() {
928         assertFalse(MathArrays.equals(new int[] { 1 }, null));
929         assertFalse(MathArrays.equals(null, new int[] { 1 }));
930         assertTrue(MathArrays.equals((int[]) null, (int[]) null));
931 
932         assertFalse(MathArrays.equals(new int[] { 1 }, new int[0]));
933         assertTrue(MathArrays.equals(new int[] { 1 }, new int[] { 1 }));
934         assertTrue(MathArrays.equals(new int[] { Integer.MAX_VALUE,
935                                                         Integer.MIN_VALUE, 1, 0 },
936                                             new int[] { Integer.MAX_VALUE,
937                                                         Integer.MIN_VALUE, 1, 0 }));
938         assertFalse(MathArrays.equals(new int[] { Integer.MAX_VALUE },
939                                              new int[] { Integer.MIN_VALUE }));
940 
941     }
942 
943     @Test
944     void testByteArrayEquals() {
945         assertFalse(MathArrays.equals(new byte[] { 1 }, null));
946         assertFalse(MathArrays.equals(null, new byte[] { 1 }));
947         assertTrue(MathArrays.equals((byte[]) null, (byte[]) null));
948 
949         assertFalse(MathArrays.equals(new byte[] { 1 }, new byte[0]));
950         assertTrue(MathArrays.equals(new byte[] { 1 }, new byte[] { 1 }));
951         assertTrue(MathArrays.equals(new byte[] { Byte.MAX_VALUE,
952                                                          Byte.MIN_VALUE, 1, 0 },
953                                             new byte[] { Byte.MAX_VALUE,
954                                                          Byte.MIN_VALUE, 1, 0 }));
955         assertFalse(MathArrays.equals(new byte[] { Byte.MAX_VALUE },
956                                              new byte[] { Byte.MIN_VALUE }));
957 
958     }
959 
960     @Test
961     void testShortArrayEquals() {
962         assertFalse(MathArrays.equals(new short[] { 1 }, null));
963         assertFalse(MathArrays.equals(null, new short[] { 1 }));
964         assertTrue(MathArrays.equals((short[]) null, (short[]) null));
965 
966         assertFalse(MathArrays.equals(new short[] { 1 }, new short[0]));
967         assertTrue(MathArrays.equals(new short[] { 1 }, new short[] { 1 }));
968         assertTrue(MathArrays.equals(new short[] { Short.MAX_VALUE,
969                                                           Short.MIN_VALUE, 1, 0 },
970                                             new short[] { Short.MAX_VALUE,
971                                                           Short.MIN_VALUE, 1, 0 }));
972         assertFalse(MathArrays.equals(new short[] { Short.MAX_VALUE },
973                                              new short[] { Short.MIN_VALUE }));
974 
975     }
976 
977     @Test
978     void testFloatArrayEquals() {
979         assertFalse(MathArrays.equals(new float[] { 1 }, null));
980         assertFalse(MathArrays.equals(null, new float[] { 1 }));
981         assertTrue(MathArrays.equals((float[]) null, (float[]) null));
982 
983         assertFalse(MathArrays.equals(new float[] { 1 }, new float[0]));
984         assertTrue(MathArrays.equals(new float[] { 1 }, new float[] { 1 }));
985         assertTrue(MathArrays.equals(new float[] { Float.MAX_VALUE,
986                                                           Float.MIN_VALUE, 1, 0 },
987                                             new float[] { Float.MAX_VALUE,
988                                                           Float.MIN_VALUE, 1, 0 }));
989         assertFalse(MathArrays.equals(new float[] { Float.MAX_VALUE },
990                                              new float[] { Float.MIN_VALUE }));
991 
992     }
993 
994     @Test
995     void testDoubleArrayEquals() {
996         assertFalse(MathArrays.equals(new double[] { 1 }, null));
997         assertFalse(MathArrays.equals(null, new double[] { 1 }));
998         assertTrue(MathArrays.equals((double[]) null, (double[]) null));
999 
1000         assertFalse(MathArrays.equals(new double[] { 1 }, new double[0]));
1001         assertTrue(MathArrays.equals(new double[] { 1 }, new double[] { 1 }));
1002         assertTrue(MathArrays.equals(new double[] { Double.MAX_VALUE,
1003                                                           Double.MIN_VALUE, 1, 0 },
1004                                             new double[] { Double.MAX_VALUE,
1005                                                           Double.MIN_VALUE, 1, 0 }));
1006         assertFalse(MathArrays.equals(new double[] { Double.MAX_VALUE },
1007                                              new double[] { Double.MIN_VALUE }));
1008 
1009     }
1010 
1011     @Test
1012     void testFieldArrayEquals() {
1013         assertFalse(MathArrays.equals(new Complex[] { Complex.I }, null));
1014         assertFalse(MathArrays.equals(null, new Complex[] { Complex.I }));
1015         assertTrue(MathArrays.equals((Complex[]) null, (Complex[]) null));
1016 
1017         assertFalse(MathArrays.equals(new Complex[] { Complex.I }, new Complex[0]));
1018         assertTrue(MathArrays.equals(new Complex[] { Complex.I }, new Complex[] { Complex.I }));
1019         assertTrue(MathArrays.equals(new Complex[] { new Complex(Double.MAX_VALUE, 0),
1020                                                      new Complex(Double.MIN_VALUE, 0),
1021                                                      Complex.ONE, Complex.ZERO },
1022                                      new Complex[] { new Complex(Double.MAX_VALUE, 0),
1023                                                      new Complex(Double.MIN_VALUE, 0),
1024                                                      Complex.ONE, Complex.ZERO }));
1025         assertFalse(MathArrays.equals(new Complex[] { new Complex(Double.MAX_VALUE, 0) },
1026                                              new Complex[] { new Complex(Double.MIN_VALUE, 0) }));
1027 
1028     }
1029 
1030     @Test
1031     void testNormalizeArray() {
1032         double[] testValues1 = new double[] {1, 1, 2};
1033         UnitTestUtils.customAssertEquals(new double[] { .25, .25, .5},
1034                                          MathArrays.normalizeArray(testValues1, 1),
1035                                          Double.MIN_VALUE);
1036 
1037         double[] testValues2 = new double[] {-1, -1, 1};
1038         UnitTestUtils.customAssertEquals(new double[] { 1, 1, -1},
1039                                          MathArrays.normalizeArray(testValues2, 1),
1040                                          Double.MIN_VALUE);
1041 
1042         // Ignore NaNs
1043         double[] testValues3 = new double[] {-1, -1, Double.NaN, 1, Double.NaN};
1044         UnitTestUtils.customAssertEquals(new double[] { 1, 1, Double.NaN, -1, Double.NaN},
1045                                          MathArrays.normalizeArray(testValues3, 1),
1046                                          Double.MIN_VALUE);
1047 
1048         // Zero sum -> MathRuntimeException
1049         double[] zeroSum = new double[] {-1, 1};
1050         try {
1051             MathArrays.normalizeArray(zeroSum, 1);
1052             fail("expecting MathRuntimeException");
1053         } catch (MathRuntimeException ex) {}
1054 
1055         // Infinite elements -> MathRuntimeException
1056         double[] hasInf = new double[] {1, 2, 1, Double.NEGATIVE_INFINITY};
1057         try {
1058             MathArrays.normalizeArray(hasInf, 1);
1059             fail("expecting MathIllegalArgumentException");
1060         } catch (MathIllegalArgumentException ex) {}
1061 
1062         // Infinite target -> MathIllegalArgumentException
1063         try {
1064             MathArrays.normalizeArray(testValues1, Double.POSITIVE_INFINITY);
1065             fail("expecting MathIllegalArgumentException");
1066         } catch (MathIllegalArgumentException ex) {}
1067 
1068         // NaN target -> MathIllegalArgumentException
1069         try {
1070             MathArrays.normalizeArray(testValues1, Double.NaN);
1071             fail("expecting MathIllegalArgumentException");
1072         } catch (MathIllegalArgumentException ex) {}
1073     }
1074 
1075     @Test
1076     void testConvolve() {
1077         /* Test Case (obtained via SciPy)
1078          * x=[1.2,-1.8,1.4]
1079          * h=[1,0.8,0.5,0.3]
1080          * convolve(x,h) -> array([ 1.2 , -0.84,  0.56,  0.58,  0.16,  0.42])
1081          */
1082         double[] x1 = { 1.2, -1.8, 1.4 };
1083         double[] h1 = { 1, 0.8, 0.5, 0.3 };
1084         double[] y1 = { 1.2, -0.84, 0.56, 0.58, 0.16, 0.42 };
1085         double tolerance = 1e-13;
1086 
1087         double[] yActual = MathArrays.convolve(x1, h1);
1088         assertArrayEquals(y1, yActual, tolerance);
1089 
1090         double[] x2 = { 1, 2, 3 };
1091         double[] h2 = { 0, 1, 0.5 };
1092         double[] y2 = { 0, 1, 2.5, 4, 1.5 };
1093 
1094         yActual = MathArrays.convolve(x2, h2);
1095         assertArrayEquals(y2, yActual, tolerance);
1096 
1097         try {
1098             MathArrays.convolve(new double[]{1, 2}, null);
1099             fail("an exception should have been thrown");
1100         } catch (NullArgumentException e) {
1101             // expected behavior
1102         }
1103 
1104         try {
1105             MathArrays.convolve(null, new double[]{1, 2});
1106             fail("an exception should have been thrown");
1107         } catch (NullArgumentException e) {
1108             // expected behavior
1109         }
1110 
1111         try {
1112             MathArrays.convolve(new double[]{1, 2}, new double[]{});
1113             fail("an exception should have been thrown");
1114         } catch (MathIllegalArgumentException e) {
1115             // expected behavior
1116         }
1117 
1118         try {
1119             MathArrays.convolve(new double[]{}, new double[]{1, 2});
1120             fail("an exception should have been thrown");
1121         } catch (MathIllegalArgumentException e) {
1122             // expected behavior
1123         }
1124 
1125         try {
1126             MathArrays.convolve(new double[]{}, new double[]{});
1127             fail("an exception should have been thrown");
1128         } catch (MathIllegalArgumentException e) {
1129             // expected behavior
1130         }
1131     }
1132 
1133     @Test
1134     void testShuffleTail() {
1135         final int[] orig = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
1136         final int[] list = orig.clone();
1137         final int start = 4;
1138         MathArrays.shuffle(list, start, MathArrays.Position.TAIL, new Well1024a(7654321L));
1139 
1140         // Ensure that all entries below index "start" did not move.
1141         for (int i = 0; i < start; i++) {
1142             assertEquals(orig[i], list[i]);
1143         }
1144 
1145         // Ensure that at least one entry has moved.
1146         boolean ok = false;
1147         for (int i = start; i < orig.length - 1; i++) {
1148             if (orig[i] != list[i]) {
1149                 ok = true;
1150                 break;
1151             }
1152         }
1153         assertTrue(ok);
1154     }
1155 
1156     @Test
1157     void testShuffleHead() {
1158         final int[] orig = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
1159         final int[] list = orig.clone();
1160         final int start = 4;
1161         MathArrays.shuffle(list, start, MathArrays.Position.HEAD, new Well1024a(1234567L));
1162 
1163         // Ensure that all entries above index "start" did not move.
1164         for (int i = start + 1; i < orig.length; i++) {
1165             assertEquals(orig[i], list[i]);
1166         }
1167 
1168         // Ensure that at least one entry has moved.
1169         boolean ok = false;
1170         for (int i = 0; i <= start; i++) {
1171             if (orig[i] != list[i]) {
1172                 ok = true;
1173                 break;
1174             }
1175         }
1176         assertTrue(ok);
1177     }
1178 
1179     @Test
1180     void testNatural() {
1181         final int n = 4;
1182         final int[] expected = {0, 1, 2, 3};
1183 
1184         final int[] natural = MathArrays.natural(n);
1185         for (int i = 0; i < n; i++) {
1186             assertEquals(expected[i], natural[i]);
1187         }
1188     }
1189 
1190     @Test
1191     void testNaturalZero() {
1192         final int[] natural = MathArrays.natural(0);
1193         assertEquals(0, natural.length);
1194     }
1195 
1196     @Test
1197     void testSequence() {
1198         final int size = 4;
1199         final int start = 5;
1200         final int stride = 2;
1201         final int[] expected = {5, 7, 9, 11};
1202 
1203         final int[] seq = MathArrays.sequence(size, start, stride);
1204         for (int i = 0; i < size; i++) {
1205             assertEquals(expected[i], seq[i]);
1206         }
1207     }
1208 
1209     @Test
1210     void testSequenceZero() {
1211         final int[] seq = MathArrays.sequence(0, 12345, 6789);
1212         assertEquals(0, seq.length);
1213     }
1214 
1215     @Test
1216     void testVerifyValuesPositive() {
1217         for (int j = 0; j < 6; j++) {
1218             for (int i = 1; i < (7 - j); i++) {
1219                 assertTrue(MathArrays.verifyValues(testArray, 0, i));
1220             }
1221         }
1222         assertTrue(MathArrays.verifyValues(singletonArray, 0, 1));
1223         assertTrue(MathArrays.verifyValues(singletonArray, 0, 0, true));
1224     }
1225 
1226     @Test
1227     void testVerifyValuesNegative() {
1228         assertFalse(MathArrays.verifyValues(singletonArray, 0, 0));
1229         assertFalse(MathArrays.verifyValues(testArray, 0, 0));
1230         try {
1231             MathArrays.verifyValues(singletonArray, 2, 1);  // start past end
1232             fail("Expecting MathIllegalArgumentException");
1233         } catch (MathIllegalArgumentException ex) {
1234             // expected
1235         }
1236         try {
1237             MathArrays.verifyValues(testArray, 0, 7);  // end past end
1238             fail("Expecting MathIllegalArgumentException");
1239         } catch (MathIllegalArgumentException ex) {
1240             // expected
1241         }
1242         try {
1243             MathArrays.verifyValues(testArray, -1, 1);  // start negative
1244             fail("Expecting MathIllegalArgumentException");
1245         } catch (MathIllegalArgumentException ex) {
1246             // expected
1247         }
1248         try {
1249             MathArrays.verifyValues(testArray, 0, -1);  // length negative
1250             fail("Expecting MathIllegalArgumentException");
1251         } catch (MathIllegalArgumentException ex) {
1252             // expected
1253         }
1254         try {
1255             MathArrays.verifyValues(nullArray, 0, 1);  // null array
1256             fail("Expecting NullArgumentException");
1257         } catch (NullArgumentException ex) {
1258             // expected
1259         }
1260         try {
1261             MathArrays.verifyValues(testArray, nullArray, 0, 1);  // null weights array
1262             fail("Expecting NullArgumentException");
1263         } catch (NullArgumentException ex) {
1264             // expected
1265         }
1266         try {
1267             MathArrays.verifyValues(singletonArray, testWeightsArray, 0, 1);  // weights.length != value.length
1268             fail("Expecting MathIllegalArgumentException");
1269         } catch (MathIllegalArgumentException ex) {
1270             // expected
1271         }
1272         try {
1273             MathArrays.verifyValues(testArray, testNegativeWeightsArray, 0, 6);  // can't have negative weights
1274             fail("Expecting MathIllegalArgumentException");
1275         } catch (MathIllegalArgumentException ex) {
1276             // expected
1277         }
1278     }
1279 
1280     @Test
1281     void testConcatenate() {
1282         final double[] u = new double[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
1283         final double[] x = new double[] {0, 1, 2};
1284         final double[] y = new double[] {3, 4, 5, 6, 7, 8};
1285         final double[] z = new double[] {9};
1286         assertArrayEquals(u, MathArrays.concatenate(x, y, z), 0);
1287     }
1288 
1289     @Test
1290     void testConcatentateSingle() {
1291         final double[] x = new double[] {0, 1, 2};
1292         assertArrayEquals(x, MathArrays.concatenate(x), 0);
1293     }
1294 
1295     public void testConcatenateEmptyArguments() {
1296         final double[] x = new double[] {0, 1, 2};
1297         final double[] y = new double[] {3};
1298         final double[] z = new double[] {};
1299         final double[] u = new double[] {0, 1, 2, 3};
1300         assertArrayEquals(u,  MathArrays.concatenate(x, z, y), 0);
1301         assertArrayEquals(u,  MathArrays.concatenate(x, y, z), 0);
1302         assertArrayEquals(u,  MathArrays.concatenate(z, x, y), 0);
1303         assertEquals(0,  MathArrays.concatenate(z, z, z).length);
1304     }
1305 
1306     @Test
1307     void testConcatenateNullArguments() {
1308         assertThrows(NullPointerException.class, () -> {
1309             final double[] x = new double[]{0, 1, 2};
1310             MathArrays.concatenate(x, null);
1311         });
1312     }
1313 
1314     @Test
1315     void testUnique() {
1316         final double[] x = {0, 9, 3, 0, 11, 7, 3, 5, -1, -2};
1317         final double[] values = {11, 9, 7, 5, 3, 0, -1, -2};
1318         assertArrayEquals(values, MathArrays.unique(x), 0);
1319     }
1320 
1321     @Test
1322     void testUniqueInfiniteValues() {
1323         final double [] x = {0, Double.NEGATIVE_INFINITY, 3, Double.NEGATIVE_INFINITY,
1324             3, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY};
1325         final double[] u = {Double.POSITIVE_INFINITY, 3, 0, Double.NEGATIVE_INFINITY};
1326         assertArrayEquals(u , MathArrays.unique(x), 0);
1327     }
1328 
1329     @Test
1330     void testUniqueNaNValues() {
1331         final double[] x = new double[] {10, 2, Double.NaN, Double.NaN, Double.NaN,
1332             Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY};
1333         final double[] u = MathArrays.unique(x);
1334         assertEquals(5, u.length);
1335         assertTrue(Double.isNaN(u[0]));
1336         assertEquals(Double.POSITIVE_INFINITY, u[1], 0);
1337         assertEquals(10, u[2], 0);
1338         assertEquals(2, u[3], 0);
1339         assertEquals(Double.NEGATIVE_INFINITY, u[4], 0);
1340     }
1341 
1342     @Test
1343     void testUniqueNullArgument() {
1344         assertThrows(NullPointerException.class, () -> {
1345             MathArrays.unique(null);
1346         });
1347     }
1348 
1349     @Test
1350     void testBuildArray1() {
1351         Binary64Field field = Binary64Field.getInstance();
1352         Binary64[] array = MathArrays.buildArray(field, 3);
1353         assertEquals(3, array.length);
1354         for (Binary64 d : array) {
1355             assertSame(field.getZero(), d);
1356         }
1357     }
1358 
1359     @Test
1360     void testBuildArray2AllIndices() {
1361         Binary64Field field = Binary64Field.getInstance();
1362         Binary64[][] array = MathArrays.buildArray(field, 3, 2);
1363         assertEquals(3, array.length);
1364         for (Binary64[] a1 : array) {
1365             assertEquals(2, a1.length);
1366             for (Binary64 d : a1) {
1367                 assertSame(field.getZero(), d);
1368             }
1369         }
1370     }
1371 
1372     @Test
1373     void testBuildArray2MissingLastIndex() {
1374         Binary64Field field = Binary64Field.getInstance();
1375         Binary64[][] array = MathArrays.buildArray(field, 3, -1);
1376         assertEquals(3, array.length);
1377         for (Binary64[] a1 : array) {
1378             assertNull(a1);
1379         }
1380     }
1381 
1382     @Test
1383     void testBuildArray3AllIndices() {
1384         Binary64Field field = Binary64Field.getInstance();
1385         Binary64[][][] array = MathArrays.buildArray(field, 3, 2, 4);
1386         assertEquals(3, array.length);
1387         for (Binary64[][] a1 : array) {
1388             assertEquals(2, a1.length);
1389             for (Binary64[] a2 : a1) {
1390                 assertEquals(4, a2.length);
1391                 for (Binary64 d : a2) {
1392                     assertSame(field.getZero(), d);
1393                 }
1394             }
1395         }
1396     }
1397 
1398     @Test
1399     void testBuildArray3MissingLastIndex() {
1400         Binary64Field field = Binary64Field.getInstance();
1401         Binary64[][][] array = MathArrays.buildArray(field, 3, 2, -1);
1402         assertEquals(3, array.length);
1403         for (Binary64[][] a1 : array) {
1404             assertEquals(2, a1.length);
1405             for (Binary64[] a2 : a1) {
1406                 assertNull(a2);
1407             }
1408         }
1409     }
1410 
1411 }