View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  /*
19   * This is not the original file distributed by the Apache Software Foundation
20   * It has been modified by the Hipparchus project
21   */
22  
23  package org.hipparchus.util;
24  
25  import java.lang.reflect.Array;
26  import java.util.ArrayList;
27  import java.util.Arrays;
28  import java.util.Collections;
29  import java.util.Comparator;
30  import java.util.Iterator;
31  import java.util.List;
32  import java.util.TreeSet;
33  
34  import org.hipparchus.Field;
35  import org.hipparchus.FieldElement;
36  import org.hipparchus.CalculusFieldElement;
37  import org.hipparchus.exception.LocalizedCoreFormats;
38  import org.hipparchus.exception.MathIllegalArgumentException;
39  import org.hipparchus.exception.MathRuntimeException;
40  import org.hipparchus.exception.NullArgumentException;
41  import org.hipparchus.random.RandomGenerator;
42  import org.hipparchus.random.Well19937c;
43  
44  /**
45   * Arrays utilities.
46   */
47  public class MathArrays {
48  
49      /**
50       * Private constructor.
51       */
52      private MathArrays() {}
53  
54      /**
55       * Real-valued function that operates on an array or a part of it.
56       */
57      public interface Function {
58  
59          /** Operates on an entire array.
60           * @param array Array to operate on.
61           * @return the result of the operation.
62           */
63          double evaluate(double[] array);
64  
65          /** Operates on a sub-array.
66           * @param array Array to operate on.
67           * @param startIndex Index of the first element to take into account.
68           * @param numElements Number of elements to take into account.
69           * @return the result of the operation.
70           */
71          double evaluate(double[] array,
72                          int startIndex,
73                          int numElements);
74  
75      }
76  
77      /**
78       * Create a copy of an array scaled by a value.
79       *
80       * @param arr Array to scale.
81       * @param val Scalar.
82       * @return scaled copy of array with each entry multiplied by val.
83       */
84      public static double[] scale(double val, final double[] arr) {
85          double[] newArr = new double[arr.length];
86          for (int i = 0; i < arr.length; i++) {
87              newArr[i] = arr[i] * val;
88          }
89          return newArr;
90      }
91  
92      /**
93       * Multiply each element of an array by a value.
94       * <p>
95       * The array is modified in place (no copy is created).
96       *
97       * @param arr Array to scale
98       * @param val Scalar
99       */
100     public static void scaleInPlace(double val, final double[] arr) {
101         for (int i = 0; i < arr.length; i++) {
102             arr[i] *= val;
103         }
104     }
105 
106     /**
107      * Creates an array whose contents will be the element-by-element
108      * addition of the arguments.
109      *
110      * @param a First term of the addition.
111      * @param b Second term of the addition.
112      * @return a new array {@code r} where {@code r[i] = a[i] + b[i]}.
113      * @throws MathIllegalArgumentException if the array lengths differ.
114      */
115     public static double[] ebeAdd(double[] a, double[] b)
116         throws MathIllegalArgumentException {
117         checkEqualLength(a, b);
118 
119         final double[] result = a.clone();
120         for (int i = 0; i < a.length; i++) {
121             result[i] += b[i];
122         }
123         return result;
124     }
125     /**
126      * Creates an array whose contents will be the element-by-element
127      * subtraction of the second argument from the first.
128      *
129      * @param a First term.
130      * @param b Element to be subtracted.
131      * @return a new array {@code r} where {@code r[i] = a[i] - b[i]}.
132      * @throws MathIllegalArgumentException if the array lengths differ.
133      */
134     public static double[] ebeSubtract(double[] a, double[] b)
135         throws MathIllegalArgumentException {
136         checkEqualLength(a, b);
137 
138         final double[] result = a.clone();
139         for (int i = 0; i < a.length; i++) {
140             result[i] -= b[i];
141         }
142         return result;
143     }
144     /**
145      * Creates an array whose contents will be the element-by-element
146      * multiplication of the arguments.
147      *
148      * @param a First factor of the multiplication.
149      * @param b Second factor of the multiplication.
150      * @return a new array {@code r} where {@code r[i] = a[i] * b[i]}.
151      * @throws MathIllegalArgumentException if the array lengths differ.
152      */
153     public static double[] ebeMultiply(double[] a, double[] b)
154         throws MathIllegalArgumentException {
155         checkEqualLength(a, b);
156 
157         final double[] result = a.clone();
158         for (int i = 0; i < a.length; i++) {
159             result[i] *= b[i];
160         }
161         return result;
162     }
163     /**
164      * Creates an array whose contents will be the element-by-element
165      * division of the first argument by the second.
166      *
167      * @param a Numerator of the division.
168      * @param b Denominator of the division.
169      * @return a new array {@code r} where {@code r[i] = a[i] / b[i]}.
170      * @throws MathIllegalArgumentException if the array lengths differ.
171      */
172     public static double[] ebeDivide(double[] a, double[] b)
173         throws MathIllegalArgumentException {
174         checkEqualLength(a, b);
175 
176         final double[] result = a.clone();
177         for (int i = 0; i < a.length; i++) {
178             result[i] /= b[i];
179         }
180         return result;
181     }
182 
183     /**
184      * Calculates the L<sub>1</sub> (sum of abs) distance between two points.
185      *
186      * @param p1 the first point
187      * @param p2 the second point
188      * @return the L<sub>1</sub> distance between the two points
189      * @throws MathIllegalArgumentException if the array lengths differ.
190      */
191     public static double distance1(double[] p1, double[] p2)
192         throws MathIllegalArgumentException {
193         checkEqualLength(p1, p2);
194         double sum = 0;
195         for (int i = 0; i < p1.length; i++) {
196             sum += FastMath.abs(p1[i] - p2[i]);
197         }
198         return sum;
199     }
200 
201     /**
202      * Calculates the L<sub>1</sub> (sum of abs) distance between two points.
203      *
204      * @param p1 the first point
205      * @param p2 the second point
206      * @return the L<sub>1</sub> distance between the two points
207      * @throws MathIllegalArgumentException if the array lengths differ.
208      */
209     public static int distance1(int[] p1, int[] p2)
210         throws MathIllegalArgumentException {
211         checkEqualLength(p1, p2);
212         int sum = 0;
213         for (int i = 0; i < p1.length; i++) {
214             sum += FastMath.abs(p1[i] - p2[i]);
215         }
216         return sum;
217     }
218 
219     /**
220      * Calculates the L<sub>2</sub> (Euclidean) distance between two points.
221      *
222      * @param p1 the first point
223      * @param p2 the second point
224      * @return the L<sub>2</sub> distance between the two points
225      * @throws MathIllegalArgumentException if the array lengths differ.
226      */
227     public static double distance(double[] p1, double[] p2)
228         throws MathIllegalArgumentException {
229         checkEqualLength(p1, p2);
230         double sum = 0;
231         for (int i = 0; i < p1.length; i++) {
232             final double dp = p1[i] - p2[i];
233             sum += dp * dp;
234         }
235         return FastMath.sqrt(sum);
236     }
237 
238     /**
239      * Calculates the cosine of the angle between two vectors.
240      *
241      * @param v1 Cartesian coordinates of the first vector.
242      * @param v2 Cartesian coordinates of the second vector.
243      * @return the cosine of the angle between the vectors.
244      */
245     public static double cosAngle(double[] v1, double[] v2) {
246         return linearCombination(v1, v2) / (safeNorm(v1) * safeNorm(v2));
247     }
248 
249     /**
250      * Calculates the L<sub>2</sub> (Euclidean) distance between two points.
251      *
252      * @param p1 the first point
253      * @param p2 the second point
254      * @return the L<sub>2</sub> distance between the two points
255      * @throws MathIllegalArgumentException if the array lengths differ.
256      */
257     public static double distance(int[] p1, int[] p2)
258         throws MathIllegalArgumentException {
259         checkEqualLength(p1, p2);
260         double sum = 0;
261         for (int i = 0; i < p1.length; i++) {
262             final double dp = p1[i] - p2[i];
263             sum += dp * dp;
264         }
265         return FastMath.sqrt(sum);
266     }
267 
268     /**
269      * Calculates the L<sub>&infin;</sub> (max of abs) distance between two points.
270      *
271      * @param p1 the first point
272      * @param p2 the second point
273      * @return the L<sub>&infin;</sub> distance between the two points
274      * @throws MathIllegalArgumentException if the array lengths differ.
275      */
276     public static double distanceInf(double[] p1, double[] p2)
277         throws MathIllegalArgumentException {
278         checkEqualLength(p1, p2);
279         double max = 0;
280         for (int i = 0; i < p1.length; i++) {
281             max = FastMath.max(max, FastMath.abs(p1[i] - p2[i]));
282         }
283         return max;
284     }
285 
286     /**
287      * Calculates the L<sub>&infin;</sub> (max of abs) distance between two points.
288      *
289      * @param p1 the first point
290      * @param p2 the second point
291      * @return the L<sub>&infin;</sub> distance between the two points
292      * @throws MathIllegalArgumentException if the array lengths differ.
293      */
294     public static int distanceInf(int[] p1, int[] p2)
295         throws MathIllegalArgumentException {
296         checkEqualLength(p1, p2);
297         int max = 0;
298         for (int i = 0; i < p1.length; i++) {
299             max = FastMath.max(max, FastMath.abs(p1[i] - p2[i]));
300         }
301         return max;
302     }
303 
304     /**
305      * Specification of ordering direction.
306      */
307     public enum OrderDirection {
308         /** Constant for increasing direction. */
309         INCREASING,
310         /** Constant for decreasing direction. */
311         DECREASING
312     }
313 
314     /**
315      * Check that an array is monotonically increasing or decreasing.
316      *
317      * @param <T> the type of the elements in the specified array
318      * @param val Values.
319      * @param dir Ordering direction.
320      * @param strict Whether the order should be strict.
321      * @return {@code true} if sorted, {@code false} otherwise.
322      */
323     public static <T extends Comparable<? super T>> boolean isMonotonic(T[] val,
324                                                                         OrderDirection dir,
325                                                                         boolean strict) {
326         T previous = val[0];
327         final int max = val.length;
328         for (int i = 1; i < max; i++) {
329             final int comp;
330             switch (dir) {
331             case INCREASING:
332                 comp = previous.compareTo(val[i]);
333                 if (strict) {
334                     if (comp >= 0) {
335                         return false;
336                     }
337                 } else {
338                     if (comp > 0) {
339                         return false;
340                     }
341                 }
342                 break;
343             case DECREASING:
344                 comp = val[i].compareTo(previous);
345                 if (strict) {
346                     if (comp >= 0) {
347                         return false;
348                     }
349                 } else {
350                     if (comp > 0) {
351                        return false;
352                     }
353                 }
354                 break;
355             default:
356                 // Should never happen.
357                 throw MathRuntimeException.createInternalError();
358             }
359 
360             previous = val[i];
361         }
362         return true;
363     }
364 
365     /**
366      * Check that an array is monotonically increasing or decreasing.
367      *
368      * @param val Values.
369      * @param dir Ordering direction.
370      * @param strict Whether the order should be strict.
371      * @return {@code true} if sorted, {@code false} otherwise.
372      */
373     public static boolean isMonotonic(double[] val, OrderDirection dir, boolean strict) {
374         return checkOrder(val, dir, strict, false);
375     }
376 
377     /**
378      * Check that both arrays have the same length.
379      *
380      * @param a Array.
381      * @param b Array.
382      * @param abort Whether to throw an exception if the check fails.
383      * @return {@code true} if the arrays have the same length.
384      * @throws MathIllegalArgumentException if the lengths differ and
385      * {@code abort} is {@code true}.
386      */
387     public static boolean checkEqualLength(double[] a,
388                                            double[] b,
389                                            boolean abort) {
390         if (a.length == b.length) {
391             return true;
392         } else {
393             if (abort) {
394                 throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
395                                                        a.length, b.length);
396             }
397             return false;
398         }
399     }
400 
401     /**
402      * Check that both arrays have the same length.
403      *
404      * @param a Array.
405      * @param b Array.
406      * @throws MathIllegalArgumentException if the lengths differ.
407      */
408     public static void checkEqualLength(double[] a,
409                                         double[] b) {
410         checkEqualLength(a, b, true);
411     }
412 
413     /**
414      * Check that both arrays have the same length.
415      *
416      * @param a Array.
417      * @param b Array.
418      * @param abort Whether to throw an exception if the check fails.
419      * @return {@code true} if the arrays have the same length.
420      * @throws MathIllegalArgumentException if the lengths differ and
421      * {@code abort} is {@code true}.
422      * @param <T> the type of the field elements
423      * @since 1.5
424      */
425     public static <T extends CalculusFieldElement<T>> boolean checkEqualLength(final T[] a,
426                                                                            final T[] b,
427                                            boolean abort) {
428         if (a.length == b.length) {
429             return true;
430         } else {
431             if (abort) {
432                 throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
433                                                        a.length, b.length);
434             }
435             return false;
436         }
437     }
438 
439     /**
440      * Check that both arrays have the same length.
441      *
442      * @param a Array.
443      * @param b Array.
444      * @throws MathIllegalArgumentException if the lengths differ.
445      * @param <T> the type of the field elements
446      * @since 1.5
447      */
448     public static <T extends CalculusFieldElement<T>> void checkEqualLength(final T[] a, final T[] b) {
449         checkEqualLength(a, b, true);
450     }
451 
452     /**
453      * Check that both arrays have the same length.
454      *
455      * @param a Array.
456      * @param b Array.
457      * @param abort Whether to throw an exception if the check fails.
458      * @return {@code true} if the arrays have the same length.
459      * @throws MathIllegalArgumentException if the lengths differ and
460      * {@code abort} is {@code true}.
461      */
462     public static boolean checkEqualLength(int[] a,
463                                            int[] b,
464                                            boolean abort) {
465         if (a.length == b.length) {
466             return true;
467         } else {
468             if (abort) {
469                 throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
470                                                        a.length, b.length);
471             }
472             return false;
473         }
474     }
475 
476     /**
477      * Check that both arrays have the same length.
478      *
479      * @param a Array.
480      * @param b Array.
481      * @throws MathIllegalArgumentException if the lengths differ.
482      */
483     public static void checkEqualLength(int[] a,
484                                         int[] b) {
485         checkEqualLength(a, b, true);
486     }
487 
488     /**
489      * Check that the given array is sorted.
490      *
491      * @param val Values.
492      * @param dir Ordering direction.
493      * @param strict Whether the order should be strict.
494      * @param abort Whether to throw an exception if the check fails.
495      * @return {@code true} if the array is sorted.
496      * @throws MathIllegalArgumentException if the array is not sorted
497      * and {@code abort} is {@code true}.
498      */
499     public static boolean checkOrder(double[] val, OrderDirection dir,
500                                      boolean strict, boolean abort)
501         throws MathIllegalArgumentException {
502         double previous = val[0];
503         final int max = val.length;
504 
505         int index;
506         ITEM:
507         for (index = 1; index < max; index++) {
508             switch (dir) {
509             case INCREASING:
510                 if (strict) {
511                     if (val[index] <= previous) {
512                         break ITEM;
513                     }
514                 } else {
515                     if (val[index] < previous) {
516                         break ITEM;
517                     }
518                 }
519                 break;
520             case DECREASING:
521                 if (strict) {
522                     if (val[index] >= previous) {
523                         break ITEM;
524                     }
525                 } else {
526                     if (val[index] > previous) {
527                         break ITEM;
528                     }
529                 }
530                 break;
531             default:
532                 // Should never happen.
533                 throw MathRuntimeException.createInternalError();
534             }
535 
536             previous = val[index];
537         }
538 
539         if (index == max) {
540             // Loop completed.
541             return true;
542         }
543 
544         // Loop early exit means wrong ordering.
545         if (abort) {
546             throw new MathIllegalArgumentException(dir == MathArrays.OrderDirection.INCREASING ?
547                                                     (strict ?
548                                                      LocalizedCoreFormats.NOT_STRICTLY_INCREASING_SEQUENCE :
549                                                      LocalizedCoreFormats.NOT_INCREASING_SEQUENCE) :
550                                                     (strict ?
551                                                      LocalizedCoreFormats.NOT_STRICTLY_DECREASING_SEQUENCE :
552                                                      LocalizedCoreFormats.NOT_DECREASING_SEQUENCE),
553                                                     val[index], previous, index, index - 1);
554         } else {
555             return false;
556         }
557     }
558 
559     /**
560      * Check that the given array is sorted.
561      *
562      * @param val Values.
563      * @param dir Ordering direction.
564      * @param strict Whether the order should be strict.
565      * @throws MathIllegalArgumentException if the array is not sorted.
566      */
567     public static void checkOrder(double[] val, OrderDirection dir,
568                                   boolean strict) throws MathIllegalArgumentException {
569         checkOrder(val, dir, strict, true);
570     }
571 
572     /**
573      * Check that the given array is sorted in strictly increasing order.
574      *
575      * @param val Values.
576      * @throws MathIllegalArgumentException if the array is not sorted.
577      */
578     public static void checkOrder(double[] val) throws MathIllegalArgumentException {
579         checkOrder(val, OrderDirection.INCREASING, true);
580     }
581 
582     /**
583      * Check that the given array is sorted.
584      *
585      * @param val Values.
586      * @param dir Ordering direction.
587      * @param strict Whether the order should be strict.
588      * @param abort Whether to throw an exception if the check fails.
589      * @return {@code true} if the array is sorted.
590      * @throws MathIllegalArgumentException if the array is not sorted
591      * and {@code abort} is {@code true}.
592      * @param <T> the type of the field elements
593      * @since 1.5
594      */
595     public static <T extends CalculusFieldElement<T>>boolean checkOrder(T[] val, OrderDirection dir,
596                                                                     boolean strict, boolean abort)
597         throws MathIllegalArgumentException {
598         double previous = val[0].getReal();
599         final int max = val.length;
600 
601         int index;
602         ITEM:
603         for (index = 1; index < max; index++) {
604             switch (dir) {
605             case INCREASING:
606                 if (strict) {
607                     if (val[index].getReal() <= previous) {
608                         break ITEM;
609                     }
610                 } else {
611                     if (val[index].getReal() < previous) {
612                         break ITEM;
613                     }
614                 }
615                 break;
616             case DECREASING:
617                 if (strict) {
618                     if (val[index].getReal() >= previous) {
619                         break ITEM;
620                     }
621                 } else {
622                     if (val[index].getReal() > previous) {
623                         break ITEM;
624                     }
625                 }
626                 break;
627             default:
628                 // Should never happen.
629                 throw MathRuntimeException.createInternalError();
630             }
631 
632             previous = val[index].getReal();
633         }
634 
635         if (index == max) {
636             // Loop completed.
637             return true;
638         }
639 
640         // Loop early exit means wrong ordering.
641         if (abort) {
642             throw new MathIllegalArgumentException(dir == MathArrays.OrderDirection.INCREASING ?
643                                                     (strict ?
644                                                      LocalizedCoreFormats.NOT_STRICTLY_INCREASING_SEQUENCE :
645                                                      LocalizedCoreFormats.NOT_INCREASING_SEQUENCE) :
646                                                     (strict ?
647                                                      LocalizedCoreFormats.NOT_STRICTLY_DECREASING_SEQUENCE :
648                                                      LocalizedCoreFormats.NOT_DECREASING_SEQUENCE),
649                                                     val[index], previous, index, index - 1);
650         } else {
651             return false;
652         }
653     }
654 
655     /**
656      * Check that the given array is sorted.
657      *
658      * @param val Values.
659      * @param dir Ordering direction.
660      * @param strict Whether the order should be strict.
661      * @throws MathIllegalArgumentException if the array is not sorted.
662      * @param <T> the type of the field elements
663      * @since 1.5
664      */
665     public static <T extends CalculusFieldElement<T>> void checkOrder(T[] val, OrderDirection dir,
666                                                                   boolean strict) throws MathIllegalArgumentException {
667         checkOrder(val, dir, strict, true);
668     }
669 
670     /**
671      * Check that the given array is sorted in strictly increasing order.
672      *
673      * @param val Values.
674      * @throws MathIllegalArgumentException if the array is not sorted.
675      * @param <T> the type of the field elements
676      * @since 1.5
677      */
678     public static <T extends CalculusFieldElement<T>> void checkOrder(T[] val) throws MathIllegalArgumentException {
679         checkOrder(val, OrderDirection.INCREASING, true);
680     }
681 
682     /**
683      * Throws MathIllegalArgumentException if the input array is not rectangular.
684      *
685      * @param in array to be tested
686      * @throws NullArgumentException if input array is null
687      * @throws MathIllegalArgumentException if input array is not rectangular
688      */
689     public static void checkRectangular(final long[][] in)
690         throws MathIllegalArgumentException, NullArgumentException {
691         MathUtils.checkNotNull(in);
692         for (int i = 1; i < in.length; i++) {
693             if (in[i].length != in[0].length) {
694                 throw new MathIllegalArgumentException(
695                         LocalizedCoreFormats.DIFFERENT_ROWS_LENGTHS,
696                         in[i].length, in[0].length);
697             }
698         }
699     }
700 
701     /**
702      * Check that all entries of the input array are strictly positive.
703      *
704      * @param in Array to be tested
705      * @throws MathIllegalArgumentException if any entries of the array are not
706      * strictly positive.
707      */
708     public static void checkPositive(final double[] in)
709         throws MathIllegalArgumentException {
710         for (int i = 0; i < in.length; i++) {
711             if (in[i] <= 0) {
712                 throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_SMALL_BOUND_EXCLUDED,
713                                                        in[i], 0);
714             }
715         }
716     }
717 
718     /**
719      * Check that no entry of the input array is {@code NaN}.
720      *
721      * @param in Array to be tested.
722      * @throws MathIllegalArgumentException if an entry is {@code NaN}.
723      */
724     public static void checkNotNaN(final double[] in)
725         throws MathIllegalArgumentException {
726         for(int i = 0; i < in.length; i++) {
727             if (Double.isNaN(in[i])) {
728                 throw new MathIllegalArgumentException(LocalizedCoreFormats.NAN_ELEMENT_AT_INDEX, i);
729             }
730         }
731     }
732 
733     /**
734      * Check that all entries of the input array are &gt;= 0.
735      *
736      * @param in Array to be tested
737      * @throws MathIllegalArgumentException if any array entries are less than 0.
738      */
739     public static void checkNonNegative(final long[] in)
740         throws MathIllegalArgumentException {
741         for (int i = 0; i < in.length; i++) {
742             if (in[i] < 0) {
743                 throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_SMALL, in[i], 0);
744             }
745         }
746     }
747 
748     /**
749      * Check all entries of the input array are &gt;= 0.
750      *
751      * @param in Array to be tested
752      * @throws MathIllegalArgumentException if any array entries are less than 0.
753      */
754     public static void checkNonNegative(final long[][] in)
755         throws MathIllegalArgumentException {
756         for (int i = 0; i < in.length; i ++) {
757             for (int j = 0; j < in[i].length; j++) {
758                 if (in[i][j] < 0) {
759                     throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_SMALL, in[i][j], 0);
760                 }
761             }
762         }
763     }
764 
765     /**
766      * Returns the Cartesian norm (2-norm), handling both overflow and underflow.
767      * Translation of the minpack enorm subroutine.
768      *
769      * <p>
770      * The redistribution policy for MINPACK is available
771      * <a href="http://www.netlib.org/minpack/disclaimer">here</a>, for
772      * convenience, it is reproduced below.
773      * </p>
774      *
775      * <blockquote>
776      * <p>
777      *    Minpack Copyright Notice (1999) University of Chicago.
778      *    All rights reserved
779      * </p>
780      * <p>
781      * Redistribution and use in source and binary forms, with or without
782      * modification, are permitted provided that the following conditions
783      * are met:
784      * </p>
785      * <ol>
786      *  <li>Redistributions of source code must retain the above copyright
787      *      notice, this list of conditions and the following disclaimer.</li>
788      * <li>Redistributions in binary form must reproduce the above
789      *     copyright notice, this list of conditions and the following
790      *     disclaimer in the documentation and/or other materials provided
791      *     with the distribution.</li>
792      * <li>The end-user documentation included with the redistribution, if any,
793      *     must include the following acknowledgment:
794      *     {@code This product includes software developed by the University of
795      *           Chicago, as Operator of Argonne National Laboratory.}
796      *     Alternately, this acknowledgment may appear in the software itself,
797      *     if and wherever such third-party acknowledgments normally appear.</li>
798      * <li><strong>WARRANTY DISCLAIMER. THE SOFTWARE IS SUPPLIED "AS IS"
799      *     WITHOUT WARRANTY OF ANY KIND. THE COPYRIGHT HOLDER, THE
800      *     UNITED STATES, THE UNITED STATES DEPARTMENT OF ENERGY, AND
801      *     THEIR EMPLOYEES: (1) DISCLAIM ANY WARRANTIES, EXPRESS OR
802      *     IMPLIED, INCLUDING BUT NOT LIMITED TO ANY IMPLIED WARRANTIES
803      *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE
804      *     OR NON-INFRINGEMENT, (2) DO NOT ASSUME ANY LEGAL LIABILITY
805      *     OR RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR
806      *     USEFULNESS OF THE SOFTWARE, (3) DO NOT REPRESENT THAT USE OF
807      *     THE SOFTWARE WOULD NOT INFRINGE PRIVATELY OWNED RIGHTS, (4)
808      *     DO NOT WARRANT THAT THE SOFTWARE WILL FUNCTION
809      *     UNINTERRUPTED, THAT IT IS ERROR-FREE OR THAT ANY ERRORS WILL
810      *     BE CORRECTED.</strong></li>
811      * <li><strong>LIMITATION OF LIABILITY. IN NO EVENT WILL THE COPYRIGHT
812      *     HOLDER, THE UNITED STATES, THE UNITED STATES DEPARTMENT OF
813      *     ENERGY, OR THEIR EMPLOYEES: BE LIABLE FOR ANY INDIRECT,
814      *     INCIDENTAL, CONSEQUENTIAL, SPECIAL OR PUNITIVE DAMAGES OF
815      *     ANY KIND OR NATURE, INCLUDING BUT NOT LIMITED TO LOSS OF
816      *     PROFITS OR LOSS OF DATA, FOR ANY REASON WHATSOEVER, WHETHER
817      *     SUCH LIABILITY IS ASSERTED ON THE BASIS OF CONTRACT, TORT
818      *     (INCLUDING NEGLIGENCE OR STRICT LIABILITY), OR OTHERWISE,
819      *     EVEN IF ANY OF SAID PARTIES HAS BEEN WARNED OF THE
820      *     POSSIBILITY OF SUCH LOSS OR DAMAGES.</strong></li>
821      * </ol>
822      * </blockquote>
823      *
824      * @param v Vector of doubles.
825      * @return the 2-norm of the vector.
826      */
827     public static double safeNorm(double[] v) {
828         double rdwarf = 3.834e-20;
829         double rgiant = 1.304e+19;
830         double s1 = 0;
831         double s2 = 0;
832         double s3 = 0;
833         double x1max = 0;
834         double x3max = 0;
835         double floatn = v.length;
836         double agiant = rgiant / floatn;
837         for (int i = 0; i < v.length; i++) {
838             double xabs = FastMath.abs(v[i]);
839             if (xabs < rdwarf || xabs > agiant) {
840                 if (xabs > rdwarf) {
841                     if (xabs > x1max) {
842                         double r = x1max / xabs;
843                         s1= 1 + s1 * r * r;
844                         x1max = xabs;
845                     } else {
846                         double r = xabs / x1max;
847                         s1 += r * r;
848                     }
849                 } else {
850                     if (xabs > x3max) {
851                         double r = x3max / xabs;
852                         s3= 1 + s3 * r * r;
853                         x3max = xabs;
854                     } else {
855                         if (xabs != 0) {
856                             double r = xabs / x3max;
857                             s3 += r * r;
858                         }
859                     }
860                 }
861             } else {
862                 s2 += xabs * xabs;
863             }
864         }
865         double norm;
866         if (s1 != 0) {
867             norm = x1max * Math.sqrt(s1 + (s2 / x1max) / x1max);
868         } else {
869             if (s2 == 0) {
870                 norm = x3max * Math.sqrt(s3);
871             } else {
872                 if (s2 >= x3max) {
873                     norm = Math.sqrt(s2 * (1 + (x3max / s2) * (x3max * s3)));
874                 } else {
875                     norm = Math.sqrt(x3max * ((s2 / x3max) + (x3max * s3)));
876                 }
877             }
878         }
879         return norm;
880     }
881 
882     /**
883      * Sort an array in ascending order in place and perform the same reordering
884      * of entries on other arrays. For example, if
885      * {@code x = [3, 1, 2], y = [1, 2, 3]} and {@code z = [0, 5, 7]}, then
886      * {@code sortInPlace(x, y, z)} will update {@code x} to {@code [1, 2, 3]},
887      * {@code y} to {@code [2, 3, 1]} and {@code z} to {@code [5, 7, 0]}.
888      *
889      * @param x Array to be sorted and used as a pattern for permutation
890      * of the other arrays.
891      * @param yList Set of arrays whose permutations of entries will follow
892      * those performed on {@code x}.
893      * @throws MathIllegalArgumentException if any {@code y} is not the same
894      * size as {@code x}.
895      * @throws NullArgumentException if {@code x} or any {@code y} is null.
896      */
897     public static void sortInPlace(double[] x, double[]... yList)
898         throws MathIllegalArgumentException, NullArgumentException {
899         sortInPlace(x, OrderDirection.INCREASING, yList);
900     }
901 
902     /**
903      * Helper data structure holding a (double, integer) pair.
904      */
905     private static class PairDoubleInteger {
906         /** Key */
907         private final double key;
908         /** Value */
909         private final int value;
910 
911         /**
912          * @param key Key.
913          * @param value Value.
914          */
915         PairDoubleInteger(double key, int value) {
916             this.key = key;
917             this.value = value;
918         }
919 
920         /** @return the key. */
921         public double getKey() {
922             return key;
923         }
924 
925         /** @return the value. */
926         public int getValue() {
927             return value;
928         }
929     }
930 
931     /**
932      * Sort an array in place and perform the same reordering of entries on
933      * other arrays.  This method works the same as the other
934      * {@link #sortInPlace(double[], double[][]) sortInPlace} method, but
935      * allows the order of the sort to be provided in the {@code dir}
936      * parameter.
937      *
938      * @param x Array to be sorted and used as a pattern for permutation
939      * of the other arrays.
940      * @param dir Order direction.
941      * @param yList Set of arrays whose permutations of entries will follow
942      * those performed on {@code x}.
943      * @throws MathIllegalArgumentException if any {@code y} is not the same
944      * size as {@code x}.
945      * @throws NullArgumentException if {@code x} or any {@code y} is null
946      */
947     public static void sortInPlace(double[] x,
948                                    final OrderDirection dir,
949                                    double[]... yList)
950         throws MathIllegalArgumentException, NullArgumentException {
951 
952         // Consistency checks.
953         if (x == null) {
954             throw new NullArgumentException();
955         }
956 
957         final int yListLen = yList.length;
958         final int len = x.length;
959 
960         for (int j = 0; j < yListLen; j++) {
961             final double[] y = yList[j];
962             if (y == null) {
963                 throw new NullArgumentException();
964             }
965             if (y.length != len) {
966                 throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
967                                                        y.length, len);
968             }
969         }
970 
971         // Associate each abscissa "x[i]" with its index "i".
972         final List<PairDoubleInteger> list = new ArrayList<>(len);
973         for (int i = 0; i < len; i++) {
974             list.add(new PairDoubleInteger(x[i], i));
975         }
976 
977         // Create comparators for increasing and decreasing orders.
978         final Comparator<PairDoubleInteger> comp =
979             dir == MathArrays.OrderDirection.INCREASING ?
980             new Comparator<PairDoubleInteger>() {
981                 /** {@inheritDoc} */
982                 @Override
983                 public int compare(PairDoubleInteger o1,
984                                    PairDoubleInteger o2) {
985                     return Double.compare(o1.getKey(), o2.getKey());
986                 }
987             } :
988             new Comparator<PairDoubleInteger>() {
989                 /** {@inheritDoc} */
990                 @Override
991                 public int compare(PairDoubleInteger o1,
992                                    PairDoubleInteger o2) {
993                     return Double.compare(o2.getKey(), o1.getKey());
994                 }
995             };
996 
997         // Sort.
998         Collections.sort(list, comp);
999 
1000         // Modify the original array so that its elements are in
1001         // the prescribed order.
1002         // Retrieve indices of original locations.
1003         final int[] indices = new int[len];
1004         for (int i = 0; i < len; i++) {
1005             final PairDoubleInteger e = list.get(i);
1006             x[i] = e.getKey();
1007             indices[i] = e.getValue();
1008         }
1009 
1010         // In each of the associated arrays, move the
1011         // elements to their new location.
1012         for (int j = 0; j < yListLen; j++) {
1013             // Input array will be modified in place.
1014             final double[] yInPlace = yList[j];
1015             final double[] yOrig = yInPlace.clone();
1016 
1017             for (int i = 0; i < len; i++) {
1018                 yInPlace[i] = yOrig[indices[i]];
1019             }
1020         }
1021     }
1022 
1023     /**
1024      * Compute a linear combination accurately.
1025      * This method computes the sum of the products
1026      * <code>a<sub>i</sub> b<sub>i</sub></code> to high accuracy.
1027      * It does so by using specific multiplication and addition algorithms to
1028      * preserve accuracy and reduce cancellation effects.
1029      * <br>
1030      * It is based on the 2005 paper
1031      * <a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.2.1547">
1032      * Accurate Sum and Dot Product</a> by Takeshi Ogita, Siegfried M. Rump,
1033      * and Shin'ichi Oishi published in SIAM J. Sci. Comput.
1034      *
1035      * @param a Factors.
1036      * @param b Factors.
1037      * @return <code>&Sigma;<sub>i</sub> a<sub>i</sub> b<sub>i</sub></code>.
1038      * @throws MathIllegalArgumentException if arrays dimensions don't match
1039      */
1040     public static double linearCombination(final double[] a, final double[] b)
1041         throws MathIllegalArgumentException {
1042         checkEqualLength(a, b);
1043         final int len = a.length;
1044 
1045         if (len == 1) {
1046             // Revert to scalar multiplication.
1047             return a[0] * b[0];
1048         }
1049 
1050         final double[] prodHigh = new double[len];
1051         double prodLowSum = 0;
1052 
1053         for (int i = 0; i < len; i++) {
1054             final double ai    = a[i];
1055             final double aHigh = Double.longBitsToDouble(Double.doubleToRawLongBits(ai) & ((-1L) << 27));
1056             final double aLow  = ai - aHigh;
1057 
1058             final double bi    = b[i];
1059             final double bHigh = Double.longBitsToDouble(Double.doubleToRawLongBits(bi) & ((-1L) << 27));
1060             final double bLow  = bi - bHigh;
1061             prodHigh[i] = ai * bi;
1062             final double prodLow = aLow * bLow - (((prodHigh[i] -
1063                                                     aHigh * bHigh) -
1064                                                    aLow * bHigh) -
1065                                                   aHigh * bLow);
1066             prodLowSum += prodLow;
1067         }
1068 
1069 
1070         final double prodHighCur = prodHigh[0];
1071         double prodHighNext = prodHigh[1];
1072         double sHighPrev = prodHighCur + prodHighNext;
1073         double sPrime = sHighPrev - prodHighNext;
1074         double sLowSum = (prodHighNext - (sHighPrev - sPrime)) + (prodHighCur - sPrime);
1075 
1076         final int lenMinusOne = len - 1;
1077         for (int i = 1; i < lenMinusOne; i++) {
1078             prodHighNext = prodHigh[i + 1];
1079             final double sHighCur = sHighPrev + prodHighNext;
1080             sPrime = sHighCur - prodHighNext;
1081             sLowSum += (prodHighNext - (sHighCur - sPrime)) + (sHighPrev - sPrime);
1082             sHighPrev = sHighCur;
1083         }
1084 
1085         double result = sHighPrev + (prodLowSum + sLowSum);
1086 
1087         if (Double.isNaN(result) || result == 0.0) {
1088             // either we have split infinite numbers or some coefficients were NaNs or signed zeros,
1089             // just rely on the naive implementation and let IEEE754 handle this
1090             // we do this for zeros too as we want to preserve the sign of zero (see issue #76)
1091             result = a[0] * b[0];
1092             for (int i = 1; i < len; ++i) {
1093                 result += a[i] * b[i];
1094             }
1095         }
1096 
1097         return result;
1098     }
1099 
1100     /**
1101      * Compute a linear combination accurately.
1102      * <p>
1103      * This method computes a<sub>1</sub>&times;b<sub>1</sub> +
1104      * a<sub>2</sub>&times;b<sub>2</sub> to high accuracy. It does
1105      * so by using specific multiplication and addition algorithms to
1106      * preserve accuracy and reduce cancellation effects. It is based
1107      * on the 2005 paper <a
1108      * href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.2.1547">
1109      * Accurate Sum and Dot Product</a> by Takeshi Ogita,
1110      * Siegfried M. Rump, and Shin'ichi Oishi published in SIAM J. Sci. Comput.
1111      * </p>
1112      * @param a1 first factor of the first term
1113      * @param b1 second factor of the first term
1114      * @param a2 first factor of the second term
1115      * @param b2 second factor of the second term
1116      * @return a<sub>1</sub>&times;b<sub>1</sub> +
1117      * a<sub>2</sub>&times;b<sub>2</sub>
1118      * @see #linearCombination(double, double, double, double, double, double)
1119      * @see #linearCombination(double, double, double, double, double, double, double, double)
1120      */
1121     public static double linearCombination(final double a1, final double b1,
1122                                            final double a2, final double b2) {
1123 
1124         // the code below is split in many additions/subtractions that may
1125         // appear redundant. However, they should NOT be simplified, as they
1126         // use IEEE754 floating point arithmetic rounding properties.
1127         // The variable naming conventions are that xyzHigh contains the most significant
1128         // bits of xyz and xyzLow contains its least significant bits. So theoretically
1129         // xyz is the sum xyzHigh + xyzLow, but in many cases below, this sum cannot
1130         // be represented in only one double precision number so we preserve two numbers
1131         // to hold it as long as we can, combining the high and low order bits together
1132         // only at the end, after cancellation may have occurred on high order bits
1133 
1134         // split a1 and b1 as one 26 bits number and one 27 bits number
1135         final double a1High     = Double.longBitsToDouble(Double.doubleToRawLongBits(a1) & ((-1L) << 27));
1136         final double a1Low      = a1 - a1High;
1137         final double b1High     = Double.longBitsToDouble(Double.doubleToRawLongBits(b1) & ((-1L) << 27));
1138         final double b1Low      = b1 - b1High;
1139 
1140         // accurate multiplication a1 * b1
1141         final double prod1High  = a1 * b1;
1142         final double prod1Low   = a1Low * b1Low - (((prod1High - a1High * b1High) - a1Low * b1High) - a1High * b1Low);
1143 
1144         // split a2 and b2 as one 26 bits number and one 27 bits number
1145         final double a2High     = Double.longBitsToDouble(Double.doubleToRawLongBits(a2) & ((-1L) << 27));
1146         final double a2Low      = a2 - a2High;
1147         final double b2High     = Double.longBitsToDouble(Double.doubleToRawLongBits(b2) & ((-1L) << 27));
1148         final double b2Low      = b2 - b2High;
1149 
1150         // accurate multiplication a2 * b2
1151         final double prod2High  = a2 * b2;
1152         final double prod2Low   = a2Low * b2Low - (((prod2High - a2High * b2High) - a2Low * b2High) - a2High * b2Low);
1153 
1154         // accurate addition a1 * b1 + a2 * b2
1155         final double s12High    = prod1High + prod2High;
1156         final double s12Prime   = s12High - prod2High;
1157         final double s12Low     = (prod2High - (s12High - s12Prime)) + (prod1High - s12Prime);
1158 
1159         // final rounding, s12 may have suffered many cancellations, we try
1160         // to recover some bits from the extra words we have saved up to now
1161         double result = s12High + (prod1Low + prod2Low + s12Low);
1162 
1163         if (Double.isNaN(result) || result == 0.0) {
1164             // either we have split infinite numbers or some coefficients were NaNs or signed zeros,
1165             // just rely on the naive implementation and let IEEE754 handle this
1166             // we do this for zeros too as we want to preserve the sign of zero (see issue #76)
1167             result = a1 * b1 + a2 * b2;
1168         }
1169 
1170         return result;
1171     }
1172 
1173     /**
1174      * Compute a linear combination accurately.
1175      * <p>
1176      * This method computes a<sub>1</sub>&times;b<sub>1</sub> +
1177      * a<sub>2</sub>&times;b<sub>2</sub> + a<sub>3</sub>&times;b<sub>3</sub>
1178      * to high accuracy. It does so by using specific multiplication and
1179      * addition algorithms to preserve accuracy and reduce cancellation effects.
1180      * It is based on the 2005 paper <a
1181      * href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.2.1547">
1182      * Accurate Sum and Dot Product</a> by Takeshi Ogita,
1183      * Siegfried M. Rump, and Shin'ichi Oishi published in SIAM J. Sci. Comput.
1184      * </p>
1185      * @param a1 first factor of the first term
1186      * @param b1 second factor of the first term
1187      * @param a2 first factor of the second term
1188      * @param b2 second factor of the second term
1189      * @param a3 first factor of the third term
1190      * @param b3 second factor of the third term
1191      * @return a<sub>1</sub>&times;b<sub>1</sub> +
1192      * a<sub>2</sub>&times;b<sub>2</sub> + a<sub>3</sub>&times;b<sub>3</sub>
1193      * @see #linearCombination(double, double, double, double)
1194      * @see #linearCombination(double, double, double, double, double, double, double, double)
1195      */
1196     public static double linearCombination(final double a1, final double b1,
1197                                            final double a2, final double b2,
1198                                            final double a3, final double b3) {
1199 
1200         // the code below is split in many additions/subtractions that may
1201         // appear redundant. However, they should NOT be simplified, as they
1202         // do use IEEE754 floating point arithmetic rounding properties.
1203         // The variables naming conventions are that xyzHigh contains the most significant
1204         // bits of xyz and xyzLow contains its least significant bits. So theoretically
1205         // xyz is the sum xyzHigh + xyzLow, but in many cases below, this sum cannot
1206         // be represented in only one double precision number so we preserve two numbers
1207         // to hold it as long as we can, combining the high and low order bits together
1208         // only at the end, after cancellation may have occurred on high order bits
1209 
1210         // split a1 and b1 as one 26 bits number and one 27 bits number
1211         final double a1High     = Double.longBitsToDouble(Double.doubleToRawLongBits(a1) & ((-1L) << 27));
1212         final double a1Low      = a1 - a1High;
1213         final double b1High     = Double.longBitsToDouble(Double.doubleToRawLongBits(b1) & ((-1L) << 27));
1214         final double b1Low      = b1 - b1High;
1215 
1216         // accurate multiplication a1 * b1
1217         final double prod1High  = a1 * b1;
1218         final double prod1Low   = a1Low * b1Low - (((prod1High - a1High * b1High) - a1Low * b1High) - a1High * b1Low);
1219 
1220         // split a2 and b2 as one 26 bits number and one 27 bits number
1221         final double a2High     = Double.longBitsToDouble(Double.doubleToRawLongBits(a2) & ((-1L) << 27));
1222         final double a2Low      = a2 - a2High;
1223         final double b2High     = Double.longBitsToDouble(Double.doubleToRawLongBits(b2) & ((-1L) << 27));
1224         final double b2Low      = b2 - b2High;
1225 
1226         // accurate multiplication a2 * b2
1227         final double prod2High  = a2 * b2;
1228         final double prod2Low   = a2Low * b2Low - (((prod2High - a2High * b2High) - a2Low * b2High) - a2High * b2Low);
1229 
1230         // split a3 and b3 as one 26 bits number and one 27 bits number
1231         final double a3High     = Double.longBitsToDouble(Double.doubleToRawLongBits(a3) & ((-1L) << 27));
1232         final double a3Low      = a3 - a3High;
1233         final double b3High     = Double.longBitsToDouble(Double.doubleToRawLongBits(b3) & ((-1L) << 27));
1234         final double b3Low      = b3 - b3High;
1235 
1236         // accurate multiplication a3 * b3
1237         final double prod3High  = a3 * b3;
1238         final double prod3Low   = a3Low * b3Low - (((prod3High - a3High * b3High) - a3Low * b3High) - a3High * b3Low);
1239 
1240         // accurate addition a1 * b1 + a2 * b2
1241         final double s12High    = prod1High + prod2High;
1242         final double s12Prime   = s12High - prod2High;
1243         final double s12Low     = (prod2High - (s12High - s12Prime)) + (prod1High - s12Prime);
1244 
1245         // accurate addition a1 * b1 + a2 * b2 + a3 * b3
1246         final double s123High   = s12High + prod3High;
1247         final double s123Prime  = s123High - prod3High;
1248         final double s123Low    = (prod3High - (s123High - s123Prime)) + (s12High - s123Prime);
1249 
1250         // final rounding, s123 may have suffered many cancellations, we try
1251         // to recover some bits from the extra words we have saved up to now
1252         double result = s123High + (prod1Low + prod2Low + prod3Low + s12Low + s123Low);
1253 
1254         if (Double.isNaN(result) || result == 0.0) {
1255             // either we have split infinite numbers or some coefficients were NaNs or signed zeros,
1256             // just rely on the naive implementation and let IEEE754 handle this
1257             // we do this for zeros too as we want to preserve the sign of zero (see issue #76)
1258             result = a1 * b1 + a2 * b2 + a3 * b3;
1259         }
1260 
1261         return result;
1262     }
1263 
1264     /**
1265      * Compute a linear combination accurately.
1266      * <p>
1267      * This method computes a<sub>1</sub>&times;b<sub>1</sub> +
1268      * a<sub>2</sub>&times;b<sub>2</sub> + a<sub>3</sub>&times;b<sub>3</sub> +
1269      * a<sub>4</sub>&times;b<sub>4</sub>
1270      * to high accuracy. It does so by using specific multiplication and
1271      * addition algorithms to preserve accuracy and reduce cancellation effects.
1272      * It is based on the 2005 paper <a
1273      * href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.2.1547">
1274      * Accurate Sum and Dot Product</a> by Takeshi Ogita,
1275      * Siegfried M. Rump, and Shin'ichi Oishi published in SIAM J. Sci. Comput.
1276      * </p>
1277      * @param a1 first factor of the first term
1278      * @param b1 second factor of the first term
1279      * @param a2 first factor of the second term
1280      * @param b2 second factor of the second term
1281      * @param a3 first factor of the third term
1282      * @param b3 second factor of the third term
1283      * @param a4 first factor of the third term
1284      * @param b4 second factor of the third term
1285      * @return a<sub>1</sub>&times;b<sub>1</sub> +
1286      * a<sub>2</sub>&times;b<sub>2</sub> + a<sub>3</sub>&times;b<sub>3</sub> +
1287      * a<sub>4</sub>&times;b<sub>4</sub>
1288      * @see #linearCombination(double, double, double, double)
1289      * @see #linearCombination(double, double, double, double, double, double)
1290      */
1291     public static double linearCombination(final double a1, final double b1,
1292                                            final double a2, final double b2,
1293                                            final double a3, final double b3,
1294                                            final double a4, final double b4) {
1295 
1296         // the code below is split in many additions/subtractions that may
1297         // appear redundant. However, they should NOT be simplified, as they
1298         // do use IEEE754 floating point arithmetic rounding properties.
1299         // The variables naming conventions are that xyzHigh contains the most significant
1300         // bits of xyz and xyzLow contains its least significant bits. So theoretically
1301         // xyz is the sum xyzHigh + xyzLow, but in many cases below, this sum cannot
1302         // be represented in only one double precision number so we preserve two numbers
1303         // to hold it as long as we can, combining the high and low order bits together
1304         // only at the end, after cancellation may have occurred on high order bits
1305 
1306         // split a1 and b1 as one 26 bits number and one 27 bits number
1307         final double a1High     = Double.longBitsToDouble(Double.doubleToRawLongBits(a1) & ((-1L) << 27));
1308         final double a1Low      = a1 - a1High;
1309         final double b1High     = Double.longBitsToDouble(Double.doubleToRawLongBits(b1) & ((-1L) << 27));
1310         final double b1Low      = b1 - b1High;
1311 
1312         // accurate multiplication a1 * b1
1313         final double prod1High  = a1 * b1;
1314         final double prod1Low   = a1Low * b1Low - (((prod1High - a1High * b1High) - a1Low * b1High) - a1High * b1Low);
1315 
1316         // split a2 and b2 as one 26 bits number and one 27 bits number
1317         final double a2High     = Double.longBitsToDouble(Double.doubleToRawLongBits(a2) & ((-1L) << 27));
1318         final double a2Low      = a2 - a2High;
1319         final double b2High     = Double.longBitsToDouble(Double.doubleToRawLongBits(b2) & ((-1L) << 27));
1320         final double b2Low      = b2 - b2High;
1321 
1322         // accurate multiplication a2 * b2
1323         final double prod2High  = a2 * b2;
1324         final double prod2Low   = a2Low * b2Low - (((prod2High - a2High * b2High) - a2Low * b2High) - a2High * b2Low);
1325 
1326         // split a3 and b3 as one 26 bits number and one 27 bits number
1327         final double a3High     = Double.longBitsToDouble(Double.doubleToRawLongBits(a3) & ((-1L) << 27));
1328         final double a3Low      = a3 - a3High;
1329         final double b3High     = Double.longBitsToDouble(Double.doubleToRawLongBits(b3) & ((-1L) << 27));
1330         final double b3Low      = b3 - b3High;
1331 
1332         // accurate multiplication a3 * b3
1333         final double prod3High  = a3 * b3;
1334         final double prod3Low   = a3Low * b3Low - (((prod3High - a3High * b3High) - a3Low * b3High) - a3High * b3Low);
1335 
1336         // split a4 and b4 as one 26 bits number and one 27 bits number
1337         final double a4High     = Double.longBitsToDouble(Double.doubleToRawLongBits(a4) & ((-1L) << 27));
1338         final double a4Low      = a4 - a4High;
1339         final double b4High     = Double.longBitsToDouble(Double.doubleToRawLongBits(b4) & ((-1L) << 27));
1340         final double b4Low      = b4 - b4High;
1341 
1342         // accurate multiplication a4 * b4
1343         final double prod4High  = a4 * b4;
1344         final double prod4Low   = a4Low * b4Low - (((prod4High - a4High * b4High) - a4Low * b4High) - a4High * b4Low);
1345 
1346         // accurate addition a1 * b1 + a2 * b2
1347         final double s12High    = prod1High + prod2High;
1348         final double s12Prime   = s12High - prod2High;
1349         final double s12Low     = (prod2High - (s12High - s12Prime)) + (prod1High - s12Prime);
1350 
1351         // accurate addition a1 * b1 + a2 * b2 + a3 * b3
1352         final double s123High   = s12High + prod3High;
1353         final double s123Prime  = s123High - prod3High;
1354         final double s123Low    = (prod3High - (s123High - s123Prime)) + (s12High - s123Prime);
1355 
1356         // accurate addition a1 * b1 + a2 * b2 + a3 * b3 + a4 * b4
1357         final double s1234High  = s123High + prod4High;
1358         final double s1234Prime = s1234High - prod4High;
1359         final double s1234Low   = (prod4High - (s1234High - s1234Prime)) + (s123High - s1234Prime);
1360 
1361         // final rounding, s1234 may have suffered many cancellations, we try
1362         // to recover some bits from the extra words we have saved up to now
1363         double result = s1234High + (prod1Low + prod2Low + prod3Low + prod4Low + s12Low + s123Low + s1234Low);
1364 
1365         if (Double.isNaN(result) || result == 0.0) {
1366             // either we have split infinite numbers or some coefficients were NaNs or signed zeros,
1367             // just rely on the naive implementation and let IEEE754 handle this
1368             // we do this for zeros too as we want to preserve the sign of zero (see issue #76)
1369             result = a1 * b1 + a2 * b2 + a3 * b3 + a4 * b4;
1370         }
1371 
1372         return result;
1373     }
1374 
1375     /**
1376      * Returns true iff both arguments are null or have same dimensions and all
1377      * their elements are equal as defined by
1378      * {@link Precision#equals(float,float)}.
1379      *
1380      * @param x first array
1381      * @param y second array
1382      * @return true if the values are both null or have same dimension
1383      * and equal elements.
1384      */
1385     public static boolean equals(float[] x, float[] y) {
1386         if ((x == null) || (y == null)) {
1387             return !((x == null) ^ (y == null));
1388         }
1389         if (x.length != y.length) {
1390             return false;
1391         }
1392         for (int i = 0; i < x.length; ++i) {
1393             if (!Precision.equals(x[i], y[i])) {
1394                 return false;
1395             }
1396         }
1397         return true;
1398     }
1399 
1400     /**
1401      * Returns true iff both arguments are null or have same dimensions and all
1402      * their elements are equal as defined by
1403      * {@link Precision#equalsIncludingNaN(double,double) this method}.
1404      *
1405      * @param x first array
1406      * @param y second array
1407      * @return true if the values are both null or have same dimension and
1408      * equal elements
1409      */
1410     public static boolean equalsIncludingNaN(float[] x, float[] y) {
1411         if ((x == null) || (y == null)) {
1412             return !((x == null) ^ (y == null));
1413         }
1414         if (x.length != y.length) {
1415             return false;
1416         }
1417         for (int i = 0; i < x.length; ++i) {
1418             if (!Precision.equalsIncludingNaN(x[i], y[i])) {
1419                 return false;
1420             }
1421         }
1422         return true;
1423     }
1424 
1425     /**
1426      * Returns {@code true} iff both arguments are {@code null} or have same
1427      * dimensions and all their elements are equal as defined by
1428      * {@link Precision#equals(double,double)}.
1429      *
1430      * @param x First array.
1431      * @param y Second array.
1432      * @return {@code true} if the values are both {@code null} or have same
1433      * dimension and equal elements.
1434      */
1435     public static boolean equals(double[] x, double[] y) {
1436         if ((x == null) || (y == null)) {
1437             return !((x == null) ^ (y == null));
1438         }
1439         if (x.length != y.length) {
1440             return false;
1441         }
1442         for (int i = 0; i < x.length; ++i) {
1443             if (!Precision.equals(x[i], y[i])) {
1444                 return false;
1445             }
1446         }
1447         return true;
1448     }
1449 
1450     /**
1451      * Returns {@code true} iff both arguments are {@code null} or have same
1452      * dimensions and all their elements are equal as defined by
1453      * {@link Precision#equalsIncludingNaN(double,double) this method}.
1454      *
1455      * @param x First array.
1456      * @param y Second array.
1457      * @return {@code true} if the values are both {@code null} or have same
1458      * dimension and equal elements.
1459      */
1460     public static boolean equalsIncludingNaN(double[] x, double[] y) {
1461         if ((x == null) || (y == null)) {
1462             return !((x == null) ^ (y == null));
1463         }
1464         if (x.length != y.length) {
1465             return false;
1466         }
1467         for (int i = 0; i < x.length; ++i) {
1468             if (!Precision.equalsIncludingNaN(x[i], y[i])) {
1469                 return false;
1470             }
1471         }
1472         return true;
1473     }
1474 
1475     /**
1476      * Returns {@code true} if both arguments are {@code null} or have same
1477      * dimensions and all their elements are equals.
1478      *
1479      * @param x First array.
1480      * @param y Second array.
1481      * @return {@code true} if the values are both {@code null} or have same
1482      * dimension and equal elements.
1483      */
1484     public static boolean equals(long[] x, long[] y) {
1485         if ((x == null) || (y == null)) {
1486             return !((x == null) ^ (y == null));
1487         }
1488         if (x.length != y.length) {
1489             return false;
1490         }
1491         for (int i = 0; i < x.length; ++i) {
1492             if (x[i] != y[i]) {
1493                 return false;
1494             }
1495         }
1496         return true;
1497     }
1498 
1499     /**
1500      * Returns {@code true} if both arguments are {@code null} or have same
1501      * dimensions and all their elements are equals.
1502      *
1503      * @param x First array.
1504      * @param y Second array.
1505      * @return {@code true} if the values are both {@code null} or have same
1506      * dimension and equal elements.
1507      */
1508     public static boolean equals(int[] x, int[] y) {
1509         if ((x == null) || (y == null)) {
1510             return !((x == null) ^ (y == null));
1511         }
1512         if (x.length != y.length) {
1513             return false;
1514         }
1515         for (int i = 0; i < x.length; ++i) {
1516             if (x[i] != y[i]) {
1517                 return false;
1518             }
1519         }
1520         return true;
1521     }
1522 
1523     /**
1524      * Returns {@code true} if both arguments are {@code null} or have same
1525      * dimensions and all their elements are equals.
1526      *
1527      * @param x First array.
1528      * @param y Second array.
1529      * @return {@code true} if the values are both {@code null} or have same
1530      * dimension and equal elements.
1531      */
1532     public static boolean equals(byte[] x, byte[] y) {
1533         if ((x == null) || (y == null)) {
1534             return !((x == null) ^ (y == null));
1535         }
1536         if (x.length != y.length) {
1537             return false;
1538         }
1539         for (int i = 0; i < x.length; ++i) {
1540             if (x[i] != y[i]) {
1541                 return false;
1542             }
1543         }
1544         return true;
1545     }
1546 
1547     /**
1548      * Returns {@code true} if both arguments are {@code null} or have same
1549      * dimensions and all their elements are equals.
1550      *
1551      * @param x First array.
1552      * @param y Second array.
1553      * @return {@code true} if the values are both {@code null} or have same
1554      * dimension and equal elements.
1555      */
1556     public static boolean equals(short[] x, short[] y) {
1557         if ((x == null) || (y == null)) {
1558             return !((x == null) ^ (y == null));
1559         }
1560         if (x.length != y.length) {
1561             return false;
1562         }
1563         for (int i = 0; i < x.length; ++i) {
1564             if (x[i] != y[i]) {
1565                 return false;
1566             }
1567         }
1568         return true;
1569     }
1570 
1571     /**
1572      * Normalizes an array to make it sum to a specified value.
1573      * Returns the result of the transformation
1574      * <pre>
1575      *    x ↦ x * normalizedSum / sum
1576      * </pre>
1577      * applied to each non-NaN element x of the input array, where sum is the
1578      * sum of the non-NaN entries in the input array.
1579      * <p>
1580      * Throws IllegalArgumentException if {@code normalizedSum} is infinite
1581      * or NaN and ArithmeticException if the input array contains any infinite elements
1582      * or sums to 0.
1583      * <p>
1584      * Ignores (i.e., copies unchanged to the output array) NaNs in the input array.
1585      * The input array is unchanged by this method.
1586      *
1587      * @param values Input array to be normalized
1588      * @param normalizedSum Target sum for the normalized array
1589      * @return the normalized array
1590      * @throws MathRuntimeException if the input array contains infinite
1591      * elements or sums to zero
1592      * @throws MathIllegalArgumentException if the target sum is infinite or {@code NaN}
1593      */
1594     public static double[] normalizeArray(double[] values, double normalizedSum)
1595         throws MathIllegalArgumentException, MathRuntimeException {
1596         if (Double.isInfinite(normalizedSum)) {
1597             throw new MathIllegalArgumentException(LocalizedCoreFormats.NORMALIZE_INFINITE);
1598         }
1599         if (Double.isNaN(normalizedSum)) {
1600             throw new MathIllegalArgumentException(LocalizedCoreFormats.NORMALIZE_NAN);
1601         }
1602         double sum = 0d;
1603         final int len = values.length;
1604         double[] out = new double[len];
1605         for (int i = 0; i < len; i++) {
1606             if (Double.isInfinite(values[i])) {
1607                 throw new MathIllegalArgumentException(LocalizedCoreFormats.INFINITE_ARRAY_ELEMENT, values[i], i);
1608             }
1609             if (!Double.isNaN(values[i])) {
1610                 sum += values[i];
1611             }
1612         }
1613         if (sum == 0) {
1614             throw new MathRuntimeException(LocalizedCoreFormats.ARRAY_SUMS_TO_ZERO);
1615         }
1616         for (int i = 0; i < len; i++) {
1617             if (Double.isNaN(values[i])) {
1618                 out[i] = Double.NaN;
1619             } else {
1620                 out[i] = values[i] * normalizedSum / sum;
1621             }
1622         }
1623         return out;
1624     }
1625 
1626     /** Build an array of elements.
1627      * <p>
1628      * Arrays are filled with {@code field.getZero()}
1629      *
1630      * @param <T> the type of the field elements
1631      * @param field field to which array elements belong
1632      * @param length of the array
1633      * @return a new array
1634      */
1635     public static <T extends FieldElement<T>> T[] buildArray(final Field<T> field, final int length) {
1636         @SuppressWarnings("unchecked") // OK because field must be correct class
1637         T[] array = (T[]) Array.newInstance(field.getRuntimeClass(), length);
1638         Arrays.fill(array, field.getZero());
1639         return array;
1640     }
1641 
1642     /** Build a double dimension array of elements.
1643      * <p>
1644      * Arrays are filled with {@code field.getZero()}
1645      *
1646      * @param <T> the type of the field elements
1647      * @param field field to which array elements belong
1648      * @param rows number of rows in the array
1649      * @param columns number of columns (may be negative to build partial
1650      * arrays in the same way {@code new Field[rows][]} works)
1651      * @return a new array
1652      */
1653     @SuppressWarnings("unchecked")
1654     public static <T extends FieldElement<T>> T[][] buildArray(final Field<T> field, final int rows, final int columns) {
1655         final T[][] array;
1656         if (columns < 0) {
1657             T[] dummyRow = buildArray(field, 0);
1658             array = (T[][]) Array.newInstance(dummyRow.getClass(), rows);
1659         } else {
1660             array = (T[][]) Array.newInstance(field.getRuntimeClass(),
1661                                               new int[] {
1662                                                   rows, columns
1663                                               });
1664             for (int i = 0; i < rows; ++i) {
1665                 Arrays.fill(array[i], field.getZero());
1666             }
1667         }
1668         return array;
1669     }
1670 
1671     /** Build a triple dimension array of elements.
1672      * <p>
1673      * Arrays are filled with {@code field.getZero()}
1674      *
1675      * @param <T> the type of the field elements
1676      * @param field field to which array elements belong
1677      * @param l1 number of elements along first dimension
1678      * @param l2 number of elements along second dimension
1679      * @param l3 number of elements along third dimension (may be negative to build partial
1680      * arrays in the same way {@code new Field[l1][l2][]} works)
1681      * @return a new array
1682      * @since 1.4
1683      */
1684     @SuppressWarnings("unchecked")
1685     public static <T extends FieldElement<T>> T[][][] buildArray(final Field<T> field, final int l1, final int l2, final int l3) {
1686         final T[][][] array;
1687         if (l3 < 0) {
1688             T[] dummyRow = buildArray(field, 0);
1689             array = (T[][][]) Array.newInstance(dummyRow.getClass(), l1, l2);
1690         } else {
1691             array = (T[][][]) Array.newInstance(field.getRuntimeClass(),
1692                                                 new int[] {
1693                                                   l1, l2, l3
1694                                                 });
1695             for (int i = 0; i < l1; ++i) {
1696                 for (int j = 0; j < l2; ++j) {
1697                     Arrays.fill(array[i][j], field.getZero());
1698                 }
1699             }
1700         }
1701         return array;
1702     }
1703 
1704     /**
1705      * Calculates the <a href="http://en.wikipedia.org/wiki/Convolution">
1706      * convolution</a> between two sequences.
1707      * <p>
1708      * The solution is obtained via straightforward computation of the
1709      * convolution sum (and not via FFT). Whenever the computation needs
1710      * an element that would be located at an index outside the input arrays,
1711      * the value is assumed to be zero.
1712      *
1713      * @param x First sequence.
1714      * Typically, this sequence will represent an input signal to a system.
1715      * @param h Second sequence.
1716      * Typically, this sequence will represent the impulse response of the system.
1717      * @return the convolution of {@code x} and {@code h}.
1718      * This array's length will be {@code x.length + h.length - 1}.
1719      * @throws NullArgumentException if either {@code x} or {@code h} is {@code null}.
1720      * @throws MathIllegalArgumentException if either {@code x} or {@code h} is empty.
1721      */
1722     public static double[] convolve(double[] x, double[] h)
1723         throws MathIllegalArgumentException, NullArgumentException {
1724         MathUtils.checkNotNull(x);
1725         MathUtils.checkNotNull(h);
1726 
1727         final int xLen = x.length;
1728         final int hLen = h.length;
1729 
1730         if (xLen == 0 || hLen == 0) {
1731             throw new MathIllegalArgumentException(LocalizedCoreFormats.NO_DATA);
1732         }
1733 
1734         // initialize the output array
1735         final int totalLength = xLen + hLen - 1;
1736         final double[] y = new double[totalLength];
1737 
1738         // straightforward implementation of the convolution sum
1739         for (int n = 0; n < totalLength; n++) {
1740             double yn = 0;
1741             int k = FastMath.max(0, n + 1 - xLen);
1742             int j = n - k;
1743             while (k < hLen && j >= 0) {
1744                 yn += x[j--] * h[k++];
1745             }
1746             y[n] = yn;
1747         }
1748 
1749         return y;
1750     }
1751 
1752     /**
1753      * Specification for indicating that some operation applies
1754      * before or after a given index.
1755      */
1756     public enum Position {
1757         /** Designates the beginning of the array (near index 0). */
1758         HEAD,
1759         /** Designates the end of the array. */
1760         TAIL
1761     }
1762 
1763     /**
1764      * Shuffle the entries of the given array.
1765      * The {@code start} and {@code pos} parameters select which portion
1766      * of the array is randomized and which is left untouched.
1767      *
1768      * @see #shuffle(int[],int,Position,RandomGenerator)
1769      *
1770      * @param list Array whose entries will be shuffled (in-place).
1771      * @param start Index at which shuffling begins.
1772      * @param pos Shuffling is performed for index positions between
1773      * {@code start} and either the end (if {@link Position#TAIL})
1774      * or the beginning (if {@link Position#HEAD}) of the array.
1775      */
1776     public static void shuffle(int[] list,
1777                                int start,
1778                                Position pos) {
1779         shuffle(list, start, pos, new Well19937c());
1780     }
1781 
1782     /**
1783      * Shuffle the entries of the given array, using the
1784      * <a href="https://en.wikipedia.org/wiki/Fisher-Yates_shuffle#The_modern_algorithm">
1785      * Fisher–Yates</a> algorithm.
1786      * The {@code start} and {@code pos} parameters select which portion
1787      * of the array is randomized and which is left untouched.
1788      *
1789      * @param list Array whose entries will be shuffled (in-place).
1790      * @param start Index at which shuffling begins.
1791      * @param pos Shuffling is performed for index positions between
1792      * {@code start} and either the end (if {@link Position#TAIL})
1793      * or the beginning (if {@link Position#HEAD}) of the array.
1794      * @param rng Random number generator.
1795      */
1796     public static void shuffle(int[] list,
1797                                int start,
1798                                Position pos,
1799                                RandomGenerator rng) {
1800         switch (pos) {
1801         case TAIL:
1802             for (int i = list.length - 1; i > start; i--) {
1803                 final int target = start + rng.nextInt(i - start + 1);
1804                 final int temp = list[target];
1805                 list[target] = list[i];
1806                 list[i] = temp;
1807             }
1808             break;
1809 
1810         case HEAD:
1811             for (int i = 0; i < start; i++) {
1812                 final int target = i + rng.nextInt(start - i + 1);
1813                 final int temp = list[target];
1814                 list[target] = list[i];
1815                 list[i] = temp;
1816             }
1817             break;
1818 
1819         default:
1820             throw MathRuntimeException.createInternalError(); // Should never happen.
1821         }
1822     }
1823 
1824     /**
1825      * Shuffle the entries of the given array.
1826      *
1827      * @see #shuffle(int[],int,Position,RandomGenerator)
1828      *
1829      * @param list Array whose entries will be shuffled (in-place).
1830      * @param rng Random number generator.
1831      */
1832     public static void shuffle(int[] list,
1833                                RandomGenerator rng) {
1834         shuffle(list, 0, Position.TAIL, rng);
1835     }
1836 
1837     /**
1838      * Shuffle the entries of the given array.
1839      *
1840      * @see #shuffle(int[],int,Position,RandomGenerator)
1841      *
1842      * @param list Array whose entries will be shuffled (in-place).
1843      */
1844     public static void shuffle(int[] list) {
1845         shuffle(list, new Well19937c());
1846     }
1847 
1848     /**
1849      * Returns an array representing the natural number {@code n}.
1850      *
1851      * @param n Natural number.
1852      * @return an array whose entries are the numbers 0, 1, ..., {@code n}-1.
1853      * If {@code n == 0}, the returned array is empty.
1854      */
1855     public static int[] natural(int n) {
1856         return sequence(n, 0, 1);
1857     }
1858 
1859     /**
1860      * Returns an array of {@code size} integers starting at {@code start},
1861      * skipping {@code stride} numbers.
1862      *
1863      * @param size Natural number.
1864      * @param start Natural number.
1865      * @param stride Natural number.
1866      * @return an array whose entries are the numbers
1867      * {@code start, start + stride, ..., start + (size - 1) * stride}.
1868      * If {@code size == 0}, the returned array is empty.
1869      */
1870     public static int[] sequence(int size,
1871                                  int start,
1872                                  int stride) {
1873         final int[] a = new int[size];
1874         for (int i = 0; i < size; i++) {
1875             a[i] = start + i * stride;
1876         }
1877         return a;
1878     }
1879 
1880     /**
1881      * This method is used
1882      * to verify that the input parameters designate a subarray of positive length.
1883      * <ul>
1884      * <li>returns {@code true} iff the parameters designate a subarray of
1885      * positive length</li>
1886      * <li>throws {@code MathIllegalArgumentException} if the array is null or
1887      * or the indices are invalid</li>
1888      * <li>returns {@code false} if the array is non-null, but
1889      * {@code length} is 0.</li>
1890      * </ul>
1891      *
1892      * @param values the input array
1893      * @param begin index of the first array element to include
1894      * @param length the number of elements to include
1895      * @return true if the parameters are valid and designate a subarray of positive length
1896      * @throws MathIllegalArgumentException if the indices are invalid or the array is null
1897      */
1898     public static boolean verifyValues(final double[] values, final int begin, final int length)
1899             throws MathIllegalArgumentException {
1900         return verifyValues(values, begin, length, false);
1901     }
1902 
1903     /**
1904      * This method is used
1905      * to verify that the input parameters designate a subarray of positive length.
1906      * <ul>
1907      * <li>returns {@code true} iff the parameters designate a subarray of
1908      * non-negative length</li>
1909      * <li>throws {@code IllegalArgumentException} if the array is null or
1910      * or the indices are invalid</li>
1911      * <li>returns {@code false} if the array is non-null, but
1912      * {@code length} is 0 unless {@code allowEmpty} is {@code true}</li>
1913      * </ul>
1914      *
1915      * @param values the input array
1916      * @param begin index of the first array element to include
1917      * @param length the number of elements to include
1918      * @param allowEmpty if <code>true</code> then zero length arrays are allowed
1919      * @return true if the parameters are valid
1920      * @throws MathIllegalArgumentException if the indices are invalid or the array is null
1921      */
1922     public static boolean verifyValues(final double[] values, final int begin,
1923             final int length, final boolean allowEmpty) throws MathIllegalArgumentException {
1924 
1925         MathUtils.checkNotNull(values, LocalizedCoreFormats.INPUT_ARRAY);
1926 
1927         if (begin < 0) {
1928             throw new MathIllegalArgumentException(LocalizedCoreFormats.START_POSITION, Integer.valueOf(begin));
1929         }
1930 
1931         if (length < 0) {
1932             throw new MathIllegalArgumentException(LocalizedCoreFormats.LENGTH, Integer.valueOf(length));
1933         }
1934 
1935         if (begin + length > values.length) {
1936             throw new MathIllegalArgumentException(LocalizedCoreFormats.SUBARRAY_ENDS_AFTER_ARRAY_END,
1937                     Integer.valueOf(begin + length), Integer.valueOf(values.length), true);
1938         }
1939 
1940         if (length == 0 && !allowEmpty) {
1941             return false;
1942         }
1943 
1944         return true;
1945     }
1946 
1947     /**
1948      * This method is used
1949      * to verify that the begin and length parameters designate a subarray of positive length
1950      * and the weights are all non-negative, non-NaN, finite, and not all zero.
1951      * <ul>
1952      * <li>returns {@code true} iff the parameters designate a subarray of
1953      * positive length and the weights array contains legitimate values.</li>
1954      * <li>throws {@code IllegalArgumentException} if any of the following are true:
1955      * <ul><li>the values array is null</li>
1956      *     <li>the weights array is null</li>
1957      *     <li>the weights array does not have the same length as the values array</li>
1958      *     <li>the weights array contains one or more infinite values</li>
1959      *     <li>the weights array contains one or more NaN values</li>
1960      *     <li>the weights array contains negative values</li>
1961      *     <li>the start and length arguments do not determine a valid array</li></ul>
1962      * </li>
1963      * <li>returns {@code false} if the array is non-null, but {@code length} is 0.</li>
1964      * </ul>
1965      *
1966      * @param values the input array
1967      * @param weights the weights array
1968      * @param begin index of the first array element to include
1969      * @param length the number of elements to include
1970      * @return true if the parameters are valid and designate a subarray of positive length
1971      * @throws MathIllegalArgumentException if the indices are invalid or the array is null
1972      */
1973     public static boolean verifyValues(
1974         final double[] values,
1975         final double[] weights,
1976         final int begin,
1977         final int length) throws MathIllegalArgumentException {
1978         return verifyValues(values, weights, begin, length, false);
1979     }
1980 
1981     /**
1982      * This method is used
1983      * to verify that the begin and length parameters designate a subarray of positive length
1984      * and the weights are all non-negative, non-NaN, finite, and not all zero.
1985      * <ul>
1986      * <li>returns {@code true} iff the parameters designate a subarray of
1987      * non-negative length and the weights array contains legitimate values.</li>
1988      * <li>throws {@code MathIllegalArgumentException} if any of the following are true:
1989      * <ul><li>the values array is null</li>
1990      *     <li>the weights array is null</li>
1991      *     <li>the weights array does not have the same length as the values array</li>
1992      *     <li>the weights array contains one or more infinite values</li>
1993      *     <li>the weights array contains one or more NaN values</li>
1994      *     <li>the weights array contains negative values</li>
1995      *     <li>the start and length arguments do not determine a valid array</li></ul>
1996      * </li>
1997      * <li>returns {@code false} if the array is non-null, but
1998      * {@code length} is 0 unless {@code allowEmpty} is {@code true}</li>
1999      * </ul>
2000      *
2001      * @param values the input array.
2002      * @param weights the weights array.
2003      * @param begin index of the first array element to include.
2004      * @param length the number of elements to include.
2005      * @param allowEmpty if {@code true} than allow zero length arrays to pass.
2006      * @return {@code true} if the parameters are valid.
2007      * @throws NullArgumentException if either of the arrays are null
2008      * @throws MathIllegalArgumentException if the array indices are not valid,
2009      * the weights array contains NaN, infinite or negative elements, or there
2010      * are no positive weights.
2011      */
2012     public static boolean verifyValues(final double[] values, final double[] weights,
2013             final int begin, final int length, final boolean allowEmpty) throws MathIllegalArgumentException {
2014 
2015         MathUtils.checkNotNull(weights, LocalizedCoreFormats.INPUT_ARRAY);
2016         MathUtils.checkNotNull(values, LocalizedCoreFormats.INPUT_ARRAY);
2017 
2018         checkEqualLength(weights, values);
2019 
2020         boolean containsPositiveWeight = false;
2021         for (int i = begin; i < begin + length; i++) {
2022             final double weight = weights[i];
2023             if (Double.isNaN(weight)) {
2024                 throw new MathIllegalArgumentException(LocalizedCoreFormats.NAN_ELEMENT_AT_INDEX, Integer.valueOf(i));
2025             }
2026             if (Double.isInfinite(weight)) {
2027                 throw new MathIllegalArgumentException(LocalizedCoreFormats.INFINITE_ARRAY_ELEMENT, Double.valueOf(weight), Integer.valueOf(i));
2028             }
2029             if (weight < 0) {
2030                 throw new MathIllegalArgumentException(LocalizedCoreFormats.NEGATIVE_ELEMENT_AT_INDEX, Integer.valueOf(i), Double.valueOf(weight));
2031             }
2032             if (!containsPositiveWeight && weight > 0.0) {
2033                 containsPositiveWeight = true;
2034             }
2035         }
2036 
2037         if (!containsPositiveWeight) {
2038             throw new MathIllegalArgumentException(LocalizedCoreFormats.WEIGHT_AT_LEAST_ONE_NON_ZERO);
2039         }
2040 
2041         return verifyValues(values, begin, length, allowEmpty);
2042     }
2043 
2044     /**
2045      * Concatenates a sequence of arrays. The return array consists of the
2046      * entries of the input arrays concatenated in the order they appear in
2047      * the argument list.  Null arrays cause NullPointerExceptions; zero
2048      * length arrays are allowed (contributing nothing to the output array).
2049      *
2050      * @param x list of double[] arrays to concatenate
2051      * @return a new array consisting of the entries of the argument arrays
2052      * @throws NullPointerException if any of the arrays are null
2053      */
2054     public static double[] concatenate(double[]... x) {
2055         int combinedLength = 0;
2056         for (double[] a : x) {
2057             combinedLength += a.length;
2058         }
2059         int offset = 0;
2060         final double[] combined = new double[combinedLength];
2061         for (int i = 0; i < x.length; i++) {
2062             final int curLength = x[i].length;
2063             System.arraycopy(x[i], 0, combined, offset, curLength);
2064             offset += curLength;
2065         }
2066         return combined;
2067     }
2068 
2069     /**
2070      * Returns an array consisting of the unique values in {@code data}.
2071      * The return array is sorted in descending order.  Empty arrays
2072      * are allowed, but null arrays result in NullPointerException.
2073      * Infinities are allowed.  NaN values are allowed with maximum
2074      * sort order - i.e., if there are NaN values in {@code data},
2075      * {@code Double.NaN} will be the first element of the output array,
2076      * even if the array also contains {@code Double.POSITIVE_INFINITY}.
2077      *
2078      * @param data array to scan
2079      * @return descending list of values included in the input array
2080      * @throws NullPointerException if data is null
2081      */
2082     public static double[] unique(double[] data) {
2083         TreeSet<Double> values = new TreeSet<>();
2084         for (int i = 0; i < data.length; i++) {
2085             values.add(data[i]);
2086         }
2087         final int count = values.size();
2088         final double[] out = new double[count];
2089         Iterator<Double> iterator = values.descendingIterator();
2090         int i = 0;
2091         while (iterator.hasNext()) {
2092             out[i++] = iterator.next();
2093         }
2094         return out;
2095     }
2096 }