MathArrays.java

  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.  * This is not the original file distributed by the Apache Software Foundation
  19.  * It has been modified by the Hipparchus project
  20.  */

  21. package org.hipparchus.util;

  22. import java.lang.reflect.Array;
  23. import java.util.ArrayList;
  24. import java.util.Arrays;
  25. import java.util.Comparator;
  26. import java.util.Iterator;
  27. import java.util.List;
  28. import java.util.NavigableSet;
  29. import java.util.TreeSet;

  30. import org.hipparchus.Field;
  31. import org.hipparchus.FieldElement;
  32. import org.hipparchus.CalculusFieldElement;
  33. import org.hipparchus.exception.LocalizedCoreFormats;
  34. import org.hipparchus.exception.MathIllegalArgumentException;
  35. import org.hipparchus.exception.MathRuntimeException;
  36. import org.hipparchus.exception.NullArgumentException;
  37. import org.hipparchus.random.RandomGenerator;
  38. import org.hipparchus.random.Well19937c;

  39. /**
  40.  * Arrays utilities.
  41.  */
  42. public class MathArrays {

  43.     /**
  44.      * Private constructor.
  45.      */
  46.     private MathArrays() {}

  47.     /**
  48.      * Real-valued function that operates on an array or a part of it.
  49.      */
  50.     public interface Function {

  51.         /** Operates on an entire array.
  52.          * @param array Array to operate on.
  53.          * @return the result of the operation.
  54.          */
  55.         double evaluate(double[] array);

  56.         /** Operates on a sub-array.
  57.          * @param array Array to operate on.
  58.          * @param startIndex Index of the first element to take into account.
  59.          * @param numElements Number of elements to take into account.
  60.          * @return the result of the operation.
  61.          */
  62.         double evaluate(double[] array,
  63.                         int startIndex,
  64.                         int numElements);

  65.     }

  66.     /**
  67.      * Create a copy of an array scaled by a value.
  68.      *
  69.      * @param arr Array to scale.
  70.      * @param val Scalar.
  71.      * @return scaled copy of array with each entry multiplied by val.
  72.      */
  73.     public static double[] scale(double val, final double[] arr) {
  74.         double[] newArr = new double[arr.length];
  75.         for (int i = 0; i < arr.length; i++) {
  76.             newArr[i] = arr[i] * val;
  77.         }
  78.         return newArr;
  79.     }

  80.     /**
  81.      * Multiply each element of an array by a value.
  82.      * <p>
  83.      * The array is modified in place (no copy is created).
  84.      *
  85.      * @param arr Array to scale
  86.      * @param val Scalar
  87.      */
  88.     public static void scaleInPlace(double val, final double[] arr) {
  89.         for (int i = 0; i < arr.length; i++) {
  90.             arr[i] *= val;
  91.         }
  92.     }

  93.     /**
  94.      * Creates an array whose contents will be the element-by-element
  95.      * addition of the arguments.
  96.      *
  97.      * @param a First term of the addition.
  98.      * @param b Second term of the addition.
  99.      * @return a new array {@code r} where {@code r[i] = a[i] + b[i]}.
  100.      * @throws MathIllegalArgumentException if the array lengths differ.
  101.      */
  102.     public static double[] ebeAdd(double[] a, double[] b)
  103.         throws MathIllegalArgumentException {
  104.         checkEqualLength(a, b);

  105.         final double[] result = a.clone();
  106.         for (int i = 0; i < a.length; i++) {
  107.             result[i] += b[i];
  108.         }
  109.         return result;
  110.     }
  111.     /**
  112.      * Creates an array whose contents will be the element-by-element
  113.      * subtraction of the second argument from the first.
  114.      *
  115.      * @param a First term.
  116.      * @param b Element to be subtracted.
  117.      * @return a new array {@code r} where {@code r[i] = a[i] - b[i]}.
  118.      * @throws MathIllegalArgumentException if the array lengths differ.
  119.      */
  120.     public static double[] ebeSubtract(double[] a, double[] b)
  121.         throws MathIllegalArgumentException {
  122.         checkEqualLength(a, b);

  123.         final double[] result = a.clone();
  124.         for (int i = 0; i < a.length; i++) {
  125.             result[i] -= b[i];
  126.         }
  127.         return result;
  128.     }
  129.     /**
  130.      * Creates an array whose contents will be the element-by-element
  131.      * multiplication of the arguments.
  132.      *
  133.      * @param a First factor of the multiplication.
  134.      * @param b Second factor of the multiplication.
  135.      * @return a new array {@code r} where {@code r[i] = a[i] * b[i]}.
  136.      * @throws MathIllegalArgumentException if the array lengths differ.
  137.      */
  138.     public static double[] ebeMultiply(double[] a, double[] b)
  139.         throws MathIllegalArgumentException {
  140.         checkEqualLength(a, b);

  141.         final double[] result = a.clone();
  142.         for (int i = 0; i < a.length; i++) {
  143.             result[i] *= b[i];
  144.         }
  145.         return result;
  146.     }
  147.     /**
  148.      * Creates an array whose contents will be the element-by-element
  149.      * division of the first argument by the second.
  150.      *
  151.      * @param a Numerator of the division.
  152.      * @param b Denominator of the division.
  153.      * @return a new array {@code r} where {@code r[i] = a[i] / b[i]}.
  154.      * @throws MathIllegalArgumentException if the array lengths differ.
  155.      */
  156.     public static double[] ebeDivide(double[] a, double[] b)
  157.         throws MathIllegalArgumentException {
  158.         checkEqualLength(a, b);

  159.         final double[] result = a.clone();
  160.         for (int i = 0; i < a.length; i++) {
  161.             result[i] /= b[i];
  162.         }
  163.         return result;
  164.     }

  165.     /**
  166.      * Calculates the L<sub>1</sub> (sum of abs) distance between two points.
  167.      *
  168.      * @param p1 the first point
  169.      * @param p2 the second point
  170.      * @return the L<sub>1</sub> distance between the two points
  171.      * @throws MathIllegalArgumentException if the array lengths differ.
  172.      */
  173.     public static double distance1(double[] p1, double[] p2)
  174.         throws MathIllegalArgumentException {
  175.         checkEqualLength(p1, p2);
  176.         double sum = 0;
  177.         for (int i = 0; i < p1.length; i++) {
  178.             sum += FastMath.abs(p1[i] - p2[i]);
  179.         }
  180.         return sum;
  181.     }

  182.     /**
  183.      * Calculates the L<sub>1</sub> (sum of abs) distance between two points.
  184.      *
  185.      * @param p1 the first point
  186.      * @param p2 the second point
  187.      * @return the L<sub>1</sub> distance between the two points
  188.      * @throws MathIllegalArgumentException if the array lengths differ.
  189.      */
  190.     public static int distance1(int[] p1, int[] p2)
  191.         throws MathIllegalArgumentException {
  192.         checkEqualLength(p1, p2);
  193.         int sum = 0;
  194.         for (int i = 0; i < p1.length; i++) {
  195.             sum += FastMath.abs(p1[i] - p2[i]);
  196.         }
  197.         return sum;
  198.     }

  199.     /**
  200.      * Calculates the L<sub>2</sub> (Euclidean) distance between two points.
  201.      *
  202.      * @param p1 the first point
  203.      * @param p2 the second point
  204.      * @return the L<sub>2</sub> distance between the two points
  205.      * @throws MathIllegalArgumentException if the array lengths differ.
  206.      */
  207.     public static double distance(double[] p1, double[] p2)
  208.         throws MathIllegalArgumentException {
  209.         checkEqualLength(p1, p2);
  210.         double sum = 0;
  211.         for (int i = 0; i < p1.length; i++) {
  212.             final double dp = p1[i] - p2[i];
  213.             sum += dp * dp;
  214.         }
  215.         return FastMath.sqrt(sum);
  216.     }

  217.     /**
  218.      * Calculates the cosine of the angle between two vectors.
  219.      *
  220.      * @param v1 Cartesian coordinates of the first vector.
  221.      * @param v2 Cartesian coordinates of the second vector.
  222.      * @return the cosine of the angle between the vectors.
  223.      */
  224.     public static double cosAngle(double[] v1, double[] v2) {
  225.         return linearCombination(v1, v2) / (safeNorm(v1) * safeNorm(v2));
  226.     }

  227.     /**
  228.      * Calculates the L<sub>2</sub> (Euclidean) distance between two points.
  229.      *
  230.      * @param p1 the first point
  231.      * @param p2 the second point
  232.      * @return the L<sub>2</sub> distance between the two points
  233.      * @throws MathIllegalArgumentException if the array lengths differ.
  234.      */
  235.     public static double distance(int[] p1, int[] p2)
  236.         throws MathIllegalArgumentException {
  237.         checkEqualLength(p1, p2);
  238.         double sum = 0;
  239.         for (int i = 0; i < p1.length; i++) {
  240.             final double dp = p1[i] - p2[i];
  241.             sum += dp * dp;
  242.         }
  243.         return FastMath.sqrt(sum);
  244.     }

  245.     /**
  246.      * Calculates the L<sub>&infin;</sub> (max of abs) distance between two points.
  247.      *
  248.      * @param p1 the first point
  249.      * @param p2 the second point
  250.      * @return the L<sub>&infin;</sub> distance between the two points
  251.      * @throws MathIllegalArgumentException if the array lengths differ.
  252.      */
  253.     public static double distanceInf(double[] p1, double[] p2)
  254.         throws MathIllegalArgumentException {
  255.         checkEqualLength(p1, p2);
  256.         double max = 0;
  257.         for (int i = 0; i < p1.length; i++) {
  258.             max = FastMath.max(max, FastMath.abs(p1[i] - p2[i]));
  259.         }
  260.         return max;
  261.     }

  262.     /**
  263.      * Calculates the L<sub>&infin;</sub> (max of abs) distance between two points.
  264.      *
  265.      * @param p1 the first point
  266.      * @param p2 the second point
  267.      * @return the L<sub>&infin;</sub> distance between the two points
  268.      * @throws MathIllegalArgumentException if the array lengths differ.
  269.      */
  270.     public static int distanceInf(int[] p1, int[] p2)
  271.         throws MathIllegalArgumentException {
  272.         checkEqualLength(p1, p2);
  273.         int max = 0;
  274.         for (int i = 0; i < p1.length; i++) {
  275.             max = FastMath.max(max, FastMath.abs(p1[i] - p2[i]));
  276.         }
  277.         return max;
  278.     }

  279.     /**
  280.      * Specification of ordering direction.
  281.      */
  282.     public enum OrderDirection {
  283.         /** Constant for increasing direction. */
  284.         INCREASING,
  285.         /** Constant for decreasing direction. */
  286.         DECREASING
  287.     }

  288.     /**
  289.      * Check that an array is monotonically increasing or decreasing.
  290.      *
  291.      * @param <T> the type of the elements in the specified array
  292.      * @param val Values.
  293.      * @param dir Ordering direction.
  294.      * @param strict Whether the order should be strict.
  295.      * @return {@code true} if sorted, {@code false} otherwise.
  296.      */
  297.     public static <T extends Comparable<? super T>> boolean isMonotonic(T[] val,
  298.                                                                         OrderDirection dir,
  299.                                                                         boolean strict) {
  300.         T previous = val[0];
  301.         final int max = val.length;
  302.         for (int i = 1; i < max; i++) {
  303.             final int comp;
  304.             switch (dir) {
  305.             case INCREASING:
  306.                 comp = previous.compareTo(val[i]);
  307.                 if (strict) {
  308.                     if (comp >= 0) {
  309.                         return false;
  310.                     }
  311.                 } else {
  312.                     if (comp > 0) {
  313.                         return false;
  314.                     }
  315.                 }
  316.                 break;
  317.             case DECREASING:
  318.                 comp = val[i].compareTo(previous);
  319.                 if (strict) {
  320.                     if (comp >= 0) {
  321.                         return false;
  322.                     }
  323.                 } else {
  324.                     if (comp > 0) {
  325.                        return false;
  326.                     }
  327.                 }
  328.                 break;
  329.             default:
  330.                 // Should never happen.
  331.                 throw MathRuntimeException.createInternalError();
  332.             }

  333.             previous = val[i];
  334.         }
  335.         return true;
  336.     }

  337.     /**
  338.      * Check that an array is monotonically increasing or decreasing.
  339.      *
  340.      * @param val Values.
  341.      * @param dir Ordering direction.
  342.      * @param strict Whether the order should be strict.
  343.      * @return {@code true} if sorted, {@code false} otherwise.
  344.      */
  345.     public static boolean isMonotonic(double[] val, OrderDirection dir, boolean strict) {
  346.         return checkOrder(val, dir, strict, false);
  347.     }

  348.     /**
  349.      * Check that both arrays have the same length.
  350.      *
  351.      * @param a Array.
  352.      * @param b Array.
  353.      * @param abort Whether to throw an exception if the check fails.
  354.      * @return {@code true} if the arrays have the same length.
  355.      * @throws MathIllegalArgumentException if the lengths differ and
  356.      * {@code abort} is {@code true}.
  357.      */
  358.     public static boolean checkEqualLength(double[] a,
  359.                                            double[] b,
  360.                                            boolean abort) {
  361.         if (a.length == b.length) {
  362.             return true;
  363.         } else {
  364.             if (abort) {
  365.                 throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
  366.                                                        a.length, b.length);
  367.             }
  368.             return false;
  369.         }
  370.     }

  371.     /**
  372.      * Check that both arrays have the same length.
  373.      *
  374.      * @param a Array.
  375.      * @param b Array.
  376.      * @throws MathIllegalArgumentException if the lengths differ.
  377.      */
  378.     public static void checkEqualLength(double[] a,
  379.                                         double[] b) {
  380.         checkEqualLength(a, b, true);
  381.     }

  382.     /**
  383.      * Check that both arrays have the same length.
  384.      *
  385.      * @param a Array.
  386.      * @param b Array.
  387.      * @param abort Whether to throw an exception if the check fails.
  388.      * @return {@code true} if the arrays have the same length.
  389.      * @throws MathIllegalArgumentException if the lengths differ and
  390.      * {@code abort} is {@code true}.
  391.      * @param <T> the type of the field elements
  392.      * @since 1.5
  393.      */
  394.     public static <T extends CalculusFieldElement<T>> boolean checkEqualLength(final T[] a,
  395.                                                                            final T[] b,
  396.                                            boolean abort) {
  397.         if (a.length == b.length) {
  398.             return true;
  399.         } else {
  400.             if (abort) {
  401.                 throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
  402.                                                        a.length, b.length);
  403.             }
  404.             return false;
  405.         }
  406.     }

  407.     /**
  408.      * Check that both arrays have the same length.
  409.      *
  410.      * @param a Array.
  411.      * @param b Array.
  412.      * @throws MathIllegalArgumentException if the lengths differ.
  413.      * @param <T> the type of the field elements
  414.      * @since 1.5
  415.      */
  416.     public static <T extends CalculusFieldElement<T>> void checkEqualLength(final T[] a, final T[] b) {
  417.         checkEqualLength(a, b, true);
  418.     }

  419.     /**
  420.      * Check that both arrays have the same length.
  421.      *
  422.      * @param a Array.
  423.      * @param b Array.
  424.      * @param abort Whether to throw an exception if the check fails.
  425.      * @return {@code true} if the arrays have the same length.
  426.      * @throws MathIllegalArgumentException if the lengths differ and
  427.      * {@code abort} is {@code true}.
  428.      */
  429.     public static boolean checkEqualLength(int[] a,
  430.                                            int[] b,
  431.                                            boolean abort) {
  432.         if (a.length == b.length) {
  433.             return true;
  434.         } else {
  435.             if (abort) {
  436.                 throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
  437.                                                        a.length, b.length);
  438.             }
  439.             return false;
  440.         }
  441.     }

  442.     /**
  443.      * Check that both arrays have the same length.
  444.      *
  445.      * @param a Array.
  446.      * @param b Array.
  447.      * @throws MathIllegalArgumentException if the lengths differ.
  448.      */
  449.     public static void checkEqualLength(int[] a,
  450.                                         int[] b) {
  451.         checkEqualLength(a, b, true);
  452.     }

  453.     /**
  454.      * Check that the given array is sorted.
  455.      *
  456.      * @param val Values.
  457.      * @param dir Ordering direction.
  458.      * @param strict Whether the order should be strict.
  459.      * @param abort Whether to throw an exception if the check fails.
  460.      * @return {@code true} if the array is sorted.
  461.      * @throws MathIllegalArgumentException if the array is not sorted
  462.      * and {@code abort} is {@code true}.
  463.      */
  464.     public static boolean checkOrder(double[] val, OrderDirection dir,
  465.                                      boolean strict, boolean abort)
  466.         throws MathIllegalArgumentException {
  467.         double previous = val[0];
  468.         final int max = val.length;

  469.         int index;
  470.         ITEM:
  471.         for (index = 1; index < max; index++) {
  472.             switch (dir) {
  473.             case INCREASING:
  474.                 if (strict) {
  475.                     if (val[index] <= previous) {
  476.                         break ITEM;
  477.                     }
  478.                 } else {
  479.                     if (val[index] < previous) {
  480.                         break ITEM;
  481.                     }
  482.                 }
  483.                 break;
  484.             case DECREASING:
  485.                 if (strict) {
  486.                     if (val[index] >= previous) {
  487.                         break ITEM;
  488.                     }
  489.                 } else {
  490.                     if (val[index] > previous) {
  491.                         break ITEM;
  492.                     }
  493.                 }
  494.                 break;
  495.             default:
  496.                 // Should never happen.
  497.                 throw MathRuntimeException.createInternalError();
  498.             }

  499.             previous = val[index];
  500.         }

  501.         if (index == max) {
  502.             // Loop completed.
  503.             return true;
  504.         }

  505.         // Loop early exit means wrong ordering.
  506.         if (abort) {
  507.             throw new MathIllegalArgumentException(dir == MathArrays.OrderDirection.INCREASING ?
  508.                                                     (strict ?
  509.                                                      LocalizedCoreFormats.NOT_STRICTLY_INCREASING_SEQUENCE :
  510.                                                      LocalizedCoreFormats.NOT_INCREASING_SEQUENCE) :
  511.                                                     (strict ?
  512.                                                      LocalizedCoreFormats.NOT_STRICTLY_DECREASING_SEQUENCE :
  513.                                                      LocalizedCoreFormats.NOT_DECREASING_SEQUENCE),
  514.                                                     val[index], previous, index, index - 1);
  515.         } else {
  516.             return false;
  517.         }
  518.     }

  519.     /**
  520.      * Check that the given array is sorted.
  521.      *
  522.      * @param val Values.
  523.      * @param dir Ordering direction.
  524.      * @param strict Whether the order should be strict.
  525.      * @throws MathIllegalArgumentException if the array is not sorted.
  526.      */
  527.     public static void checkOrder(double[] val, OrderDirection dir,
  528.                                   boolean strict) throws MathIllegalArgumentException {
  529.         checkOrder(val, dir, strict, true);
  530.     }

  531.     /**
  532.      * Check that the given array is sorted in strictly increasing order.
  533.      *
  534.      * @param val Values.
  535.      * @throws MathIllegalArgumentException if the array is not sorted.
  536.      */
  537.     public static void checkOrder(double[] val) throws MathIllegalArgumentException {
  538.         checkOrder(val, OrderDirection.INCREASING, true);
  539.     }

  540.     /**
  541.      * Check that the given array is sorted.
  542.      *
  543.      * @param val Values.
  544.      * @param dir Ordering direction.
  545.      * @param strict Whether the order should be strict.
  546.      * @param abort Whether to throw an exception if the check fails.
  547.      * @return {@code true} if the array is sorted.
  548.      * @throws MathIllegalArgumentException if the array is not sorted
  549.      * and {@code abort} is {@code true}.
  550.      * @param <T> the type of the field elements
  551.      * @since 1.5
  552.      */
  553.     public static <T extends CalculusFieldElement<T>>boolean checkOrder(T[] val, OrderDirection dir,
  554.                                                                     boolean strict, boolean abort)
  555.         throws MathIllegalArgumentException {
  556.         double previous = val[0].getReal();
  557.         final int max = val.length;

  558.         int index;
  559.         ITEM:
  560.         for (index = 1; index < max; index++) {
  561.             switch (dir) {
  562.             case INCREASING:
  563.                 if (strict) {
  564.                     if (val[index].getReal() <= previous) {
  565.                         break ITEM;
  566.                     }
  567.                 } else {
  568.                     if (val[index].getReal() < previous) {
  569.                         break ITEM;
  570.                     }
  571.                 }
  572.                 break;
  573.             case DECREASING:
  574.                 if (strict) {
  575.                     if (val[index].getReal() >= previous) {
  576.                         break ITEM;
  577.                     }
  578.                 } else {
  579.                     if (val[index].getReal() > previous) {
  580.                         break ITEM;
  581.                     }
  582.                 }
  583.                 break;
  584.             default:
  585.                 // Should never happen.
  586.                 throw MathRuntimeException.createInternalError();
  587.             }

  588.             previous = val[index].getReal();
  589.         }

  590.         if (index == max) {
  591.             // Loop completed.
  592.             return true;
  593.         }

  594.         // Loop early exit means wrong ordering.
  595.         if (abort) {
  596.             throw new MathIllegalArgumentException(dir == MathArrays.OrderDirection.INCREASING ?
  597.                                                     (strict ?
  598.                                                      LocalizedCoreFormats.NOT_STRICTLY_INCREASING_SEQUENCE :
  599.                                                      LocalizedCoreFormats.NOT_INCREASING_SEQUENCE) :
  600.                                                     (strict ?
  601.                                                      LocalizedCoreFormats.NOT_STRICTLY_DECREASING_SEQUENCE :
  602.                                                      LocalizedCoreFormats.NOT_DECREASING_SEQUENCE),
  603.                                                     val[index], previous, index, index - 1);
  604.         } else {
  605.             return false;
  606.         }
  607.     }

  608.     /**
  609.      * Check that the given array is sorted.
  610.      *
  611.      * @param val Values.
  612.      * @param dir Ordering direction.
  613.      * @param strict Whether the order should be strict.
  614.      * @throws MathIllegalArgumentException if the array is not sorted.
  615.      * @param <T> the type of the field elements
  616.      * @since 1.5
  617.      */
  618.     public static <T extends CalculusFieldElement<T>> void checkOrder(T[] val, OrderDirection dir,
  619.                                                                   boolean strict) throws MathIllegalArgumentException {
  620.         checkOrder(val, dir, strict, true);
  621.     }

  622.     /**
  623.      * Check that the given array is sorted in strictly increasing order.
  624.      *
  625.      * @param val Values.
  626.      * @throws MathIllegalArgumentException if the array is not sorted.
  627.      * @param <T> the type of the field elements
  628.      * @since 1.5
  629.      */
  630.     public static <T extends CalculusFieldElement<T>> void checkOrder(T[] val) throws MathIllegalArgumentException {
  631.         checkOrder(val, OrderDirection.INCREASING, true);
  632.     }

  633.     /**
  634.      * Throws MathIllegalArgumentException if the input array is not rectangular.
  635.      *
  636.      * @param in array to be tested
  637.      * @throws NullArgumentException if input array is null
  638.      * @throws MathIllegalArgumentException if input array is not rectangular
  639.      */
  640.     public static void checkRectangular(final long[][] in)
  641.         throws MathIllegalArgumentException, NullArgumentException {
  642.         MathUtils.checkNotNull(in);
  643.         for (int i = 1; i < in.length; i++) {
  644.             if (in[i].length != in[0].length) {
  645.                 throw new MathIllegalArgumentException(
  646.                         LocalizedCoreFormats.DIFFERENT_ROWS_LENGTHS,
  647.                         in[i].length, in[0].length);
  648.             }
  649.         }
  650.     }

  651.     /**
  652.      * Check that all entries of the input array are strictly positive.
  653.      *
  654.      * @param in Array to be tested
  655.      * @throws MathIllegalArgumentException if any entries of the array are not
  656.      * strictly positive.
  657.      */
  658.     public static void checkPositive(final double[] in)
  659.         throws MathIllegalArgumentException {
  660.         for (double v : in) {
  661.             if (v <= 0) {
  662.                 throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_SMALL_BOUND_EXCLUDED,
  663.                         v, 0);
  664.             }
  665.         }
  666.     }

  667.     /**
  668.      * Check that no entry of the input array is {@code NaN}.
  669.      *
  670.      * @param in Array to be tested.
  671.      * @throws MathIllegalArgumentException if an entry is {@code NaN}.
  672.      */
  673.     public static void checkNotNaN(final double[] in)
  674.         throws MathIllegalArgumentException {
  675.         for(int i = 0; i < in.length; i++) {
  676.             if (Double.isNaN(in[i])) {
  677.                 throw new MathIllegalArgumentException(LocalizedCoreFormats.NAN_ELEMENT_AT_INDEX, i);
  678.             }
  679.         }
  680.     }

  681.     /**
  682.      * Check that all entries of the input array are &gt;= 0.
  683.      *
  684.      * @param in Array to be tested
  685.      * @throws MathIllegalArgumentException if any array entries are less than 0.
  686.      */
  687.     public static void checkNonNegative(final long[] in)
  688.         throws MathIllegalArgumentException {
  689.         for (long l : in) {
  690.             if (l < 0) {
  691.                 throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_SMALL, l, 0);
  692.             }
  693.         }
  694.     }

  695.     /**
  696.      * Check all entries of the input array are &gt;= 0.
  697.      *
  698.      * @param in Array to be tested
  699.      * @throws MathIllegalArgumentException if any array entries are less than 0.
  700.      */
  701.     public static void checkNonNegative(final long[][] in)
  702.         throws MathIllegalArgumentException {
  703.         for (long[] longs : in) {
  704.             for (int j = 0; j < longs.length; j++) {
  705.                 if (longs[j] < 0) {
  706.                     throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_SMALL, longs[j], 0);
  707.                 }
  708.             }
  709.         }
  710.     }

  711.     /**
  712.      * Returns the Cartesian norm (2-norm), handling both overflow and underflow.
  713.      * Translation of the minpack enorm subroutine.
  714.      *
  715.      * <p>
  716.      * The redistribution policy for MINPACK is available
  717.      * <a href="http://www.netlib.org/minpack/disclaimer">here</a>, for
  718.      * convenience, it is reproduced below.
  719.      * </p>
  720.      *
  721.      * <blockquote>
  722.      * <p>
  723.      *    Minpack Copyright Notice (1999) University of Chicago.
  724.      *    All rights reserved
  725.      * </p>
  726.      * <p>
  727.      * Redistribution and use in source and binary forms, with or without
  728.      * modification, are permitted provided that the following conditions
  729.      * are met:
  730.      * </p>
  731.      * <ol>
  732.      *  <li>Redistributions of source code must retain the above copyright
  733.      *      notice, this list of conditions and the following disclaimer.</li>
  734.      * <li>Redistributions in binary form must reproduce the above
  735.      *     copyright notice, this list of conditions and the following
  736.      *     disclaimer in the documentation and/or other materials provided
  737.      *     with the distribution.</li>
  738.      * <li>The end-user documentation included with the redistribution, if any,
  739.      *     must include the following acknowledgment:
  740.      *     {@code This product includes software developed by the University of
  741.      *           Chicago, as Operator of Argonne National Laboratory.}
  742.      *     Alternately, this acknowledgment may appear in the software itself,
  743.      *     if and wherever such third-party acknowledgments normally appear.</li>
  744.      * <li><strong>WARRANTY DISCLAIMER. THE SOFTWARE IS SUPPLIED "AS IS"
  745.      *     WITHOUT WARRANTY OF ANY KIND. THE COPYRIGHT HOLDER, THE
  746.      *     UNITED STATES, THE UNITED STATES DEPARTMENT OF ENERGY, AND
  747.      *     THEIR EMPLOYEES: (1) DISCLAIM ANY WARRANTIES, EXPRESS OR
  748.      *     IMPLIED, INCLUDING BUT NOT LIMITED TO ANY IMPLIED WARRANTIES
  749.      *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE
  750.      *     OR NON-INFRINGEMENT, (2) DO NOT ASSUME ANY LEGAL LIABILITY
  751.      *     OR RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR
  752.      *     USEFULNESS OF THE SOFTWARE, (3) DO NOT REPRESENT THAT USE OF
  753.      *     THE SOFTWARE WOULD NOT INFRINGE PRIVATELY OWNED RIGHTS, (4)
  754.      *     DO NOT WARRANT THAT THE SOFTWARE WILL FUNCTION
  755.      *     UNINTERRUPTED, THAT IT IS ERROR-FREE OR THAT ANY ERRORS WILL
  756.      *     BE CORRECTED.</strong></li>
  757.      * <li><strong>LIMITATION OF LIABILITY. IN NO EVENT WILL THE COPYRIGHT
  758.      *     HOLDER, THE UNITED STATES, THE UNITED STATES DEPARTMENT OF
  759.      *     ENERGY, OR THEIR EMPLOYEES: BE LIABLE FOR ANY INDIRECT,
  760.      *     INCIDENTAL, CONSEQUENTIAL, SPECIAL OR PUNITIVE DAMAGES OF
  761.      *     ANY KIND OR NATURE, INCLUDING BUT NOT LIMITED TO LOSS OF
  762.      *     PROFITS OR LOSS OF DATA, FOR ANY REASON WHATSOEVER, WHETHER
  763.      *     SUCH LIABILITY IS ASSERTED ON THE BASIS OF CONTRACT, TORT
  764.      *     (INCLUDING NEGLIGENCE OR STRICT LIABILITY), OR OTHERWISE,
  765.      *     EVEN IF ANY OF SAID PARTIES HAS BEEN WARNED OF THE
  766.      *     POSSIBILITY OF SUCH LOSS OR DAMAGES.</strong></li>
  767.      * </ol>
  768.      * </blockquote>
  769.      *
  770.      * @param v Vector of doubles.
  771.      * @return the 2-norm of the vector.
  772.      */
  773.     public static double safeNorm(double[] v) {
  774.         double rdwarf = 3.834e-20;
  775.         double rgiant = 1.304e+19;
  776.         double s1 = 0;
  777.         double s2 = 0;
  778.         double s3 = 0;
  779.         double x1max = 0;
  780.         double x3max = 0;
  781.         double floatn = v.length;
  782.         double agiant = rgiant / floatn;
  783.         for (double value : v) {
  784.             double xabs = FastMath.abs(value);
  785.             if (xabs < rdwarf || xabs > agiant) {
  786.                 if (xabs > rdwarf) {
  787.                     if (xabs > x1max) {
  788.                         double r = x1max / xabs;
  789.                         s1 = 1 + s1 * r * r;
  790.                         x1max = xabs;
  791.                     } else {
  792.                         double r = xabs / x1max;
  793.                         s1 += r * r;
  794.                     }
  795.                 } else {
  796.                     if (xabs > x3max) {
  797.                         double r = x3max / xabs;
  798.                         s3 = 1 + s3 * r * r;
  799.                         x3max = xabs;
  800.                     } else {
  801.                         if (xabs != 0) {
  802.                             double r = xabs / x3max;
  803.                             s3 += r * r;
  804.                         }
  805.                     }
  806.                 }
  807.             } else {
  808.                 s2 += xabs * xabs;
  809.             }
  810.         }
  811.         double norm;
  812.         if (s1 != 0) {
  813.             norm = x1max * Math.sqrt(s1 + (s2 / x1max) / x1max);
  814.         } else {
  815.             if (s2 == 0) {
  816.                 norm = x3max * Math.sqrt(s3);
  817.             } else {
  818.                 if (s2 >= x3max) {
  819.                     norm = Math.sqrt(s2 * (1 + (x3max / s2) * (x3max * s3)));
  820.                 } else {
  821.                     norm = Math.sqrt(x3max * ((s2 / x3max) + (x3max * s3)));
  822.                 }
  823.             }
  824.         }
  825.         return norm;
  826.     }

  827.     /**
  828.      * Sort an array in ascending order in place and perform the same reordering
  829.      * of entries on other arrays. For example, if
  830.      * {@code x = [3, 1, 2], y = [1, 2, 3]} and {@code z = [0, 5, 7]}, then
  831.      * {@code sortInPlace(x, y, z)} will update {@code x} to {@code [1, 2, 3]},
  832.      * {@code y} to {@code [2, 3, 1]} and {@code z} to {@code [5, 7, 0]}.
  833.      *
  834.      * @param x Array to be sorted and used as a pattern for permutation
  835.      * of the other arrays.
  836.      * @param yList Set of arrays whose permutations of entries will follow
  837.      * those performed on {@code x}.
  838.      * @throws MathIllegalArgumentException if any {@code y} is not the same
  839.      * size as {@code x}.
  840.      * @throws NullArgumentException if {@code x} or any {@code y} is null.
  841.      */
  842.     public static void sortInPlace(double[] x, double[]... yList)
  843.         throws MathIllegalArgumentException, NullArgumentException {
  844.         sortInPlace(x, OrderDirection.INCREASING, yList);
  845.     }

  846.     /**
  847.      * Helper data structure holding a (double, integer) pair.
  848.      */
  849.     private static class PairDoubleInteger {
  850.         /** Key */
  851.         private final double key;
  852.         /** Value */
  853.         private final int value;

  854.         /**
  855.          * @param key Key.
  856.          * @param value Value.
  857.          */
  858.         PairDoubleInteger(double key, int value) {
  859.             this.key = key;
  860.             this.value = value;
  861.         }

  862.         /** @return the key. */
  863.         public double getKey() {
  864.             return key;
  865.         }

  866.         /** @return the value. */
  867.         public int getValue() {
  868.             return value;
  869.         }
  870.     }

  871.     /**
  872.      * Sort an array in place and perform the same reordering of entries on
  873.      * other arrays.  This method works the same as the other
  874.      * {@link #sortInPlace(double[], double[][]) sortInPlace} method, but
  875.      * allows the order of the sort to be provided in the {@code dir}
  876.      * parameter.
  877.      *
  878.      * @param x Array to be sorted and used as a pattern for permutation
  879.      * of the other arrays.
  880.      * @param dir Order direction.
  881.      * @param yList Set of arrays whose permutations of entries will follow
  882.      * those performed on {@code x}.
  883.      * @throws MathIllegalArgumentException if any {@code y} is not the same
  884.      * size as {@code x}.
  885.      * @throws NullArgumentException if {@code x} or any {@code y} is null
  886.      */
  887.     public static void sortInPlace(double[] x,
  888.                                    final OrderDirection dir,
  889.                                    double[]... yList)
  890.         throws MathIllegalArgumentException, NullArgumentException {

  891.         // Consistency checks.
  892.         if (x == null) {
  893.             throw new NullArgumentException();
  894.         }

  895.         final int len = x.length;

  896.         for (final double[] y : yList) {
  897.             if (y == null) {
  898.                 throw new NullArgumentException();
  899.             }
  900.             if (y.length != len) {
  901.                 throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
  902.                         y.length, len);
  903.             }
  904.         }

  905.         // Associate each abscissa "x[i]" with its index "i".
  906.         final List<PairDoubleInteger> list = new ArrayList<>(len);
  907.         for (int i = 0; i < len; i++) {
  908.             list.add(new PairDoubleInteger(x[i], i));
  909.         }

  910.         // Create comparators for increasing and decreasing orders.
  911.         final Comparator<PairDoubleInteger> comp =
  912.             dir == MathArrays.OrderDirection.INCREASING ?
  913.             new Comparator<PairDoubleInteger>() {
  914.                 /** {@inheritDoc} */
  915.                 @Override
  916.                 public int compare(PairDoubleInteger o1,
  917.                                    PairDoubleInteger o2) {
  918.                     return Double.compare(o1.getKey(), o2.getKey());
  919.                 }
  920.             } :
  921.             new Comparator<PairDoubleInteger>() {
  922.                 /** {@inheritDoc} */
  923.                 @Override
  924.                 public int compare(PairDoubleInteger o1,
  925.                                    PairDoubleInteger o2) {
  926.                     return Double.compare(o2.getKey(), o1.getKey());
  927.                 }
  928.             };

  929.         // Sort.
  930.         list.sort(comp);

  931.         // Modify the original array so that its elements are in
  932.         // the prescribed order.
  933.         // Retrieve indices of original locations.
  934.         final int[] indices = new int[len];
  935.         for (int i = 0; i < len; i++) {
  936.             final PairDoubleInteger e = list.get(i);
  937.             x[i] = e.getKey();
  938.             indices[i] = e.getValue();
  939.         }

  940.         // In each of the associated arrays, move the
  941.         // elements to their new location.
  942.         for (final double[] yInPlace : yList) {
  943.             // Input array will be modified in place.
  944.             final double[] yOrig = yInPlace.clone();

  945.             for (int i = 0; i < len; i++) {
  946.                 yInPlace[i] = yOrig[indices[i]];
  947.             }
  948.         }
  949.     }

  950.     /**
  951.      * Compute a linear combination accurately.
  952.      * This method computes the sum of the products
  953.      * <code>a<sub>i</sub> b<sub>i</sub></code> to high accuracy.
  954.      * It does so by using specific multiplication and addition algorithms to
  955.      * preserve accuracy and reduce cancellation effects.
  956.      * <br>
  957.      * It is based on the 2005 paper
  958.      * <a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.2.1547">
  959.      * Accurate Sum and Dot Product</a> by Takeshi Ogita, Siegfried M. Rump,
  960.      * and Shin'ichi Oishi published in SIAM J. Sci. Comput.
  961.      *
  962.      * @param a Factors.
  963.      * @param b Factors.
  964.      * @return <code>&Sigma;<sub>i</sub> a<sub>i</sub> b<sub>i</sub></code>.
  965.      * @throws MathIllegalArgumentException if arrays dimensions don't match
  966.      */
  967.     public static double linearCombination(final double[] a, final double[] b)
  968.         throws MathIllegalArgumentException {
  969.         checkEqualLength(a, b);
  970.         final int len = a.length;

  971.         if (len == 1) {
  972.             // Revert to scalar multiplication.
  973.             return a[0] * b[0];
  974.         }

  975.         final double[] prodHigh = new double[len];
  976.         double prodLowSum = 0;

  977.         for (int i = 0; i < len; i++) {
  978.             final double ai    = a[i];
  979.             final double aHigh = Double.longBitsToDouble(Double.doubleToRawLongBits(ai) & ((-1L) << 27));
  980.             final double aLow  = ai - aHigh;

  981.             final double bi    = b[i];
  982.             final double bHigh = Double.longBitsToDouble(Double.doubleToRawLongBits(bi) & ((-1L) << 27));
  983.             final double bLow  = bi - bHigh;
  984.             prodHigh[i] = ai * bi;
  985.             final double prodLow = aLow * bLow - (((prodHigh[i] -
  986.                                                     aHigh * bHigh) -
  987.                                                    aLow * bHigh) -
  988.                                                   aHigh * bLow);
  989.             prodLowSum += prodLow;
  990.         }


  991.         final double prodHighCur = prodHigh[0];
  992.         double prodHighNext = prodHigh[1];
  993.         double sHighPrev = prodHighCur + prodHighNext;
  994.         double sPrime = sHighPrev - prodHighNext;
  995.         double sLowSum = (prodHighNext - (sHighPrev - sPrime)) + (prodHighCur - sPrime);

  996.         final int lenMinusOne = len - 1;
  997.         for (int i = 1; i < lenMinusOne; i++) {
  998.             prodHighNext = prodHigh[i + 1];
  999.             final double sHighCur = sHighPrev + prodHighNext;
  1000.             sPrime = sHighCur - prodHighNext;
  1001.             sLowSum += (prodHighNext - (sHighCur - sPrime)) + (sHighPrev - sPrime);
  1002.             sHighPrev = sHighCur;
  1003.         }

  1004.         double result = sHighPrev + (prodLowSum + sLowSum);

  1005.         if (Double.isNaN(result) || result == 0.0) {
  1006.             // either we have split infinite numbers or some coefficients were NaNs or signed zeros,
  1007.             // just rely on the naive implementation and let IEEE754 handle this
  1008.             // we do this for zeros too as we want to preserve the sign of zero (see issue #76)
  1009.             result = a[0] * b[0];
  1010.             for (int i = 1; i < len; ++i) {
  1011.                 result += a[i] * b[i];
  1012.             }
  1013.         }

  1014.         return result;
  1015.     }

  1016.     /**
  1017.      * Compute a linear combination accurately.
  1018.      * <p>
  1019.      * This method computes a<sub>1</sub>&times;b<sub>1</sub> +
  1020.      * a<sub>2</sub>&times;b<sub>2</sub> to high accuracy. It does
  1021.      * so by using specific multiplication and addition algorithms to
  1022.      * preserve accuracy and reduce cancellation effects. It is based
  1023.      * on the 2005 paper <a
  1024.      * href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.2.1547">
  1025.      * Accurate Sum and Dot Product</a> by Takeshi Ogita,
  1026.      * Siegfried M. Rump, and Shin'ichi Oishi published in SIAM J. Sci. Comput.
  1027.      * </p>
  1028.      * @param a1 first factor of the first term
  1029.      * @param b1 second factor of the first term
  1030.      * @param a2 first factor of the second term
  1031.      * @param b2 second factor of the second term
  1032.      * @return a<sub>1</sub>&times;b<sub>1</sub> +
  1033.      * a<sub>2</sub>&times;b<sub>2</sub>
  1034.      * @see #linearCombination(double, double, double, double, double, double)
  1035.      * @see #linearCombination(double, double, double, double, double, double, double, double)
  1036.      */
  1037.     public static double linearCombination(final double a1, final double b1,
  1038.                                            final double a2, final double b2) {

  1039.         // the code below is split in many additions/subtractions that may
  1040.         // appear redundant. However, they should NOT be simplified, as they
  1041.         // use IEEE754 floating point arithmetic rounding properties.
  1042.         // The variable naming conventions are that xyzHigh contains the most significant
  1043.         // bits of xyz and xyzLow contains its least significant bits. So theoretically
  1044.         // xyz is the sum xyzHigh + xyzLow, but in many cases below, this sum cannot
  1045.         // be represented in only one double precision number so we preserve two numbers
  1046.         // to hold it as long as we can, combining the high and low order bits together
  1047.         // only at the end, after cancellation may have occurred on high order bits

  1048.         // split a1 and b1 as one 26 bits number and one 27 bits number
  1049.         final double a1High     = Double.longBitsToDouble(Double.doubleToRawLongBits(a1) & ((-1L) << 27));
  1050.         final double a1Low      = a1 - a1High;
  1051.         final double b1High     = Double.longBitsToDouble(Double.doubleToRawLongBits(b1) & ((-1L) << 27));
  1052.         final double b1Low      = b1 - b1High;

  1053.         // accurate multiplication a1 * b1
  1054.         final double prod1High  = a1 * b1;
  1055.         final double prod1Low   = a1Low * b1Low - (((prod1High - a1High * b1High) - a1Low * b1High) - a1High * b1Low);

  1056.         // split a2 and b2 as one 26 bits number and one 27 bits number
  1057.         final double a2High     = Double.longBitsToDouble(Double.doubleToRawLongBits(a2) & ((-1L) << 27));
  1058.         final double a2Low      = a2 - a2High;
  1059.         final double b2High     = Double.longBitsToDouble(Double.doubleToRawLongBits(b2) & ((-1L) << 27));
  1060.         final double b2Low      = b2 - b2High;

  1061.         // accurate multiplication a2 * b2
  1062.         final double prod2High  = a2 * b2;
  1063.         final double prod2Low   = a2Low * b2Low - (((prod2High - a2High * b2High) - a2Low * b2High) - a2High * b2Low);

  1064.         // accurate addition a1 * b1 + a2 * b2
  1065.         final double s12High    = prod1High + prod2High;
  1066.         final double s12Prime   = s12High - prod2High;
  1067.         final double s12Low     = (prod2High - (s12High - s12Prime)) + (prod1High - s12Prime);

  1068.         // final rounding, s12 may have suffered many cancellations, we try
  1069.         // to recover some bits from the extra words we have saved up to now
  1070.         double result = s12High + (prod1Low + prod2Low + s12Low);

  1071.         if (Double.isNaN(result) || result == 0.0) {
  1072.             // either we have split infinite numbers or some coefficients were NaNs or signed zeros,
  1073.             // just rely on the naive implementation and let IEEE754 handle this
  1074.             // we do this for zeros too as we want to preserve the sign of zero (see issue #76)
  1075.             result = a1 * b1 + a2 * b2;
  1076.         }

  1077.         return result;
  1078.     }

  1079.     /**
  1080.      * Compute a linear combination accurately.
  1081.      * <p>
  1082.      * This method computes a<sub>1</sub>&times;b<sub>1</sub> +
  1083.      * a<sub>2</sub>&times;b<sub>2</sub> + a<sub>3</sub>&times;b<sub>3</sub>
  1084.      * to high accuracy. It does so by using specific multiplication and
  1085.      * addition algorithms to preserve accuracy and reduce cancellation effects.
  1086.      * It is based on the 2005 paper <a
  1087.      * href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.2.1547">
  1088.      * Accurate Sum and Dot Product</a> by Takeshi Ogita,
  1089.      * Siegfried M. Rump, and Shin'ichi Oishi published in SIAM J. Sci. Comput.
  1090.      * </p>
  1091.      * @param a1 first factor of the first term
  1092.      * @param b1 second factor of the first term
  1093.      * @param a2 first factor of the second term
  1094.      * @param b2 second factor of the second term
  1095.      * @param a3 first factor of the third term
  1096.      * @param b3 second factor of the third term
  1097.      * @return a<sub>1</sub>&times;b<sub>1</sub> +
  1098.      * a<sub>2</sub>&times;b<sub>2</sub> + a<sub>3</sub>&times;b<sub>3</sub>
  1099.      * @see #linearCombination(double, double, double, double)
  1100.      * @see #linearCombination(double, double, double, double, double, double, double, double)
  1101.      */
  1102.     public static double linearCombination(final double a1, final double b1,
  1103.                                            final double a2, final double b2,
  1104.                                            final double a3, final double b3) {

  1105.         // the code below is split in many additions/subtractions that may
  1106.         // appear redundant. However, they should NOT be simplified, as they
  1107.         // do use IEEE754 floating point arithmetic rounding properties.
  1108.         // The variables naming conventions are that xyzHigh contains the most significant
  1109.         // bits of xyz and xyzLow contains its least significant bits. So theoretically
  1110.         // xyz is the sum xyzHigh + xyzLow, but in many cases below, this sum cannot
  1111.         // be represented in only one double precision number so we preserve two numbers
  1112.         // to hold it as long as we can, combining the high and low order bits together
  1113.         // only at the end, after cancellation may have occurred on high order bits

  1114.         // split a1 and b1 as one 26 bits number and one 27 bits number
  1115.         final double a1High     = Double.longBitsToDouble(Double.doubleToRawLongBits(a1) & ((-1L) << 27));
  1116.         final double a1Low      = a1 - a1High;
  1117.         final double b1High     = Double.longBitsToDouble(Double.doubleToRawLongBits(b1) & ((-1L) << 27));
  1118.         final double b1Low      = b1 - b1High;

  1119.         // accurate multiplication a1 * b1
  1120.         final double prod1High  = a1 * b1;
  1121.         final double prod1Low   = a1Low * b1Low - (((prod1High - a1High * b1High) - a1Low * b1High) - a1High * b1Low);

  1122.         // split a2 and b2 as one 26 bits number and one 27 bits number
  1123.         final double a2High     = Double.longBitsToDouble(Double.doubleToRawLongBits(a2) & ((-1L) << 27));
  1124.         final double a2Low      = a2 - a2High;
  1125.         final double b2High     = Double.longBitsToDouble(Double.doubleToRawLongBits(b2) & ((-1L) << 27));
  1126.         final double b2Low      = b2 - b2High;

  1127.         // accurate multiplication a2 * b2
  1128.         final double prod2High  = a2 * b2;
  1129.         final double prod2Low   = a2Low * b2Low - (((prod2High - a2High * b2High) - a2Low * b2High) - a2High * b2Low);

  1130.         // split a3 and b3 as one 26 bits number and one 27 bits number
  1131.         final double a3High     = Double.longBitsToDouble(Double.doubleToRawLongBits(a3) & ((-1L) << 27));
  1132.         final double a3Low      = a3 - a3High;
  1133.         final double b3High     = Double.longBitsToDouble(Double.doubleToRawLongBits(b3) & ((-1L) << 27));
  1134.         final double b3Low      = b3 - b3High;

  1135.         // accurate multiplication a3 * b3
  1136.         final double prod3High  = a3 * b3;
  1137.         final double prod3Low   = a3Low * b3Low - (((prod3High - a3High * b3High) - a3Low * b3High) - a3High * b3Low);

  1138.         // accurate addition a1 * b1 + a2 * b2
  1139.         final double s12High    = prod1High + prod2High;
  1140.         final double s12Prime   = s12High - prod2High;
  1141.         final double s12Low     = (prod2High - (s12High - s12Prime)) + (prod1High - s12Prime);

  1142.         // accurate addition a1 * b1 + a2 * b2 + a3 * b3
  1143.         final double s123High   = s12High + prod3High;
  1144.         final double s123Prime  = s123High - prod3High;
  1145.         final double s123Low    = (prod3High - (s123High - s123Prime)) + (s12High - s123Prime);

  1146.         // final rounding, s123 may have suffered many cancellations, we try
  1147.         // to recover some bits from the extra words we have saved up to now
  1148.         double result = s123High + (prod1Low + prod2Low + prod3Low + s12Low + s123Low);

  1149.         if (Double.isNaN(result) || result == 0.0) {
  1150.             // either we have split infinite numbers or some coefficients were NaNs or signed zeros,
  1151.             // just rely on the naive implementation and let IEEE754 handle this
  1152.             // we do this for zeros too as we want to preserve the sign of zero (see issue #76)
  1153.             result = a1 * b1 + a2 * b2 + a3 * b3;
  1154.         }

  1155.         return result;
  1156.     }

  1157.     /**
  1158.      * Compute a linear combination accurately.
  1159.      * <p>
  1160.      * This method computes a<sub>1</sub>&times;b<sub>1</sub> +
  1161.      * a<sub>2</sub>&times;b<sub>2</sub> + a<sub>3</sub>&times;b<sub>3</sub> +
  1162.      * a<sub>4</sub>&times;b<sub>4</sub>
  1163.      * to high accuracy. It does so by using specific multiplication and
  1164.      * addition algorithms to preserve accuracy and reduce cancellation effects.
  1165.      * It is based on the 2005 paper <a
  1166.      * href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.2.1547">
  1167.      * Accurate Sum and Dot Product</a> by Takeshi Ogita,
  1168.      * Siegfried M. Rump, and Shin'ichi Oishi published in SIAM J. Sci. Comput.
  1169.      * </p>
  1170.      * @param a1 first factor of the first term
  1171.      * @param b1 second factor of the first term
  1172.      * @param a2 first factor of the second term
  1173.      * @param b2 second factor of the second term
  1174.      * @param a3 first factor of the third term
  1175.      * @param b3 second factor of the third term
  1176.      * @param a4 first factor of the third term
  1177.      * @param b4 second factor of the third term
  1178.      * @return a<sub>1</sub>&times;b<sub>1</sub> +
  1179.      * a<sub>2</sub>&times;b<sub>2</sub> + a<sub>3</sub>&times;b<sub>3</sub> +
  1180.      * a<sub>4</sub>&times;b<sub>4</sub>
  1181.      * @see #linearCombination(double, double, double, double)
  1182.      * @see #linearCombination(double, double, double, double, double, double)
  1183.      */
  1184.     public static double linearCombination(final double a1, final double b1,
  1185.                                            final double a2, final double b2,
  1186.                                            final double a3, final double b3,
  1187.                                            final double a4, final double b4) {

  1188.         // the code below is split in many additions/subtractions that may
  1189.         // appear redundant. However, they should NOT be simplified, as they
  1190.         // do use IEEE754 floating point arithmetic rounding properties.
  1191.         // The variables naming conventions are that xyzHigh contains the most significant
  1192.         // bits of xyz and xyzLow contains its least significant bits. So theoretically
  1193.         // xyz is the sum xyzHigh + xyzLow, but in many cases below, this sum cannot
  1194.         // be represented in only one double precision number so we preserve two numbers
  1195.         // to hold it as long as we can, combining the high and low order bits together
  1196.         // only at the end, after cancellation may have occurred on high order bits

  1197.         // split a1 and b1 as one 26 bits number and one 27 bits number
  1198.         final double a1High     = Double.longBitsToDouble(Double.doubleToRawLongBits(a1) & ((-1L) << 27));
  1199.         final double a1Low      = a1 - a1High;
  1200.         final double b1High     = Double.longBitsToDouble(Double.doubleToRawLongBits(b1) & ((-1L) << 27));
  1201.         final double b1Low      = b1 - b1High;

  1202.         // accurate multiplication a1 * b1
  1203.         final double prod1High  = a1 * b1;
  1204.         final double prod1Low   = a1Low * b1Low - (((prod1High - a1High * b1High) - a1Low * b1High) - a1High * b1Low);

  1205.         // split a2 and b2 as one 26 bits number and one 27 bits number
  1206.         final double a2High     = Double.longBitsToDouble(Double.doubleToRawLongBits(a2) & ((-1L) << 27));
  1207.         final double a2Low      = a2 - a2High;
  1208.         final double b2High     = Double.longBitsToDouble(Double.doubleToRawLongBits(b2) & ((-1L) << 27));
  1209.         final double b2Low      = b2 - b2High;

  1210.         // accurate multiplication a2 * b2
  1211.         final double prod2High  = a2 * b2;
  1212.         final double prod2Low   = a2Low * b2Low - (((prod2High - a2High * b2High) - a2Low * b2High) - a2High * b2Low);

  1213.         // split a3 and b3 as one 26 bits number and one 27 bits number
  1214.         final double a3High     = Double.longBitsToDouble(Double.doubleToRawLongBits(a3) & ((-1L) << 27));
  1215.         final double a3Low      = a3 - a3High;
  1216.         final double b3High     = Double.longBitsToDouble(Double.doubleToRawLongBits(b3) & ((-1L) << 27));
  1217.         final double b3Low      = b3 - b3High;

  1218.         // accurate multiplication a3 * b3
  1219.         final double prod3High  = a3 * b3;
  1220.         final double prod3Low   = a3Low * b3Low - (((prod3High - a3High * b3High) - a3Low * b3High) - a3High * b3Low);

  1221.         // split a4 and b4 as one 26 bits number and one 27 bits number
  1222.         final double a4High     = Double.longBitsToDouble(Double.doubleToRawLongBits(a4) & ((-1L) << 27));
  1223.         final double a4Low      = a4 - a4High;
  1224.         final double b4High     = Double.longBitsToDouble(Double.doubleToRawLongBits(b4) & ((-1L) << 27));
  1225.         final double b4Low      = b4 - b4High;

  1226.         // accurate multiplication a4 * b4
  1227.         final double prod4High  = a4 * b4;
  1228.         final double prod4Low   = a4Low * b4Low - (((prod4High - a4High * b4High) - a4Low * b4High) - a4High * b4Low);

  1229.         // accurate addition a1 * b1 + a2 * b2
  1230.         final double s12High    = prod1High + prod2High;
  1231.         final double s12Prime   = s12High - prod2High;
  1232.         final double s12Low     = (prod2High - (s12High - s12Prime)) + (prod1High - s12Prime);

  1233.         // accurate addition a1 * b1 + a2 * b2 + a3 * b3
  1234.         final double s123High   = s12High + prod3High;
  1235.         final double s123Prime  = s123High - prod3High;
  1236.         final double s123Low    = (prod3High - (s123High - s123Prime)) + (s12High - s123Prime);

  1237.         // accurate addition a1 * b1 + a2 * b2 + a3 * b3 + a4 * b4
  1238.         final double s1234High  = s123High + prod4High;
  1239.         final double s1234Prime = s1234High - prod4High;
  1240.         final double s1234Low   = (prod4High - (s1234High - s1234Prime)) + (s123High - s1234Prime);

  1241.         // final rounding, s1234 may have suffered many cancellations, we try
  1242.         // to recover some bits from the extra words we have saved up to now
  1243.         double result = s1234High + (prod1Low + prod2Low + prod3Low + prod4Low + s12Low + s123Low + s1234Low);

  1244.         if (Double.isNaN(result) || result == 0.0) {
  1245.             // either we have split infinite numbers or some coefficients were NaNs or signed zeros,
  1246.             // just rely on the naive implementation and let IEEE754 handle this
  1247.             // we do this for zeros too as we want to preserve the sign of zero (see issue #76)
  1248.             result = a1 * b1 + a2 * b2 + a3 * b3 + a4 * b4;
  1249.         }

  1250.         return result;
  1251.     }

  1252.     /**
  1253.      * Returns true iff both arguments are null or have same dimensions and all
  1254.      * their elements are equal as defined by
  1255.      * {@link Precision#equals(float,float)}.
  1256.      *
  1257.      * @param x first array
  1258.      * @param y second array
  1259.      * @return true if the values are both null or have same dimension
  1260.      * and equal elements.
  1261.      */
  1262.     public static boolean equals(float[] x, float[] y) {
  1263.         if ((x == null) || (y == null)) {
  1264.             return !((x == null) ^ (y == null));
  1265.         }
  1266.         if (x.length != y.length) {
  1267.             return false;
  1268.         }
  1269.         for (int i = 0; i < x.length; ++i) {
  1270.             if (!Precision.equals(x[i], y[i])) {
  1271.                 return false;
  1272.             }
  1273.         }
  1274.         return true;
  1275.     }

  1276.     /**
  1277.      * Returns true iff both arguments are null or have same dimensions and all
  1278.      * their elements are equal as defined by
  1279.      * {@link Precision#equalsIncludingNaN(double,double) this method}.
  1280.      *
  1281.      * @param x first array
  1282.      * @param y second array
  1283.      * @return true if the values are both null or have same dimension and
  1284.      * equal elements
  1285.      */
  1286.     public static boolean equalsIncludingNaN(float[] x, float[] y) {
  1287.         if ((x == null) || (y == null)) {
  1288.             return !((x == null) ^ (y == null));
  1289.         }
  1290.         if (x.length != y.length) {
  1291.             return false;
  1292.         }
  1293.         for (int i = 0; i < x.length; ++i) {
  1294.             if (!Precision.equalsIncludingNaN(x[i], y[i])) {
  1295.                 return false;
  1296.             }
  1297.         }
  1298.         return true;
  1299.     }

  1300.     /**
  1301.      * Returns {@code true} iff both arguments are {@code null} or have same
  1302.      * dimensions and all their elements are equal as defined by
  1303.      * {@link Precision#equals(double,double)}.
  1304.      *
  1305.      * @param x First array.
  1306.      * @param y Second array.
  1307.      * @return {@code true} if the values are both {@code null} or have same
  1308.      * dimension and equal elements.
  1309.      */
  1310.     public static boolean equals(double[] x, double[] y) {
  1311.         if ((x == null) || (y == null)) {
  1312.             return !((x == null) ^ (y == null));
  1313.         }
  1314.         if (x.length != y.length) {
  1315.             return false;
  1316.         }
  1317.         for (int i = 0; i < x.length; ++i) {
  1318.             if (!Precision.equals(x[i], y[i])) {
  1319.                 return false;
  1320.             }
  1321.         }
  1322.         return true;
  1323.     }

  1324.     /**
  1325.      * Returns {@code true} iff both arguments are {@code null} or have same
  1326.      * dimensions and all their elements are equal as defined by
  1327.      * {@link Object#equals(Object)}.
  1328.      *
  1329.      * @param <T> type of the field elements
  1330.      * @param x First array.
  1331.      * @param y Second array.
  1332.      * @return {@code true} if the values are both {@code null} or have same
  1333.      * dimension and equal elements.
  1334.      * @since 4.0
  1335.      */
  1336.     public static <T extends FieldElement<T>> boolean equals(T[] x, T[] y) {
  1337.         if ((x == null) || (y == null)) {
  1338.             return !((x == null) ^ (y == null));
  1339.         }
  1340.         if (x.length != y.length) {
  1341.             return false;
  1342.         }
  1343.         for (int i = 0; i < x.length; ++i) {
  1344.             if (!x[i].equals(y[i])) {
  1345.                 return false;
  1346.             }
  1347.         }
  1348.         return true;
  1349.     }

  1350.     /**
  1351.      * Returns {@code true} iff both arguments are {@code null} or have same
  1352.      * dimensions and all their elements are equal as defined by
  1353.      * {@link Precision#equalsIncludingNaN(double,double) this method}.
  1354.      *
  1355.      * @param x First array.
  1356.      * @param y Second array.
  1357.      * @return {@code true} if the values are both {@code null} or have same
  1358.      * dimension and equal elements.
  1359.      */
  1360.     public static boolean equalsIncludingNaN(double[] x, double[] y) {
  1361.         if ((x == null) || (y == null)) {
  1362.             return !((x == null) ^ (y == null));
  1363.         }
  1364.         if (x.length != y.length) {
  1365.             return false;
  1366.         }
  1367.         for (int i = 0; i < x.length; ++i) {
  1368.             if (!Precision.equalsIncludingNaN(x[i], y[i])) {
  1369.                 return false;
  1370.             }
  1371.         }
  1372.         return true;
  1373.     }

  1374.     /**
  1375.      * Returns {@code true} if both arguments are {@code null} or have same
  1376.      * dimensions and all their elements are equals.
  1377.      *
  1378.      * @param x First array.
  1379.      * @param y Second array.
  1380.      * @return {@code true} if the values are both {@code null} or have same
  1381.      * dimension and equal elements.
  1382.      */
  1383.     public static boolean equals(long[] x, long[] y) {
  1384.         if ((x == null) || (y == null)) {
  1385.             return !((x == null) ^ (y == null));
  1386.         }
  1387.         if (x.length != y.length) {
  1388.             return false;
  1389.         }
  1390.         for (int i = 0; i < x.length; ++i) {
  1391.             if (x[i] != y[i]) {
  1392.                 return false;
  1393.             }
  1394.         }
  1395.         return true;
  1396.     }

  1397.     /**
  1398.      * Returns {@code true} if both arguments are {@code null} or have same
  1399.      * dimensions and all their elements are equals.
  1400.      *
  1401.      * @param x First array.
  1402.      * @param y Second array.
  1403.      * @return {@code true} if the values are both {@code null} or have same
  1404.      * dimension and equal elements.
  1405.      */
  1406.     public static boolean equals(int[] x, int[] y) {
  1407.         if ((x == null) || (y == null)) {
  1408.             return !((x == null) ^ (y == null));
  1409.         }
  1410.         if (x.length != y.length) {
  1411.             return false;
  1412.         }
  1413.         for (int i = 0; i < x.length; ++i) {
  1414.             if (x[i] != y[i]) {
  1415.                 return false;
  1416.             }
  1417.         }
  1418.         return true;
  1419.     }

  1420.     /**
  1421.      * Returns {@code true} if both arguments are {@code null} or have same
  1422.      * dimensions and all their elements are equals.
  1423.      *
  1424.      * @param x First array.
  1425.      * @param y Second array.
  1426.      * @return {@code true} if the values are both {@code null} or have same
  1427.      * dimension and equal elements.
  1428.      */
  1429.     public static boolean equals(byte[] x, byte[] y) {
  1430.         if ((x == null) || (y == null)) {
  1431.             return !((x == null) ^ (y == null));
  1432.         }
  1433.         if (x.length != y.length) {
  1434.             return false;
  1435.         }
  1436.         for (int i = 0; i < x.length; ++i) {
  1437.             if (x[i] != y[i]) {
  1438.                 return false;
  1439.             }
  1440.         }
  1441.         return true;
  1442.     }

  1443.     /**
  1444.      * Returns {@code true} if both arguments are {@code null} or have same
  1445.      * dimensions and all their elements are equals.
  1446.      *
  1447.      * @param x First array.
  1448.      * @param y Second array.
  1449.      * @return {@code true} if the values are both {@code null} or have same
  1450.      * dimension and equal elements.
  1451.      */
  1452.     public static boolean equals(short[] x, short[] y) {
  1453.         if ((x == null) || (y == null)) {
  1454.             return !((x == null) ^ (y == null));
  1455.         }
  1456.         if (x.length != y.length) {
  1457.             return false;
  1458.         }
  1459.         for (int i = 0; i < x.length; ++i) {
  1460.             if (x[i] != y[i]) {
  1461.                 return false;
  1462.             }
  1463.         }
  1464.         return true;
  1465.     }

  1466.     /**
  1467.      * Normalizes an array to make it sum to a specified value.
  1468.      * Returns the result of the transformation
  1469.      * <pre>
  1470.      *    x ↦ x * normalizedSum / sum
  1471.      * </pre>
  1472.      * applied to each non-NaN element x of the input array, where sum is the
  1473.      * sum of the non-NaN entries in the input array.
  1474.      * <p>
  1475.      * Throws IllegalArgumentException if {@code normalizedSum} is infinite
  1476.      * or NaN and ArithmeticException if the input array contains any infinite elements
  1477.      * or sums to 0.
  1478.      * <p>
  1479.      * Ignores (i.e., copies unchanged to the output array) NaNs in the input array.
  1480.      * The input array is unchanged by this method.
  1481.      *
  1482.      * @param values Input array to be normalized
  1483.      * @param normalizedSum Target sum for the normalized array
  1484.      * @return the normalized array
  1485.      * @throws MathRuntimeException if the input array contains infinite
  1486.      * elements or sums to zero
  1487.      * @throws MathIllegalArgumentException if the target sum is infinite or {@code NaN}
  1488.      */
  1489.     public static double[] normalizeArray(double[] values, double normalizedSum)
  1490.         throws MathIllegalArgumentException, MathRuntimeException {
  1491.         if (Double.isInfinite(normalizedSum)) {
  1492.             throw new MathIllegalArgumentException(LocalizedCoreFormats.NORMALIZE_INFINITE);
  1493.         }
  1494.         if (Double.isNaN(normalizedSum)) {
  1495.             throw new MathIllegalArgumentException(LocalizedCoreFormats.NORMALIZE_NAN);
  1496.         }
  1497.         double sum = 0d;
  1498.         final int len = values.length;
  1499.         double[] out = new double[len];
  1500.         for (int i = 0; i < len; i++) {
  1501.             if (Double.isInfinite(values[i])) {
  1502.                 throw new MathIllegalArgumentException(LocalizedCoreFormats.INFINITE_ARRAY_ELEMENT, values[i], i);
  1503.             }
  1504.             if (!Double.isNaN(values[i])) {
  1505.                 sum += values[i];
  1506.             }
  1507.         }
  1508.         if (sum == 0) {
  1509.             throw new MathRuntimeException(LocalizedCoreFormats.ARRAY_SUMS_TO_ZERO);
  1510.         }
  1511.         for (int i = 0; i < len; i++) {
  1512.             if (Double.isNaN(values[i])) {
  1513.                 out[i] = Double.NaN;
  1514.             } else {
  1515.                 out[i] = values[i] * normalizedSum / sum;
  1516.             }
  1517.         }
  1518.         return out;
  1519.     }

  1520.     /** Build an array of elements.
  1521.      * <p>
  1522.      * Arrays are filled with {@code field.getZero()}
  1523.      *
  1524.      * @param <T> the type of the field elements
  1525.      * @param field field to which array elements belong
  1526.      * @param length of the array
  1527.      * @return a new array
  1528.      */
  1529.     public static <T extends FieldElement<T>> T[] buildArray(final Field<T> field, final int length) {
  1530.         @SuppressWarnings("unchecked") // OK because field must be correct class
  1531.         T[] array = (T[]) Array.newInstance(field.getRuntimeClass(), length);
  1532.         Arrays.fill(array, field.getZero());
  1533.         return array;
  1534.     }

  1535.     /** Build a double dimension array of elements.
  1536.      * <p>
  1537.      * Arrays are filled with {@code field.getZero()}
  1538.      *
  1539.      * @param <T> the type of the field elements
  1540.      * @param field field to which array elements belong
  1541.      * @param rows number of rows in the array
  1542.      * @param columns number of columns (may be negative to build partial
  1543.      * arrays in the same way {@code new Field[rows][]} works)
  1544.      * @return a new array
  1545.      */
  1546.     @SuppressWarnings("unchecked")
  1547.     public static <T extends FieldElement<T>> T[][] buildArray(final Field<T> field, final int rows, final int columns) {
  1548.         final T[][] array;
  1549.         if (columns < 0) {
  1550.             T[] dummyRow = buildArray(field, 0);
  1551.             array = (T[][]) Array.newInstance(dummyRow.getClass(), rows);
  1552.         } else {
  1553.             array = (T[][]) Array.newInstance(field.getRuntimeClass(), rows, columns);
  1554.             for (int i = 0; i < rows; ++i) {
  1555.                 Arrays.fill(array[i], field.getZero());
  1556.             }
  1557.         }
  1558.         return array;
  1559.     }

  1560.     /** Build a triple dimension array of elements.
  1561.      * <p>
  1562.      * Arrays are filled with {@code field.getZero()}
  1563.      *
  1564.      * @param <T> the type of the field elements
  1565.      * @param field field to which array elements belong
  1566.      * @param l1 number of elements along first dimension
  1567.      * @param l2 number of elements along second dimension
  1568.      * @param l3 number of elements along third dimension (may be negative to build partial
  1569.      * arrays in the same way {@code new Field[l1][l2][]} works)
  1570.      * @return a new array
  1571.      * @since 1.4
  1572.      */
  1573.     @SuppressWarnings("unchecked")
  1574.     public static <T extends FieldElement<T>> T[][][] buildArray(final Field<T> field, final int l1, final int l2, final int l3) {
  1575.         final T[][][] array;
  1576.         if (l3 < 0) {
  1577.             T[] dummyRow = buildArray(field, 0);
  1578.             array = (T[][][]) Array.newInstance(dummyRow.getClass(), l1, l2);
  1579.         } else {
  1580.             array = (T[][][]) Array.newInstance(field.getRuntimeClass(), l1, l2, l3);
  1581.             for (int i = 0; i < l1; ++i) {
  1582.                 for (int j = 0; j < l2; ++j) {
  1583.                     Arrays.fill(array[i][j], field.getZero());
  1584.                 }
  1585.             }
  1586.         }
  1587.         return array;
  1588.     }

  1589.     /**
  1590.      * Calculates the <a href="http://en.wikipedia.org/wiki/Convolution">
  1591.      * convolution</a> between two sequences.
  1592.      * <p>
  1593.      * The solution is obtained via straightforward computation of the
  1594.      * convolution sum (and not via FFT). Whenever the computation needs
  1595.      * an element that would be located at an index outside the input arrays,
  1596.      * the value is assumed to be zero.
  1597.      *
  1598.      * @param x First sequence.
  1599.      * Typically, this sequence will represent an input signal to a system.
  1600.      * @param h Second sequence.
  1601.      * Typically, this sequence will represent the impulse response of the system.
  1602.      * @return the convolution of {@code x} and {@code h}.
  1603.      * This array's length will be {@code x.length + h.length - 1}.
  1604.      * @throws NullArgumentException if either {@code x} or {@code h} is {@code null}.
  1605.      * @throws MathIllegalArgumentException if either {@code x} or {@code h} is empty.
  1606.      */
  1607.     public static double[] convolve(double[] x, double[] h)
  1608.         throws MathIllegalArgumentException, NullArgumentException {
  1609.         MathUtils.checkNotNull(x);
  1610.         MathUtils.checkNotNull(h);

  1611.         final int xLen = x.length;
  1612.         final int hLen = h.length;

  1613.         if (xLen == 0 || hLen == 0) {
  1614.             throw new MathIllegalArgumentException(LocalizedCoreFormats.NO_DATA);
  1615.         }

  1616.         // initialize the output array
  1617.         final int totalLength = xLen + hLen - 1;
  1618.         final double[] y = new double[totalLength];

  1619.         // straightforward implementation of the convolution sum
  1620.         for (int n = 0; n < totalLength; n++) {
  1621.             double yn = 0;
  1622.             int k = FastMath.max(0, n + 1 - xLen);
  1623.             int j = n - k;
  1624.             while (k < hLen && j >= 0) {
  1625.                 yn += x[j--] * h[k++];
  1626.             }
  1627.             y[n] = yn;
  1628.         }

  1629.         return y;
  1630.     }

  1631.     /**
  1632.      * Specification for indicating that some operation applies
  1633.      * before or after a given index.
  1634.      */
  1635.     public enum Position {
  1636.         /** Designates the beginning of the array (near index 0). */
  1637.         HEAD,
  1638.         /** Designates the end of the array. */
  1639.         TAIL
  1640.     }

  1641.     /**
  1642.      * Shuffle the entries of the given array.
  1643.      * The {@code start} and {@code pos} parameters select which portion
  1644.      * of the array is randomized and which is left untouched.
  1645.      *
  1646.      * @see #shuffle(int[],int,Position,RandomGenerator)
  1647.      *
  1648.      * @param list Array whose entries will be shuffled (in-place).
  1649.      * @param start Index at which shuffling begins.
  1650.      * @param pos Shuffling is performed for index positions between
  1651.      * {@code start} and either the end (if {@link Position#TAIL})
  1652.      * or the beginning (if {@link Position#HEAD}) of the array.
  1653.      */
  1654.     public static void shuffle(int[] list,
  1655.                                int start,
  1656.                                Position pos) {
  1657.         shuffle(list, start, pos, new Well19937c());
  1658.     }

  1659.     /**
  1660.      * Shuffle the entries of the given array, using the
  1661.      * <a href="https://en.wikipedia.org/wiki/Fisher-Yates_shuffle#The_modern_algorithm">
  1662.      * Fisher–Yates</a> algorithm.
  1663.      * The {@code start} and {@code pos} parameters select which portion
  1664.      * of the array is randomized and which is left untouched.
  1665.      *
  1666.      * @param list Array whose entries will be shuffled (in-place).
  1667.      * @param start Index at which shuffling begins.
  1668.      * @param pos Shuffling is performed for index positions between
  1669.      * {@code start} and either the end (if {@link Position#TAIL})
  1670.      * or the beginning (if {@link Position#HEAD}) of the array.
  1671.      * @param rng Random number generator.
  1672.      */
  1673.     public static void shuffle(int[] list,
  1674.                                int start,
  1675.                                Position pos,
  1676.                                RandomGenerator rng) {
  1677.         switch (pos) {
  1678.         case TAIL:
  1679.             for (int i = list.length - 1; i > start; i--) {
  1680.                 final int target = start + rng.nextInt(i - start + 1);
  1681.                 final int temp = list[target];
  1682.                 list[target] = list[i];
  1683.                 list[i] = temp;
  1684.             }
  1685.             break;

  1686.         case HEAD:
  1687.             for (int i = 0; i < start; i++) {
  1688.                 final int target = i + rng.nextInt(start - i + 1);
  1689.                 final int temp = list[target];
  1690.                 list[target] = list[i];
  1691.                 list[i] = temp;
  1692.             }
  1693.             break;

  1694.         default:
  1695.             throw MathRuntimeException.createInternalError(); // Should never happen.
  1696.         }
  1697.     }

  1698.     /**
  1699.      * Shuffle the entries of the given array.
  1700.      *
  1701.      * @see #shuffle(int[],int,Position,RandomGenerator)
  1702.      *
  1703.      * @param list Array whose entries will be shuffled (in-place).
  1704.      * @param rng Random number generator.
  1705.      */
  1706.     public static void shuffle(int[] list,
  1707.                                RandomGenerator rng) {
  1708.         shuffle(list, 0, Position.TAIL, rng);
  1709.     }

  1710.     /**
  1711.      * Shuffle the entries of the given array.
  1712.      *
  1713.      * @see #shuffle(int[],int,Position,RandomGenerator)
  1714.      *
  1715.      * @param list Array whose entries will be shuffled (in-place).
  1716.      */
  1717.     public static void shuffle(int[] list) {
  1718.         shuffle(list, new Well19937c());
  1719.     }

  1720.     /**
  1721.      * Returns an array representing the natural number {@code n}.
  1722.      *
  1723.      * @param n Natural number.
  1724.      * @return an array whose entries are the numbers 0, 1, ..., {@code n}-1.
  1725.      * If {@code n == 0}, the returned array is empty.
  1726.      */
  1727.     public static int[] natural(int n) {
  1728.         return sequence(n, 0, 1);
  1729.     }

  1730.     /**
  1731.      * Returns an array of {@code size} integers starting at {@code start},
  1732.      * skipping {@code stride} numbers.
  1733.      *
  1734.      * @param size Natural number.
  1735.      * @param start Natural number.
  1736.      * @param stride Natural number.
  1737.      * @return an array whose entries are the numbers
  1738.      * {@code start, start + stride, ..., start + (size - 1) * stride}.
  1739.      * If {@code size == 0}, the returned array is empty.
  1740.      */
  1741.     public static int[] sequence(int size,
  1742.                                  int start,
  1743.                                  int stride) {
  1744.         final int[] a = new int[size];
  1745.         for (int i = 0; i < size; i++) {
  1746.             a[i] = start + i * stride;
  1747.         }
  1748.         return a;
  1749.     }

  1750.     /**
  1751.      * This method is used
  1752.      * to verify that the input parameters designate a subarray of positive length.
  1753.      * <ul>
  1754.      * <li>returns {@code true} iff the parameters designate a subarray of
  1755.      * positive length</li>
  1756.      * <li>throws {@code MathIllegalArgumentException} if the array is null or
  1757.      * or the indices are invalid</li>
  1758.      * <li>returns {@code false} if the array is non-null, but
  1759.      * {@code length} is 0.</li>
  1760.      * </ul>
  1761.      *
  1762.      * @param values the input array
  1763.      * @param begin index of the first array element to include
  1764.      * @param length the number of elements to include
  1765.      * @return true if the parameters are valid and designate a subarray of positive length
  1766.      * @throws MathIllegalArgumentException if the indices are invalid or the array is null
  1767.      */
  1768.     public static boolean verifyValues(final double[] values, final int begin, final int length)
  1769.             throws MathIllegalArgumentException {
  1770.         return verifyValues(values, begin, length, false);
  1771.     }

  1772.     /**
  1773.      * This method is used
  1774.      * to verify that the input parameters designate a subarray of positive length.
  1775.      * <ul>
  1776.      * <li>returns {@code true} iff the parameters designate a subarray of
  1777.      * non-negative length</li>
  1778.      * <li>throws {@code IllegalArgumentException} if the array is null or
  1779.      * or the indices are invalid</li>
  1780.      * <li>returns {@code false} if the array is non-null, but
  1781.      * {@code length} is 0 unless {@code allowEmpty} is {@code true}</li>
  1782.      * </ul>
  1783.      *
  1784.      * @param values the input array
  1785.      * @param begin index of the first array element to include
  1786.      * @param length the number of elements to include
  1787.      * @param allowEmpty if <code>true</code> then zero length arrays are allowed
  1788.      * @return true if the parameters are valid
  1789.      * @throws MathIllegalArgumentException if the indices are invalid or the array is null
  1790.      */
  1791.     public static boolean verifyValues(final double[] values, final int begin,
  1792.             final int length, final boolean allowEmpty) throws MathIllegalArgumentException {

  1793.         MathUtils.checkNotNull(values, LocalizedCoreFormats.INPUT_ARRAY);

  1794.         if (begin < 0) {
  1795.             throw new MathIllegalArgumentException(LocalizedCoreFormats.START_POSITION, begin);
  1796.         }

  1797.         if (length < 0) {
  1798.             throw new MathIllegalArgumentException(LocalizedCoreFormats.LENGTH, length);
  1799.         }

  1800.         if (begin + length > values.length) {
  1801.             throw new MathIllegalArgumentException(LocalizedCoreFormats.SUBARRAY_ENDS_AFTER_ARRAY_END,
  1802.                     begin + length, values.length, true);
  1803.         }

  1804.         if (length == 0 && !allowEmpty) {
  1805.             return false;
  1806.         }

  1807.         return true;
  1808.     }

  1809.     /**
  1810.      * This method is used
  1811.      * to verify that the begin and length parameters designate a subarray of positive length
  1812.      * and the weights are all non-negative, non-NaN, finite, and not all zero.
  1813.      * <ul>
  1814.      * <li>returns {@code true} iff the parameters designate a subarray of
  1815.      * positive length and the weights array contains legitimate values.</li>
  1816.      * <li>throws {@code IllegalArgumentException} if any of the following are true:
  1817.      * <ul><li>the values array is null</li>
  1818.      *     <li>the weights array is null</li>
  1819.      *     <li>the weights array does not have the same length as the values array</li>
  1820.      *     <li>the weights array contains one or more infinite values</li>
  1821.      *     <li>the weights array contains one or more NaN values</li>
  1822.      *     <li>the weights array contains negative values</li>
  1823.      *     <li>the start and length arguments do not determine a valid array</li></ul>
  1824.      * </li>
  1825.      * <li>returns {@code false} if the array is non-null, but {@code length} is 0.</li>
  1826.      * </ul>
  1827.      *
  1828.      * @param values the input array
  1829.      * @param weights the weights array
  1830.      * @param begin index of the first array element to include
  1831.      * @param length the number of elements to include
  1832.      * @return true if the parameters are valid and designate a subarray of positive length
  1833.      * @throws MathIllegalArgumentException if the indices are invalid or the array is null
  1834.      */
  1835.     public static boolean verifyValues(
  1836.         final double[] values,
  1837.         final double[] weights,
  1838.         final int begin,
  1839.         final int length) throws MathIllegalArgumentException {
  1840.         return verifyValues(values, weights, begin, length, false);
  1841.     }

  1842.     /**
  1843.      * This method is used
  1844.      * to verify that the begin and length parameters designate a subarray of positive length
  1845.      * and the weights are all non-negative, non-NaN, finite, and not all zero.
  1846.      * <ul>
  1847.      * <li>returns {@code true} iff the parameters designate a subarray of
  1848.      * non-negative length and the weights array contains legitimate values.</li>
  1849.      * <li>throws {@code MathIllegalArgumentException} if any of the following are true:
  1850.      * <ul><li>the values array is null</li>
  1851.      *     <li>the weights array is null</li>
  1852.      *     <li>the weights array does not have the same length as the values array</li>
  1853.      *     <li>the weights array contains one or more infinite values</li>
  1854.      *     <li>the weights array contains one or more NaN values</li>
  1855.      *     <li>the weights array contains negative values</li>
  1856.      *     <li>the start and length arguments do not determine a valid array</li></ul>
  1857.      * </li>
  1858.      * <li>returns {@code false} if the array is non-null, but
  1859.      * {@code length} is 0 unless {@code allowEmpty} is {@code true}</li>
  1860.      * </ul>
  1861.      *
  1862.      * @param values the input array.
  1863.      * @param weights the weights array.
  1864.      * @param begin index of the first array element to include.
  1865.      * @param length the number of elements to include.
  1866.      * @param allowEmpty if {@code true} than allow zero length arrays to pass.
  1867.      * @return {@code true} if the parameters are valid.
  1868.      * @throws NullArgumentException if either of the arrays are null
  1869.      * @throws MathIllegalArgumentException if the array indices are not valid,
  1870.      * the weights array contains NaN, infinite or negative elements, or there
  1871.      * are no positive weights.
  1872.      */
  1873.     public static boolean verifyValues(final double[] values, final double[] weights,
  1874.             final int begin, final int length, final boolean allowEmpty) throws MathIllegalArgumentException {

  1875.         MathUtils.checkNotNull(weights, LocalizedCoreFormats.INPUT_ARRAY);
  1876.         MathUtils.checkNotNull(values, LocalizedCoreFormats.INPUT_ARRAY);

  1877.         checkEqualLength(weights, values);

  1878.         boolean containsPositiveWeight = false;
  1879.         for (int i = begin; i < begin + length; i++) {
  1880.             final double weight = weights[i];
  1881.             if (Double.isNaN(weight)) {
  1882.                 throw new MathIllegalArgumentException(LocalizedCoreFormats.NAN_ELEMENT_AT_INDEX, i);
  1883.             }
  1884.             if (Double.isInfinite(weight)) {
  1885.                 throw new MathIllegalArgumentException(LocalizedCoreFormats.INFINITE_ARRAY_ELEMENT, weight, i);
  1886.             }
  1887.             if (weight < 0) {
  1888.                 throw new MathIllegalArgumentException(LocalizedCoreFormats.NEGATIVE_ELEMENT_AT_INDEX, i, weight);
  1889.             }
  1890.             if (!containsPositiveWeight && weight > 0.0) {
  1891.                 containsPositiveWeight = true;
  1892.             }
  1893.         }

  1894.         if (!containsPositiveWeight) {
  1895.             throw new MathIllegalArgumentException(LocalizedCoreFormats.WEIGHT_AT_LEAST_ONE_NON_ZERO);
  1896.         }

  1897.         return verifyValues(values, begin, length, allowEmpty);
  1898.     }

  1899.     /**
  1900.      * Concatenates a sequence of arrays. The return array consists of the
  1901.      * entries of the input arrays concatenated in the order they appear in
  1902.      * the argument list.  Null arrays cause NullPointerExceptions; zero
  1903.      * length arrays are allowed (contributing nothing to the output array).
  1904.      *
  1905.      * @param x list of double[] arrays to concatenate
  1906.      * @return a new array consisting of the entries of the argument arrays
  1907.      * @throws NullPointerException if any of the arrays are null
  1908.      */
  1909.     public static double[] concatenate(double[]... x) {
  1910.         int combinedLength = 0;
  1911.         for (double[] a : x) {
  1912.             combinedLength += a.length;
  1913.         }
  1914.         int offset = 0;
  1915.         final double[] combined = new double[combinedLength];
  1916.         for (double[] doubles : x) {
  1917.             final int curLength = doubles.length;
  1918.             System.arraycopy(doubles, 0, combined, offset, curLength);
  1919.             offset += curLength;
  1920.         }
  1921.         return combined;
  1922.     }

  1923.     /**
  1924.      * Returns an array consisting of the unique values in {@code data}.
  1925.      * The return array is sorted in descending order.  Empty arrays
  1926.      * are allowed, but null arrays result in NullPointerException.
  1927.      * Infinities are allowed.  NaN values are allowed with maximum
  1928.      * sort order - i.e., if there are NaN values in {@code data},
  1929.      * {@code Double.NaN} will be the first element of the output array,
  1930.      * even if the array also contains {@code Double.POSITIVE_INFINITY}.
  1931.      *
  1932.      * @param data array to scan
  1933.      * @return descending list of values included in the input array
  1934.      * @throws NullPointerException if data is null
  1935.      */
  1936.     public static double[] unique(double[] data) {
  1937.         NavigableSet<Double> values = new TreeSet<>();
  1938.         for (double datum : data) {
  1939.             values.add(datum);
  1940.         }
  1941.         final int count = values.size();
  1942.         final double[] out = new double[count];
  1943.         Iterator<Double> iterator = values.descendingIterator();
  1944.         int i = 0;
  1945.         while (iterator.hasNext()) {
  1946.             out[i++] = iterator.next();
  1947.         }
  1948.         return out;
  1949.     }
  1950. }