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.Comparator;
29  import java.util.Iterator;
30  import java.util.List;
31  import java.util.NavigableSet;
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 (double v : in) {
711             if (v <= 0) {
712                 throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_SMALL_BOUND_EXCLUDED,
713                         v, 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 (long l : in) {
742             if (l < 0) {
743                 throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_SMALL, l, 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 (long[] longs : in) {
757             for (int j = 0; j < longs.length; j++) {
758                 if (longs[j] < 0) {
759                     throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_SMALL, longs[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 (double value : v) {
838             double xabs = FastMath.abs(value);
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 len = x.length;
958 
959         for (final double[] y : yList) {
960             if (y == null) {
961                 throw new NullArgumentException();
962             }
963             if (y.length != len) {
964                 throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
965                         y.length, len);
966             }
967         }
968 
969         // Associate each abscissa "x[i]" with its index "i".
970         final List<PairDoubleInteger> list = new ArrayList<>(len);
971         for (int i = 0; i < len; i++) {
972             list.add(new PairDoubleInteger(x[i], i));
973         }
974 
975         // Create comparators for increasing and decreasing orders.
976         final Comparator<PairDoubleInteger> comp =
977             dir == MathArrays.OrderDirection.INCREASING ?
978             new Comparator<PairDoubleInteger>() {
979                 /** {@inheritDoc} */
980                 @Override
981                 public int compare(PairDoubleInteger o1,
982                                    PairDoubleInteger o2) {
983                     return Double.compare(o1.getKey(), o2.getKey());
984                 }
985             } :
986             new Comparator<PairDoubleInteger>() {
987                 /** {@inheritDoc} */
988                 @Override
989                 public int compare(PairDoubleInteger o1,
990                                    PairDoubleInteger o2) {
991                     return Double.compare(o2.getKey(), o1.getKey());
992                 }
993             };
994 
995         // Sort.
996         list.sort(comp);
997 
998         // Modify the original array so that its elements are in
999         // the prescribed order.
1000         // Retrieve indices of original locations.
1001         final int[] indices = new int[len];
1002         for (int i = 0; i < len; i++) {
1003             final PairDoubleInteger e = list.get(i);
1004             x[i] = e.getKey();
1005             indices[i] = e.getValue();
1006         }
1007 
1008         // In each of the associated arrays, move the
1009         // elements to their new location.
1010         for (final double[] yInPlace : yList) {
1011             // Input array will be modified in place.
1012             final double[] yOrig = yInPlace.clone();
1013 
1014             for (int i = 0; i < len; i++) {
1015                 yInPlace[i] = yOrig[indices[i]];
1016             }
1017         }
1018     }
1019 
1020     /**
1021      * Compute a linear combination accurately.
1022      * This method computes the sum of the products
1023      * <code>a<sub>i</sub> b<sub>i</sub></code> to high accuracy.
1024      * It does so by using specific multiplication and addition algorithms to
1025      * preserve accuracy and reduce cancellation effects.
1026      * <br>
1027      * It is based on the 2005 paper
1028      * <a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.2.1547">
1029      * Accurate Sum and Dot Product</a> by Takeshi Ogita, Siegfried M. Rump,
1030      * and Shin'ichi Oishi published in SIAM J. Sci. Comput.
1031      *
1032      * @param a Factors.
1033      * @param b Factors.
1034      * @return <code>&Sigma;<sub>i</sub> a<sub>i</sub> b<sub>i</sub></code>.
1035      * @throws MathIllegalArgumentException if arrays dimensions don't match
1036      */
1037     public static double linearCombination(final double[] a, final double[] b)
1038         throws MathIllegalArgumentException {
1039         checkEqualLength(a, b);
1040         final int len = a.length;
1041 
1042         if (len == 1) {
1043             // Revert to scalar multiplication.
1044             return a[0] * b[0];
1045         }
1046 
1047         final double[] prodHigh = new double[len];
1048         double prodLowSum = 0;
1049 
1050         for (int i = 0; i < len; i++) {
1051             final double ai    = a[i];
1052             final double aHigh = Double.longBitsToDouble(Double.doubleToRawLongBits(ai) & ((-1L) << 27));
1053             final double aLow  = ai - aHigh;
1054 
1055             final double bi    = b[i];
1056             final double bHigh = Double.longBitsToDouble(Double.doubleToRawLongBits(bi) & ((-1L) << 27));
1057             final double bLow  = bi - bHigh;
1058             prodHigh[i] = ai * bi;
1059             final double prodLow = aLow * bLow - (((prodHigh[i] -
1060                                                     aHigh * bHigh) -
1061                                                    aLow * bHigh) -
1062                                                   aHigh * bLow);
1063             prodLowSum += prodLow;
1064         }
1065 
1066 
1067         final double prodHighCur = prodHigh[0];
1068         double prodHighNext = prodHigh[1];
1069         double sHighPrev = prodHighCur + prodHighNext;
1070         double sPrime = sHighPrev - prodHighNext;
1071         double sLowSum = (prodHighNext - (sHighPrev - sPrime)) + (prodHighCur - sPrime);
1072 
1073         final int lenMinusOne = len - 1;
1074         for (int i = 1; i < lenMinusOne; i++) {
1075             prodHighNext = prodHigh[i + 1];
1076             final double sHighCur = sHighPrev + prodHighNext;
1077             sPrime = sHighCur - prodHighNext;
1078             sLowSum += (prodHighNext - (sHighCur - sPrime)) + (sHighPrev - sPrime);
1079             sHighPrev = sHighCur;
1080         }
1081 
1082         double result = sHighPrev + (prodLowSum + sLowSum);
1083 
1084         if (Double.isNaN(result) || result == 0.0) {
1085             // either we have split infinite numbers or some coefficients were NaNs or signed zeros,
1086             // just rely on the naive implementation and let IEEE754 handle this
1087             // we do this for zeros too as we want to preserve the sign of zero (see issue #76)
1088             result = a[0] * b[0];
1089             for (int i = 1; i < len; ++i) {
1090                 result += a[i] * b[i];
1091             }
1092         }
1093 
1094         return result;
1095     }
1096 
1097     /**
1098      * Compute a linear combination accurately.
1099      * <p>
1100      * This method computes a<sub>1</sub>&times;b<sub>1</sub> +
1101      * a<sub>2</sub>&times;b<sub>2</sub> to high accuracy. It does
1102      * so by using specific multiplication and addition algorithms to
1103      * preserve accuracy and reduce cancellation effects. It is based
1104      * on the 2005 paper <a
1105      * href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.2.1547">
1106      * Accurate Sum and Dot Product</a> by Takeshi Ogita,
1107      * Siegfried M. Rump, and Shin'ichi Oishi published in SIAM J. Sci. Comput.
1108      * </p>
1109      * @param a1 first factor of the first term
1110      * @param b1 second factor of the first term
1111      * @param a2 first factor of the second term
1112      * @param b2 second factor of the second term
1113      * @return a<sub>1</sub>&times;b<sub>1</sub> +
1114      * a<sub>2</sub>&times;b<sub>2</sub>
1115      * @see #linearCombination(double, double, double, double, double, double)
1116      * @see #linearCombination(double, double, double, double, double, double, double, double)
1117      */
1118     public static double linearCombination(final double a1, final double b1,
1119                                            final double a2, final double b2) {
1120 
1121         // the code below is split in many additions/subtractions that may
1122         // appear redundant. However, they should NOT be simplified, as they
1123         // use IEEE754 floating point arithmetic rounding properties.
1124         // The variable naming conventions are that xyzHigh contains the most significant
1125         // bits of xyz and xyzLow contains its least significant bits. So theoretically
1126         // xyz is the sum xyzHigh + xyzLow, but in many cases below, this sum cannot
1127         // be represented in only one double precision number so we preserve two numbers
1128         // to hold it as long as we can, combining the high and low order bits together
1129         // only at the end, after cancellation may have occurred on high order bits
1130 
1131         // split a1 and b1 as one 26 bits number and one 27 bits number
1132         final double a1High     = Double.longBitsToDouble(Double.doubleToRawLongBits(a1) & ((-1L) << 27));
1133         final double a1Low      = a1 - a1High;
1134         final double b1High     = Double.longBitsToDouble(Double.doubleToRawLongBits(b1) & ((-1L) << 27));
1135         final double b1Low      = b1 - b1High;
1136 
1137         // accurate multiplication a1 * b1
1138         final double prod1High  = a1 * b1;
1139         final double prod1Low   = a1Low * b1Low - (((prod1High - a1High * b1High) - a1Low * b1High) - a1High * b1Low);
1140 
1141         // split a2 and b2 as one 26 bits number and one 27 bits number
1142         final double a2High     = Double.longBitsToDouble(Double.doubleToRawLongBits(a2) & ((-1L) << 27));
1143         final double a2Low      = a2 - a2High;
1144         final double b2High     = Double.longBitsToDouble(Double.doubleToRawLongBits(b2) & ((-1L) << 27));
1145         final double b2Low      = b2 - b2High;
1146 
1147         // accurate multiplication a2 * b2
1148         final double prod2High  = a2 * b2;
1149         final double prod2Low   = a2Low * b2Low - (((prod2High - a2High * b2High) - a2Low * b2High) - a2High * b2Low);
1150 
1151         // accurate addition a1 * b1 + a2 * b2
1152         final double s12High    = prod1High + prod2High;
1153         final double s12Prime   = s12High - prod2High;
1154         final double s12Low     = (prod2High - (s12High - s12Prime)) + (prod1High - s12Prime);
1155 
1156         // final rounding, s12 may have suffered many cancellations, we try
1157         // to recover some bits from the extra words we have saved up to now
1158         double result = s12High + (prod1Low + prod2Low + s12Low);
1159 
1160         if (Double.isNaN(result) || result == 0.0) {
1161             // either we have split infinite numbers or some coefficients were NaNs or signed zeros,
1162             // just rely on the naive implementation and let IEEE754 handle this
1163             // we do this for zeros too as we want to preserve the sign of zero (see issue #76)
1164             result = a1 * b1 + a2 * b2;
1165         }
1166 
1167         return result;
1168     }
1169 
1170     /**
1171      * Compute a linear combination accurately.
1172      * <p>
1173      * This method computes a<sub>1</sub>&times;b<sub>1</sub> +
1174      * a<sub>2</sub>&times;b<sub>2</sub> + a<sub>3</sub>&times;b<sub>3</sub>
1175      * to high accuracy. It does so by using specific multiplication and
1176      * addition algorithms to preserve accuracy and reduce cancellation effects.
1177      * It is based on the 2005 paper <a
1178      * href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.2.1547">
1179      * Accurate Sum and Dot Product</a> by Takeshi Ogita,
1180      * Siegfried M. Rump, and Shin'ichi Oishi published in SIAM J. Sci. Comput.
1181      * </p>
1182      * @param a1 first factor of the first term
1183      * @param b1 second factor of the first term
1184      * @param a2 first factor of the second term
1185      * @param b2 second factor of the second term
1186      * @param a3 first factor of the third term
1187      * @param b3 second factor of the third term
1188      * @return a<sub>1</sub>&times;b<sub>1</sub> +
1189      * a<sub>2</sub>&times;b<sub>2</sub> + a<sub>3</sub>&times;b<sub>3</sub>
1190      * @see #linearCombination(double, double, double, double)
1191      * @see #linearCombination(double, double, double, double, double, double, double, double)
1192      */
1193     public static double linearCombination(final double a1, final double b1,
1194                                            final double a2, final double b2,
1195                                            final double a3, final double b3) {
1196 
1197         // the code below is split in many additions/subtractions that may
1198         // appear redundant. However, they should NOT be simplified, as they
1199         // do use IEEE754 floating point arithmetic rounding properties.
1200         // The variables naming conventions are that xyzHigh contains the most significant
1201         // bits of xyz and xyzLow contains its least significant bits. So theoretically
1202         // xyz is the sum xyzHigh + xyzLow, but in many cases below, this sum cannot
1203         // be represented in only one double precision number so we preserve two numbers
1204         // to hold it as long as we can, combining the high and low order bits together
1205         // only at the end, after cancellation may have occurred on high order bits
1206 
1207         // split a1 and b1 as one 26 bits number and one 27 bits number
1208         final double a1High     = Double.longBitsToDouble(Double.doubleToRawLongBits(a1) & ((-1L) << 27));
1209         final double a1Low      = a1 - a1High;
1210         final double b1High     = Double.longBitsToDouble(Double.doubleToRawLongBits(b1) & ((-1L) << 27));
1211         final double b1Low      = b1 - b1High;
1212 
1213         // accurate multiplication a1 * b1
1214         final double prod1High  = a1 * b1;
1215         final double prod1Low   = a1Low * b1Low - (((prod1High - a1High * b1High) - a1Low * b1High) - a1High * b1Low);
1216 
1217         // split a2 and b2 as one 26 bits number and one 27 bits number
1218         final double a2High     = Double.longBitsToDouble(Double.doubleToRawLongBits(a2) & ((-1L) << 27));
1219         final double a2Low      = a2 - a2High;
1220         final double b2High     = Double.longBitsToDouble(Double.doubleToRawLongBits(b2) & ((-1L) << 27));
1221         final double b2Low      = b2 - b2High;
1222 
1223         // accurate multiplication a2 * b2
1224         final double prod2High  = a2 * b2;
1225         final double prod2Low   = a2Low * b2Low - (((prod2High - a2High * b2High) - a2Low * b2High) - a2High * b2Low);
1226 
1227         // split a3 and b3 as one 26 bits number and one 27 bits number
1228         final double a3High     = Double.longBitsToDouble(Double.doubleToRawLongBits(a3) & ((-1L) << 27));
1229         final double a3Low      = a3 - a3High;
1230         final double b3High     = Double.longBitsToDouble(Double.doubleToRawLongBits(b3) & ((-1L) << 27));
1231         final double b3Low      = b3 - b3High;
1232 
1233         // accurate multiplication a3 * b3
1234         final double prod3High  = a3 * b3;
1235         final double prod3Low   = a3Low * b3Low - (((prod3High - a3High * b3High) - a3Low * b3High) - a3High * b3Low);
1236 
1237         // accurate addition a1 * b1 + a2 * b2
1238         final double s12High    = prod1High + prod2High;
1239         final double s12Prime   = s12High - prod2High;
1240         final double s12Low     = (prod2High - (s12High - s12Prime)) + (prod1High - s12Prime);
1241 
1242         // accurate addition a1 * b1 + a2 * b2 + a3 * b3
1243         final double s123High   = s12High + prod3High;
1244         final double s123Prime  = s123High - prod3High;
1245         final double s123Low    = (prod3High - (s123High - s123Prime)) + (s12High - s123Prime);
1246 
1247         // final rounding, s123 may have suffered many cancellations, we try
1248         // to recover some bits from the extra words we have saved up to now
1249         double result = s123High + (prod1Low + prod2Low + prod3Low + s12Low + s123Low);
1250 
1251         if (Double.isNaN(result) || result == 0.0) {
1252             // either we have split infinite numbers or some coefficients were NaNs or signed zeros,
1253             // just rely on the naive implementation and let IEEE754 handle this
1254             // we do this for zeros too as we want to preserve the sign of zero (see issue #76)
1255             result = a1 * b1 + a2 * b2 + a3 * b3;
1256         }
1257 
1258         return result;
1259     }
1260 
1261     /**
1262      * Compute a linear combination accurately.
1263      * <p>
1264      * This method computes a<sub>1</sub>&times;b<sub>1</sub> +
1265      * a<sub>2</sub>&times;b<sub>2</sub> + a<sub>3</sub>&times;b<sub>3</sub> +
1266      * a<sub>4</sub>&times;b<sub>4</sub>
1267      * to high accuracy. It does so by using specific multiplication and
1268      * addition algorithms to preserve accuracy and reduce cancellation effects.
1269      * It is based on the 2005 paper <a
1270      * href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.2.1547">
1271      * Accurate Sum and Dot Product</a> by Takeshi Ogita,
1272      * Siegfried M. Rump, and Shin'ichi Oishi published in SIAM J. Sci. Comput.
1273      * </p>
1274      * @param a1 first factor of the first term
1275      * @param b1 second factor of the first term
1276      * @param a2 first factor of the second term
1277      * @param b2 second factor of the second term
1278      * @param a3 first factor of the third term
1279      * @param b3 second factor of the third term
1280      * @param a4 first factor of the third term
1281      * @param b4 second factor of the third term
1282      * @return a<sub>1</sub>&times;b<sub>1</sub> +
1283      * a<sub>2</sub>&times;b<sub>2</sub> + a<sub>3</sub>&times;b<sub>3</sub> +
1284      * a<sub>4</sub>&times;b<sub>4</sub>
1285      * @see #linearCombination(double, double, double, double)
1286      * @see #linearCombination(double, double, double, double, double, double)
1287      */
1288     public static double linearCombination(final double a1, final double b1,
1289                                            final double a2, final double b2,
1290                                            final double a3, final double b3,
1291                                            final double a4, final double b4) {
1292 
1293         // the code below is split in many additions/subtractions that may
1294         // appear redundant. However, they should NOT be simplified, as they
1295         // do use IEEE754 floating point arithmetic rounding properties.
1296         // The variables naming conventions are that xyzHigh contains the most significant
1297         // bits of xyz and xyzLow contains its least significant bits. So theoretically
1298         // xyz is the sum xyzHigh + xyzLow, but in many cases below, this sum cannot
1299         // be represented in only one double precision number so we preserve two numbers
1300         // to hold it as long as we can, combining the high and low order bits together
1301         // only at the end, after cancellation may have occurred on high order bits
1302 
1303         // split a1 and b1 as one 26 bits number and one 27 bits number
1304         final double a1High     = Double.longBitsToDouble(Double.doubleToRawLongBits(a1) & ((-1L) << 27));
1305         final double a1Low      = a1 - a1High;
1306         final double b1High     = Double.longBitsToDouble(Double.doubleToRawLongBits(b1) & ((-1L) << 27));
1307         final double b1Low      = b1 - b1High;
1308 
1309         // accurate multiplication a1 * b1
1310         final double prod1High  = a1 * b1;
1311         final double prod1Low   = a1Low * b1Low - (((prod1High - a1High * b1High) - a1Low * b1High) - a1High * b1Low);
1312 
1313         // split a2 and b2 as one 26 bits number and one 27 bits number
1314         final double a2High     = Double.longBitsToDouble(Double.doubleToRawLongBits(a2) & ((-1L) << 27));
1315         final double a2Low      = a2 - a2High;
1316         final double b2High     = Double.longBitsToDouble(Double.doubleToRawLongBits(b2) & ((-1L) << 27));
1317         final double b2Low      = b2 - b2High;
1318 
1319         // accurate multiplication a2 * b2
1320         final double prod2High  = a2 * b2;
1321         final double prod2Low   = a2Low * b2Low - (((prod2High - a2High * b2High) - a2Low * b2High) - a2High * b2Low);
1322 
1323         // split a3 and b3 as one 26 bits number and one 27 bits number
1324         final double a3High     = Double.longBitsToDouble(Double.doubleToRawLongBits(a3) & ((-1L) << 27));
1325         final double a3Low      = a3 - a3High;
1326         final double b3High     = Double.longBitsToDouble(Double.doubleToRawLongBits(b3) & ((-1L) << 27));
1327         final double b3Low      = b3 - b3High;
1328 
1329         // accurate multiplication a3 * b3
1330         final double prod3High  = a3 * b3;
1331         final double prod3Low   = a3Low * b3Low - (((prod3High - a3High * b3High) - a3Low * b3High) - a3High * b3Low);
1332 
1333         // split a4 and b4 as one 26 bits number and one 27 bits number
1334         final double a4High     = Double.longBitsToDouble(Double.doubleToRawLongBits(a4) & ((-1L) << 27));
1335         final double a4Low      = a4 - a4High;
1336         final double b4High     = Double.longBitsToDouble(Double.doubleToRawLongBits(b4) & ((-1L) << 27));
1337         final double b4Low      = b4 - b4High;
1338 
1339         // accurate multiplication a4 * b4
1340         final double prod4High  = a4 * b4;
1341         final double prod4Low   = a4Low * b4Low - (((prod4High - a4High * b4High) - a4Low * b4High) - a4High * b4Low);
1342 
1343         // accurate addition a1 * b1 + a2 * b2
1344         final double s12High    = prod1High + prod2High;
1345         final double s12Prime   = s12High - prod2High;
1346         final double s12Low     = (prod2High - (s12High - s12Prime)) + (prod1High - s12Prime);
1347 
1348         // accurate addition a1 * b1 + a2 * b2 + a3 * b3
1349         final double s123High   = s12High + prod3High;
1350         final double s123Prime  = s123High - prod3High;
1351         final double s123Low    = (prod3High - (s123High - s123Prime)) + (s12High - s123Prime);
1352 
1353         // accurate addition a1 * b1 + a2 * b2 + a3 * b3 + a4 * b4
1354         final double s1234High  = s123High + prod4High;
1355         final double s1234Prime = s1234High - prod4High;
1356         final double s1234Low   = (prod4High - (s1234High - s1234Prime)) + (s123High - s1234Prime);
1357 
1358         // final rounding, s1234 may have suffered many cancellations, we try
1359         // to recover some bits from the extra words we have saved up to now
1360         double result = s1234High + (prod1Low + prod2Low + prod3Low + prod4Low + s12Low + s123Low + s1234Low);
1361 
1362         if (Double.isNaN(result) || result == 0.0) {
1363             // either we have split infinite numbers or some coefficients were NaNs or signed zeros,
1364             // just rely on the naive implementation and let IEEE754 handle this
1365             // we do this for zeros too as we want to preserve the sign of zero (see issue #76)
1366             result = a1 * b1 + a2 * b2 + a3 * b3 + a4 * b4;
1367         }
1368 
1369         return result;
1370     }
1371 
1372     /**
1373      * Returns true iff both arguments are null or have same dimensions and all
1374      * their elements are equal as defined by
1375      * {@link Precision#equals(float,float)}.
1376      *
1377      * @param x first array
1378      * @param y second array
1379      * @return true if the values are both null or have same dimension
1380      * and equal elements.
1381      */
1382     public static boolean equals(float[] x, float[] y) {
1383         if ((x == null) || (y == null)) {
1384             return !((x == null) ^ (y == null));
1385         }
1386         if (x.length != y.length) {
1387             return false;
1388         }
1389         for (int i = 0; i < x.length; ++i) {
1390             if (!Precision.equals(x[i], y[i])) {
1391                 return false;
1392             }
1393         }
1394         return true;
1395     }
1396 
1397     /**
1398      * Returns true iff both arguments are null or have same dimensions and all
1399      * their elements are equal as defined by
1400      * {@link Precision#equalsIncludingNaN(double,double) this method}.
1401      *
1402      * @param x first array
1403      * @param y second array
1404      * @return true if the values are both null or have same dimension and
1405      * equal elements
1406      */
1407     public static boolean equalsIncludingNaN(float[] x, float[] y) {
1408         if ((x == null) || (y == null)) {
1409             return !((x == null) ^ (y == null));
1410         }
1411         if (x.length != y.length) {
1412             return false;
1413         }
1414         for (int i = 0; i < x.length; ++i) {
1415             if (!Precision.equalsIncludingNaN(x[i], y[i])) {
1416                 return false;
1417             }
1418         }
1419         return true;
1420     }
1421 
1422     /**
1423      * Returns {@code true} iff both arguments are {@code null} or have same
1424      * dimensions and all their elements are equal as defined by
1425      * {@link Precision#equals(double,double)}.
1426      *
1427      * @param x First array.
1428      * @param y Second array.
1429      * @return {@code true} if the values are both {@code null} or have same
1430      * dimension and equal elements.
1431      */
1432     public static boolean equals(double[] x, double[] y) {
1433         if ((x == null) || (y == null)) {
1434             return !((x == null) ^ (y == null));
1435         }
1436         if (x.length != y.length) {
1437             return false;
1438         }
1439         for (int i = 0; i < x.length; ++i) {
1440             if (!Precision.equals(x[i], y[i])) {
1441                 return false;
1442             }
1443         }
1444         return true;
1445     }
1446 
1447     /**
1448      * Returns {@code true} iff both arguments are {@code null} or have same
1449      * dimensions and all their elements are equal as defined by
1450      * {@link Object#equals(Object)}.
1451      *
1452      * @param <T> type of the field elements
1453      * @param x First array.
1454      * @param y Second array.
1455      * @return {@code true} if the values are both {@code null} or have same
1456      * dimension and equal elements.
1457      * @since 4.0
1458      */
1459     public static <T extends FieldElement<T>> boolean equals(T[] x, T[] y) {
1460         if ((x == null) || (y == null)) {
1461             return !((x == null) ^ (y == null));
1462         }
1463         if (x.length != y.length) {
1464             return false;
1465         }
1466         for (int i = 0; i < x.length; ++i) {
1467             if (!x[i].equals(y[i])) {
1468                 return false;
1469             }
1470         }
1471         return true;
1472     }
1473 
1474     /**
1475      * Returns {@code true} iff both arguments are {@code null} or have same
1476      * dimensions and all their elements are equal as defined by
1477      * {@link Precision#equalsIncludingNaN(double,double) this method}.
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 equalsIncludingNaN(double[] x, double[] 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 (!Precision.equalsIncludingNaN(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(long[] x, long[] 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(int[] x, int[] 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(byte[] x, byte[] 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      * Returns {@code true} if both arguments are {@code null} or have same
1573      * dimensions and all their elements are equals.
1574      *
1575      * @param x First array.
1576      * @param y Second array.
1577      * @return {@code true} if the values are both {@code null} or have same
1578      * dimension and equal elements.
1579      */
1580     public static boolean equals(short[] x, short[] y) {
1581         if ((x == null) || (y == null)) {
1582             return !((x == null) ^ (y == null));
1583         }
1584         if (x.length != y.length) {
1585             return false;
1586         }
1587         for (int i = 0; i < x.length; ++i) {
1588             if (x[i] != y[i]) {
1589                 return false;
1590             }
1591         }
1592         return true;
1593     }
1594 
1595     /**
1596      * Normalizes an array to make it sum to a specified value.
1597      * Returns the result of the transformation
1598      * <pre>
1599      *    x ↦ x * normalizedSum / sum
1600      * </pre>
1601      * applied to each non-NaN element x of the input array, where sum is the
1602      * sum of the non-NaN entries in the input array.
1603      * <p>
1604      * Throws IllegalArgumentException if {@code normalizedSum} is infinite
1605      * or NaN and ArithmeticException if the input array contains any infinite elements
1606      * or sums to 0.
1607      * <p>
1608      * Ignores (i.e., copies unchanged to the output array) NaNs in the input array.
1609      * The input array is unchanged by this method.
1610      *
1611      * @param values Input array to be normalized
1612      * @param normalizedSum Target sum for the normalized array
1613      * @return the normalized array
1614      * @throws MathRuntimeException if the input array contains infinite
1615      * elements or sums to zero
1616      * @throws MathIllegalArgumentException if the target sum is infinite or {@code NaN}
1617      */
1618     public static double[] normalizeArray(double[] values, double normalizedSum)
1619         throws MathIllegalArgumentException, MathRuntimeException {
1620         if (Double.isInfinite(normalizedSum)) {
1621             throw new MathIllegalArgumentException(LocalizedCoreFormats.NORMALIZE_INFINITE);
1622         }
1623         if (Double.isNaN(normalizedSum)) {
1624             throw new MathIllegalArgumentException(LocalizedCoreFormats.NORMALIZE_NAN);
1625         }
1626         double sum = 0d;
1627         final int len = values.length;
1628         double[] out = new double[len];
1629         for (int i = 0; i < len; i++) {
1630             if (Double.isInfinite(values[i])) {
1631                 throw new MathIllegalArgumentException(LocalizedCoreFormats.INFINITE_ARRAY_ELEMENT, values[i], i);
1632             }
1633             if (!Double.isNaN(values[i])) {
1634                 sum += values[i];
1635             }
1636         }
1637         if (sum == 0) {
1638             throw new MathRuntimeException(LocalizedCoreFormats.ARRAY_SUMS_TO_ZERO);
1639         }
1640         for (int i = 0; i < len; i++) {
1641             if (Double.isNaN(values[i])) {
1642                 out[i] = Double.NaN;
1643             } else {
1644                 out[i] = values[i] * normalizedSum / sum;
1645             }
1646         }
1647         return out;
1648     }
1649 
1650     /** Build an array of elements.
1651      * <p>
1652      * Arrays are filled with {@code field.getZero()}
1653      *
1654      * @param <T> the type of the field elements
1655      * @param field field to which array elements belong
1656      * @param length of the array
1657      * @return a new array
1658      */
1659     public static <T extends FieldElement<T>> T[] buildArray(final Field<T> field, final int length) {
1660         @SuppressWarnings("unchecked") // OK because field must be correct class
1661         T[] array = (T[]) Array.newInstance(field.getRuntimeClass(), length);
1662         Arrays.fill(array, field.getZero());
1663         return array;
1664     }
1665 
1666     /** Build a double dimension array of elements.
1667      * <p>
1668      * Arrays are filled with {@code field.getZero()}
1669      *
1670      * @param <T> the type of the field elements
1671      * @param field field to which array elements belong
1672      * @param rows number of rows in the array
1673      * @param columns number of columns (may be negative to build partial
1674      * arrays in the same way {@code new Field[rows][]} works)
1675      * @return a new array
1676      */
1677     @SuppressWarnings("unchecked")
1678     public static <T extends FieldElement<T>> T[][] buildArray(final Field<T> field, final int rows, final int columns) {
1679         final T[][] array;
1680         if (columns < 0) {
1681             T[] dummyRow = buildArray(field, 0);
1682             array = (T[][]) Array.newInstance(dummyRow.getClass(), rows);
1683         } else {
1684             array = (T[][]) Array.newInstance(field.getRuntimeClass(), rows, columns);
1685             for (int i = 0; i < rows; ++i) {
1686                 Arrays.fill(array[i], field.getZero());
1687             }
1688         }
1689         return array;
1690     }
1691 
1692     /** Build a triple dimension array of elements.
1693      * <p>
1694      * Arrays are filled with {@code field.getZero()}
1695      *
1696      * @param <T> the type of the field elements
1697      * @param field field to which array elements belong
1698      * @param l1 number of elements along first dimension
1699      * @param l2 number of elements along second dimension
1700      * @param l3 number of elements along third dimension (may be negative to build partial
1701      * arrays in the same way {@code new Field[l1][l2][]} works)
1702      * @return a new array
1703      * @since 1.4
1704      */
1705     @SuppressWarnings("unchecked")
1706     public static <T extends FieldElement<T>> T[][][] buildArray(final Field<T> field, final int l1, final int l2, final int l3) {
1707         final T[][][] array;
1708         if (l3 < 0) {
1709             T[] dummyRow = buildArray(field, 0);
1710             array = (T[][][]) Array.newInstance(dummyRow.getClass(), l1, l2);
1711         } else {
1712             array = (T[][][]) Array.newInstance(field.getRuntimeClass(), l1, l2, l3);
1713             for (int i = 0; i < l1; ++i) {
1714                 for (int j = 0; j < l2; ++j) {
1715                     Arrays.fill(array[i][j], field.getZero());
1716                 }
1717             }
1718         }
1719         return array;
1720     }
1721 
1722     /**
1723      * Calculates the <a href="http://en.wikipedia.org/wiki/Convolution">
1724      * convolution</a> between two sequences.
1725      * <p>
1726      * The solution is obtained via straightforward computation of the
1727      * convolution sum (and not via FFT). Whenever the computation needs
1728      * an element that would be located at an index outside the input arrays,
1729      * the value is assumed to be zero.
1730      *
1731      * @param x First sequence.
1732      * Typically, this sequence will represent an input signal to a system.
1733      * @param h Second sequence.
1734      * Typically, this sequence will represent the impulse response of the system.
1735      * @return the convolution of {@code x} and {@code h}.
1736      * This array's length will be {@code x.length + h.length - 1}.
1737      * @throws NullArgumentException if either {@code x} or {@code h} is {@code null}.
1738      * @throws MathIllegalArgumentException if either {@code x} or {@code h} is empty.
1739      */
1740     public static double[] convolve(double[] x, double[] h)
1741         throws MathIllegalArgumentException, NullArgumentException {
1742         MathUtils.checkNotNull(x);
1743         MathUtils.checkNotNull(h);
1744 
1745         final int xLen = x.length;
1746         final int hLen = h.length;
1747 
1748         if (xLen == 0 || hLen == 0) {
1749             throw new MathIllegalArgumentException(LocalizedCoreFormats.NO_DATA);
1750         }
1751 
1752         // initialize the output array
1753         final int totalLength = xLen + hLen - 1;
1754         final double[] y = new double[totalLength];
1755 
1756         // straightforward implementation of the convolution sum
1757         for (int n = 0; n < totalLength; n++) {
1758             double yn = 0;
1759             int k = FastMath.max(0, n + 1 - xLen);
1760             int j = n - k;
1761             while (k < hLen && j >= 0) {
1762                 yn += x[j--] * h[k++];
1763             }
1764             y[n] = yn;
1765         }
1766 
1767         return y;
1768     }
1769 
1770     /**
1771      * Specification for indicating that some operation applies
1772      * before or after a given index.
1773      */
1774     public enum Position {
1775         /** Designates the beginning of the array (near index 0). */
1776         HEAD,
1777         /** Designates the end of the array. */
1778         TAIL
1779     }
1780 
1781     /**
1782      * Shuffle the entries of the given array.
1783      * The {@code start} and {@code pos} parameters select which portion
1784      * of the array is randomized and which is left untouched.
1785      *
1786      * @see #shuffle(int[],int,Position,RandomGenerator)
1787      *
1788      * @param list Array whose entries will be shuffled (in-place).
1789      * @param start Index at which shuffling begins.
1790      * @param pos Shuffling is performed for index positions between
1791      * {@code start} and either the end (if {@link Position#TAIL})
1792      * or the beginning (if {@link Position#HEAD}) of the array.
1793      */
1794     public static void shuffle(int[] list,
1795                                int start,
1796                                Position pos) {
1797         shuffle(list, start, pos, new Well19937c());
1798     }
1799 
1800     /**
1801      * Shuffle the entries of the given array, using the
1802      * <a href="https://en.wikipedia.org/wiki/Fisher-Yates_shuffle#The_modern_algorithm">
1803      * Fisher–Yates</a> algorithm.
1804      * The {@code start} and {@code pos} parameters select which portion
1805      * of the array is randomized and which is left untouched.
1806      *
1807      * @param list Array whose entries will be shuffled (in-place).
1808      * @param start Index at which shuffling begins.
1809      * @param pos Shuffling is performed for index positions between
1810      * {@code start} and either the end (if {@link Position#TAIL})
1811      * or the beginning (if {@link Position#HEAD}) of the array.
1812      * @param rng Random number generator.
1813      */
1814     public static void shuffle(int[] list,
1815                                int start,
1816                                Position pos,
1817                                RandomGenerator rng) {
1818         switch (pos) {
1819         case TAIL:
1820             for (int i = list.length - 1; i > start; i--) {
1821                 final int target = start + rng.nextInt(i - start + 1);
1822                 final int temp = list[target];
1823                 list[target] = list[i];
1824                 list[i] = temp;
1825             }
1826             break;
1827 
1828         case HEAD:
1829             for (int i = 0; i < start; i++) {
1830                 final int target = i + rng.nextInt(start - i + 1);
1831                 final int temp = list[target];
1832                 list[target] = list[i];
1833                 list[i] = temp;
1834             }
1835             break;
1836 
1837         default:
1838             throw MathRuntimeException.createInternalError(); // Should never happen.
1839         }
1840     }
1841 
1842     /**
1843      * Shuffle the entries of the given array.
1844      *
1845      * @see #shuffle(int[],int,Position,RandomGenerator)
1846      *
1847      * @param list Array whose entries will be shuffled (in-place).
1848      * @param rng Random number generator.
1849      */
1850     public static void shuffle(int[] list,
1851                                RandomGenerator rng) {
1852         shuffle(list, 0, Position.TAIL, rng);
1853     }
1854 
1855     /**
1856      * Shuffle the entries of the given array.
1857      *
1858      * @see #shuffle(int[],int,Position,RandomGenerator)
1859      *
1860      * @param list Array whose entries will be shuffled (in-place).
1861      */
1862     public static void shuffle(int[] list) {
1863         shuffle(list, new Well19937c());
1864     }
1865 
1866     /**
1867      * Returns an array representing the natural number {@code n}.
1868      *
1869      * @param n Natural number.
1870      * @return an array whose entries are the numbers 0, 1, ..., {@code n}-1.
1871      * If {@code n == 0}, the returned array is empty.
1872      */
1873     public static int[] natural(int n) {
1874         return sequence(n, 0, 1);
1875     }
1876 
1877     /**
1878      * Returns an array of {@code size} integers starting at {@code start},
1879      * skipping {@code stride} numbers.
1880      *
1881      * @param size Natural number.
1882      * @param start Natural number.
1883      * @param stride Natural number.
1884      * @return an array whose entries are the numbers
1885      * {@code start, start + stride, ..., start + (size - 1) * stride}.
1886      * If {@code size == 0}, the returned array is empty.
1887      */
1888     public static int[] sequence(int size,
1889                                  int start,
1890                                  int stride) {
1891         final int[] a = new int[size];
1892         for (int i = 0; i < size; i++) {
1893             a[i] = start + i * stride;
1894         }
1895         return a;
1896     }
1897 
1898     /**
1899      * This method is used
1900      * to verify that the input parameters designate a subarray of positive length.
1901      * <ul>
1902      * <li>returns {@code true} iff the parameters designate a subarray of
1903      * positive length</li>
1904      * <li>throws {@code MathIllegalArgumentException} if the array is null or
1905      * or the indices are invalid</li>
1906      * <li>returns {@code false} if the array is non-null, but
1907      * {@code length} is 0.</li>
1908      * </ul>
1909      *
1910      * @param values the input array
1911      * @param begin index of the first array element to include
1912      * @param length the number of elements to include
1913      * @return true if the parameters are valid and designate a subarray of positive length
1914      * @throws MathIllegalArgumentException if the indices are invalid or the array is null
1915      */
1916     public static boolean verifyValues(final double[] values, final int begin, final int length)
1917             throws MathIllegalArgumentException {
1918         return verifyValues(values, begin, length, false);
1919     }
1920 
1921     /**
1922      * This method is used
1923      * to verify that the input parameters designate a subarray of positive length.
1924      * <ul>
1925      * <li>returns {@code true} iff the parameters designate a subarray of
1926      * non-negative length</li>
1927      * <li>throws {@code IllegalArgumentException} if the array is null or
1928      * or the indices are invalid</li>
1929      * <li>returns {@code false} if the array is non-null, but
1930      * {@code length} is 0 unless {@code allowEmpty} is {@code true}</li>
1931      * </ul>
1932      *
1933      * @param values the input array
1934      * @param begin index of the first array element to include
1935      * @param length the number of elements to include
1936      * @param allowEmpty if <code>true</code> then zero length arrays are allowed
1937      * @return true if the parameters are valid
1938      * @throws MathIllegalArgumentException if the indices are invalid or the array is null
1939      */
1940     public static boolean verifyValues(final double[] values, final int begin,
1941             final int length, final boolean allowEmpty) throws MathIllegalArgumentException {
1942 
1943         MathUtils.checkNotNull(values, LocalizedCoreFormats.INPUT_ARRAY);
1944 
1945         if (begin < 0) {
1946             throw new MathIllegalArgumentException(LocalizedCoreFormats.START_POSITION, begin);
1947         }
1948 
1949         if (length < 0) {
1950             throw new MathIllegalArgumentException(LocalizedCoreFormats.LENGTH, length);
1951         }
1952 
1953         if (begin + length > values.length) {
1954             throw new MathIllegalArgumentException(LocalizedCoreFormats.SUBARRAY_ENDS_AFTER_ARRAY_END,
1955                     begin + length, values.length, true);
1956         }
1957 
1958         if (length == 0 && !allowEmpty) {
1959             return false;
1960         }
1961 
1962         return true;
1963     }
1964 
1965     /**
1966      * This method is used
1967      * to verify that the begin and length parameters designate a subarray of positive length
1968      * and the weights are all non-negative, non-NaN, finite, and not all zero.
1969      * <ul>
1970      * <li>returns {@code true} iff the parameters designate a subarray of
1971      * positive length and the weights array contains legitimate values.</li>
1972      * <li>throws {@code IllegalArgumentException} if any of the following are true:
1973      * <ul><li>the values array is null</li>
1974      *     <li>the weights array is null</li>
1975      *     <li>the weights array does not have the same length as the values array</li>
1976      *     <li>the weights array contains one or more infinite values</li>
1977      *     <li>the weights array contains one or more NaN values</li>
1978      *     <li>the weights array contains negative values</li>
1979      *     <li>the start and length arguments do not determine a valid array</li></ul>
1980      * </li>
1981      * <li>returns {@code false} if the array is non-null, but {@code length} is 0.</li>
1982      * </ul>
1983      *
1984      * @param values the input array
1985      * @param weights the weights array
1986      * @param begin index of the first array element to include
1987      * @param length the number of elements to include
1988      * @return true if the parameters are valid and designate a subarray of positive length
1989      * @throws MathIllegalArgumentException if the indices are invalid or the array is null
1990      */
1991     public static boolean verifyValues(
1992         final double[] values,
1993         final double[] weights,
1994         final int begin,
1995         final int length) throws MathIllegalArgumentException {
1996         return verifyValues(values, weights, begin, length, false);
1997     }
1998 
1999     /**
2000      * This method is used
2001      * to verify that the begin and length parameters designate a subarray of positive length
2002      * and the weights are all non-negative, non-NaN, finite, and not all zero.
2003      * <ul>
2004      * <li>returns {@code true} iff the parameters designate a subarray of
2005      * non-negative length and the weights array contains legitimate values.</li>
2006      * <li>throws {@code MathIllegalArgumentException} if any of the following are true:
2007      * <ul><li>the values array is null</li>
2008      *     <li>the weights array is null</li>
2009      *     <li>the weights array does not have the same length as the values array</li>
2010      *     <li>the weights array contains one or more infinite values</li>
2011      *     <li>the weights array contains one or more NaN values</li>
2012      *     <li>the weights array contains negative values</li>
2013      *     <li>the start and length arguments do not determine a valid array</li></ul>
2014      * </li>
2015      * <li>returns {@code false} if the array is non-null, but
2016      * {@code length} is 0 unless {@code allowEmpty} is {@code true}</li>
2017      * </ul>
2018      *
2019      * @param values the input array.
2020      * @param weights the weights array.
2021      * @param begin index of the first array element to include.
2022      * @param length the number of elements to include.
2023      * @param allowEmpty if {@code true} than allow zero length arrays to pass.
2024      * @return {@code true} if the parameters are valid.
2025      * @throws NullArgumentException if either of the arrays are null
2026      * @throws MathIllegalArgumentException if the array indices are not valid,
2027      * the weights array contains NaN, infinite or negative elements, or there
2028      * are no positive weights.
2029      */
2030     public static boolean verifyValues(final double[] values, final double[] weights,
2031             final int begin, final int length, final boolean allowEmpty) throws MathIllegalArgumentException {
2032 
2033         MathUtils.checkNotNull(weights, LocalizedCoreFormats.INPUT_ARRAY);
2034         MathUtils.checkNotNull(values, LocalizedCoreFormats.INPUT_ARRAY);
2035 
2036         checkEqualLength(weights, values);
2037 
2038         boolean containsPositiveWeight = false;
2039         for (int i = begin; i < begin + length; i++) {
2040             final double weight = weights[i];
2041             if (Double.isNaN(weight)) {
2042                 throw new MathIllegalArgumentException(LocalizedCoreFormats.NAN_ELEMENT_AT_INDEX, i);
2043             }
2044             if (Double.isInfinite(weight)) {
2045                 throw new MathIllegalArgumentException(LocalizedCoreFormats.INFINITE_ARRAY_ELEMENT, weight, i);
2046             }
2047             if (weight < 0) {
2048                 throw new MathIllegalArgumentException(LocalizedCoreFormats.NEGATIVE_ELEMENT_AT_INDEX, i, weight);
2049             }
2050             if (!containsPositiveWeight && weight > 0.0) {
2051                 containsPositiveWeight = true;
2052             }
2053         }
2054 
2055         if (!containsPositiveWeight) {
2056             throw new MathIllegalArgumentException(LocalizedCoreFormats.WEIGHT_AT_LEAST_ONE_NON_ZERO);
2057         }
2058 
2059         return verifyValues(values, begin, length, allowEmpty);
2060     }
2061 
2062     /**
2063      * Concatenates a sequence of arrays. The return array consists of the
2064      * entries of the input arrays concatenated in the order they appear in
2065      * the argument list.  Null arrays cause NullPointerExceptions; zero
2066      * length arrays are allowed (contributing nothing to the output array).
2067      *
2068      * @param x list of double[] arrays to concatenate
2069      * @return a new array consisting of the entries of the argument arrays
2070      * @throws NullPointerException if any of the arrays are null
2071      */
2072     public static double[] concatenate(double[]... x) {
2073         int combinedLength = 0;
2074         for (double[] a : x) {
2075             combinedLength += a.length;
2076         }
2077         int offset = 0;
2078         final double[] combined = new double[combinedLength];
2079         for (double[] doubles : x) {
2080             final int curLength = doubles.length;
2081             System.arraycopy(doubles, 0, combined, offset, curLength);
2082             offset += curLength;
2083         }
2084         return combined;
2085     }
2086 
2087     /**
2088      * Returns an array consisting of the unique values in {@code data}.
2089      * The return array is sorted in descending order.  Empty arrays
2090      * are allowed, but null arrays result in NullPointerException.
2091      * Infinities are allowed.  NaN values are allowed with maximum
2092      * sort order - i.e., if there are NaN values in {@code data},
2093      * {@code Double.NaN} will be the first element of the output array,
2094      * even if the array also contains {@code Double.POSITIVE_INFINITY}.
2095      *
2096      * @param data array to scan
2097      * @return descending list of values included in the input array
2098      * @throws NullPointerException if data is null
2099      */
2100     public static double[] unique(double[] data) {
2101         NavigableSet<Double> values = new TreeSet<>();
2102         for (double datum : data) {
2103             values.add(datum);
2104         }
2105         final int count = values.size();
2106         final double[] out = new double[count];
2107         Iterator<Double> iterator = values.descendingIterator();
2108         int i = 0;
2109         while (iterator.hasNext()) {
2110             out[i++] = iterator.next();
2111         }
2112         return out;
2113     }
2114 }