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.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */

  17. package org.apache.commons.math4.legacy.core;

  18. import java.lang.reflect.Array;
  19. import java.util.Arrays;
  20. import java.util.Iterator;
  21. import java.util.TreeSet;

  22. import org.apache.commons.numbers.core.Precision;
  23. import org.apache.commons.math4.legacy.exception.DimensionMismatchException;
  24. import org.apache.commons.math4.legacy.exception.MathArithmeticException;
  25. import org.apache.commons.math4.legacy.exception.MathIllegalArgumentException;
  26. import org.apache.commons.math4.legacy.exception.MathInternalError;
  27. import org.apache.commons.math4.legacy.exception.NoDataException;
  28. import org.apache.commons.math4.legacy.exception.NonMonotonicSequenceException;
  29. import org.apache.commons.math4.legacy.exception.NotANumberException;
  30. import org.apache.commons.math4.legacy.exception.NotPositiveException;
  31. import org.apache.commons.math4.legacy.exception.NotStrictlyPositiveException;
  32. import org.apache.commons.math4.legacy.exception.NullArgumentException;
  33. import org.apache.commons.math4.legacy.exception.NumberIsTooLargeException;
  34. import org.apache.commons.math4.legacy.exception.NotFiniteNumberException;
  35. import org.apache.commons.math4.legacy.exception.util.LocalizedFormats;
  36. import org.apache.commons.math4.core.jdkmath.JdkMath;

  37. /**
  38.  * Arrays utilities.
  39.  *
  40.  * @since 3.0
  41.  */
  42. public final class MathArrays {

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

  47.     /**
  48.      * Real-valued function that operate on an array or a part of it.
  49.      * @since 3.1
  50.      */
  51.     public interface Function {
  52.         /**
  53.          * Operates on an entire array.
  54.          *
  55.          * @param array Array to operate on.
  56.          * @return the result of the operation.
  57.          */
  58.         double evaluate(double[] array);
  59.         /**
  60.          * @param array Array to operate on.
  61.          * @param startIndex Index of the first element to take into account.
  62.          * @param numElements Number of elements to take into account.
  63.          * @return the result of the operation.
  64.          */
  65.         double evaluate(double[] array,
  66.                         int startIndex,
  67.                         int numElements);
  68.     }

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

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

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

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

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

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

  164.         final double[] result = a.clone();
  165.         for (int i = 0; i < a.length; i++) {
  166.             result[i] /= b[i];
  167.         }
  168.         return result;
  169.     }

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

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

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

  219.     /**
  220.      * Calculates the L<sub>2</sub> (Euclidean) distance between two points.
  221.      *
  222.      * @param p1 the first point
  223.      * @param p2 the second point
  224.      * @return the L<sub>2</sub> distance between the two points
  225.      * @throws DimensionMismatchException if the array lengths differ.
  226.      */
  227.     public static double distance(int[] p1, int[] p2) {
  228.         checkEqualLength(p1, p2);
  229.         double sum = 0;
  230.         for (int i = 0; i < p1.length; i++) {
  231.             final double dp = (double) p1[i] - p2[i];
  232.             sum += dp * dp;
  233.         }
  234.         return JdkMath.sqrt(sum);
  235.     }

  236.     /**
  237.      * Calculates the L<sub>&infin;</sub> (max of abs) distance between two points.
  238.      *
  239.      * @param p1 the first point
  240.      * @param p2 the second point
  241.      * @return the L<sub>&infin;</sub> distance between the two points
  242.      * @throws DimensionMismatchException if the array lengths differ.
  243.      */
  244.     public static double distanceInf(double[] p1, double[] p2) {
  245.         checkEqualLength(p1, p2);
  246.         double max = 0;
  247.         for (int i = 0; i < p1.length; i++) {
  248.             max = JdkMath.max(max, JdkMath.abs(p1[i] - p2[i]));
  249.         }
  250.         return max;
  251.     }

  252.     /**
  253.      * Calculates the L<sub>&infin;</sub> (max of abs) distance between two points.
  254.      *
  255.      * @param p1 the first point
  256.      * @param p2 the second point
  257.      * @return the L<sub>&infin;</sub> distance between the two points
  258.      * @throws DimensionMismatchException if the array lengths differ.
  259.      */
  260.     public static int distanceInf(int[] p1, int[] p2) {
  261.         checkEqualLength(p1, p2);
  262.         int max = 0;
  263.         for (int i = 0; i < p1.length; i++) {
  264.             max = JdkMath.max(max, JdkMath.abs(p1[i] - p2[i]));
  265.         }
  266.         return max;
  267.     }

  268.     /**
  269.      * Specification of ordering direction.
  270.      */
  271.     public enum OrderDirection {
  272.         /** Constant for increasing direction. */
  273.         INCREASING,
  274.         /** Constant for decreasing direction. */
  275.         DECREASING
  276.     }

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

  322.             previous = val[i];
  323.         }
  324.         return true;
  325.     }

  326.     /**
  327.      * Check that an array is monotonically increasing or decreasing.
  328.      *
  329.      * @param val Values.
  330.      * @param dir Ordering direction.
  331.      * @param strict Whether the order should be strict.
  332.      * @return {@code true} if sorted, {@code false} otherwise.
  333.      */
  334.     public static boolean isMonotonic(double[] val, OrderDirection dir, boolean strict) {
  335.         return checkOrder(val, dir, strict, false);
  336.     }

  337.     /**
  338.      * Check that both arrays have the same length.
  339.      *
  340.      * @param a Array.
  341.      * @param b Array.
  342.      * @param abort Whether to throw an exception if the check fails.
  343.      * @return {@code true} if the arrays have the same length.
  344.      * @throws DimensionMismatchException if the lengths differ and
  345.      * {@code abort} is {@code true}.
  346.      * @since 3.6
  347.      */
  348.     public static boolean checkEqualLength(double[] a,
  349.                                            double[] b,
  350.                                            boolean abort) {
  351.         if (a.length == b.length) {
  352.             return true;
  353.         } else {
  354.             if (abort) {
  355.                 throw new DimensionMismatchException(a.length, b.length);
  356.             }
  357.             return false;
  358.         }
  359.     }

  360.     /**
  361.      * Check that both arrays have the same length.
  362.      *
  363.      * @param a Array.
  364.      * @param b Array.
  365.      * @throws DimensionMismatchException if the lengths differ.
  366.      * @since 3.6
  367.      */
  368.     public static void checkEqualLength(double[] a,
  369.                                         double[] b) {
  370.         checkEqualLength(a, b, true);
  371.     }


  372.     /**
  373.      * Check that both arrays have the same length.
  374.      *
  375.      * @param a Array.
  376.      * @param b Array.
  377.      * @param abort Whether to throw an exception if the check fails.
  378.      * @return {@code true} if the arrays have the same length.
  379.      * @throws DimensionMismatchException if the lengths differ and
  380.      * {@code abort} is {@code true}.
  381.      * @since 3.6
  382.      */
  383.     public static boolean checkEqualLength(int[] a,
  384.                                            int[] b,
  385.                                            boolean abort) {
  386.         if (a.length == b.length) {
  387.             return true;
  388.         } else {
  389.             if (abort) {
  390.                 throw new DimensionMismatchException(a.length, b.length);
  391.             }
  392.             return false;
  393.         }
  394.     }

  395.     /**
  396.      * Check that both arrays have the same length.
  397.      *
  398.      * @param a Array.
  399.      * @param b Array.
  400.      * @throws DimensionMismatchException if the lengths differ.
  401.      * @since 3.6
  402.      */
  403.     public static void checkEqualLength(int[] a,
  404.                                         int[] b) {
  405.         checkEqualLength(a, b, true);
  406.     }

  407.     /**
  408.      * Check that the given array is sorted.
  409.      *
  410.      * @param val Values.
  411.      * @param dir Ordering direction.
  412.      * @param strict Whether the order should be strict.
  413.      * @param abort Whether to throw an exception if the check fails.
  414.      * @return {@code true} if the array is sorted.
  415.      * @throws NonMonotonicSequenceException if the array is not sorted
  416.      * and {@code abort} is {@code true}.
  417.      */
  418.     public static boolean checkOrder(double[] val, OrderDirection dir,
  419.                                      boolean strict, boolean abort) {
  420.         double previous = val[0];
  421.         final int max = val.length;

  422.         int index;
  423.         ITEM:
  424.         for (index = 1; index < max; index++) {
  425.             switch (dir) {
  426.             case INCREASING:
  427.                 if (strict) {
  428.                     if (val[index] <= previous) {
  429.                         break ITEM;
  430.                     }
  431.                 } else {
  432.                     if (val[index] < previous) {
  433.                         break ITEM;
  434.                     }
  435.                 }
  436.                 break;
  437.             case DECREASING:
  438.                 if (strict) {
  439.                     if (val[index] >= previous) {
  440.                         break ITEM;
  441.                     }
  442.                 } else {
  443.                     if (val[index] > previous) {
  444.                         break ITEM;
  445.                     }
  446.                 }
  447.                 break;
  448.             default:
  449.                 // Should never happen.
  450.                 throw new MathInternalError();
  451.             }

  452.             previous = val[index];
  453.         }

  454.         if (index == max) {
  455.             // Loop completed.
  456.             return true;
  457.         }

  458.         // Loop early exit means wrong ordering.
  459.         if (abort) {
  460.             throw new NonMonotonicSequenceException(val[index],
  461.                                                     previous,
  462.                                                     index,
  463.                                                     dir == OrderDirection.INCREASING,
  464.                                                     strict);
  465.         } else {
  466.             return false;
  467.         }
  468.     }

  469.     /**
  470.      * Check that the given array is sorted.
  471.      *
  472.      * @param val Values.
  473.      * @param dir Ordering direction.
  474.      * @param strict Whether the order should be strict.
  475.      * @throws NonMonotonicSequenceException if the array is not sorted.
  476.      * @since 2.2
  477.      */
  478.     public static void checkOrder(double[] val, OrderDirection dir, boolean strict) {
  479.         checkOrder(val, dir, strict, true);
  480.     }

  481.     /**
  482.      * Check that the given array is sorted in strictly increasing order.
  483.      *
  484.      * @param val Values.
  485.      * @throws NonMonotonicSequenceException if the array is not sorted.
  486.      * @since 2.2
  487.      */
  488.     public static void checkOrder(double[] val) {
  489.         checkOrder(val, OrderDirection.INCREASING, true);
  490.     }

  491.     /**
  492.      * Throws DimensionMismatchException if the input array is not rectangular.
  493.      *
  494.      * @param in array to be tested
  495.      * @throws NullArgumentException if input array is null
  496.      * @throws DimensionMismatchException if input array is not rectangular
  497.      * @since 3.1
  498.      */
  499.     public static void checkRectangular(final long[][] in) {
  500.         NullArgumentException.check(in);
  501.         for (int i = 1; i < in.length; i++) {
  502.             if (in[i].length != in[0].length) {
  503.                 throw new DimensionMismatchException(
  504.                         LocalizedFormats.DIFFERENT_ROWS_LENGTHS,
  505.                         in[i].length, in[0].length);
  506.             }
  507.         }
  508.     }

  509.     /**
  510.      * Check that all entries of the input array are strictly positive.
  511.      *
  512.      * @param in Array to be tested
  513.      * @throws NotStrictlyPositiveException if any entries of the array are not
  514.      * strictly positive.
  515.      * @since 3.1
  516.      */
  517.     public static void checkPositive(final double[] in) {
  518.         for (double x : in) {
  519.             if (x <= 0) {
  520.                 throw new NotStrictlyPositiveException(x);
  521.             }
  522.         }
  523.     }

  524.     /**
  525.      * Check that no entry of the input array is {@code NaN}.
  526.      *
  527.      * @param in Array to be tested.
  528.      * @throws NotANumberException if an entry is {@code NaN}.
  529.      * @since 3.4
  530.      */
  531.     public static void checkNotNaN(final double[] in) {
  532.         for (double x : in) {
  533.             if (Double.isNaN(x)) {
  534.                 throw new NotANumberException();
  535.             }
  536.         }
  537.     }

  538.     /**
  539.      * Check that all the elements are real numbers.
  540.      *
  541.      * @param val Arguments.
  542.      * @throws NotFiniteNumberException if any values of the array is not a
  543.      * finite real number.
  544.      */
  545.     public static void checkFinite(final double[] val) {
  546.         for (double x : val) {
  547.             if (!Double.isFinite(x)) {
  548.                 throw new NotFiniteNumberException(x);
  549.             }
  550.         }
  551.     }

  552.     /**
  553.      * Check that all entries of the input array are &gt;= 0.
  554.      *
  555.      * @param in Array to be tested
  556.      * @throws NotPositiveException if any array entries are less than 0.
  557.      * @since 3.1
  558.      */
  559.     public static void checkNonNegative(final long[] in) {
  560.         for (long i : in) {
  561.             if (i < 0) {
  562.                 throw new NotPositiveException(i);
  563.             }
  564.         }
  565.     }

  566.     /**
  567.      * Check all entries of the input array are &gt;= 0.
  568.      *
  569.      * @param in Array to be tested
  570.      * @throws NotPositiveException if any array entries are less than 0.
  571.      * @since 3.1
  572.      */
  573.     public static void checkNonNegative(final long[][] in) {
  574.         for (int i = 0; i < in.length; i++) {
  575.             for (int j = 0; j < in[i].length; j++) {
  576.                 if (in[i][j] < 0) {
  577.                     throw new NotPositiveException(in[i][j]);
  578.                 }
  579.             }
  580.         }
  581.     }

  582.     /**
  583.      * Returns true iff both arguments are null or have same dimensions and all
  584.      * their elements are equal as defined by
  585.      * {@link Precision#equals(float,float)}.
  586.      *
  587.      * @param x first array
  588.      * @param y second array
  589.      * @return true if the values are both null or have same dimension
  590.      * and equal elements.
  591.      */
  592.     public static boolean equals(float[] x, float[] y) {
  593.         if (x == null || y == null) {
  594.             return (x == null) == (y == null);
  595.         }
  596.         if (x.length != y.length) {
  597.             return false;
  598.         }
  599.         for (int i = 0; i < x.length; ++i) {
  600.             if (!Precision.equals(x[i], y[i])) {
  601.                 return false;
  602.             }
  603.         }
  604.         return true;
  605.     }

  606.     /**
  607.      * Returns true iff both arguments are null or have same dimensions and all
  608.      * their elements are equal as defined by
  609.      * {@link Precision#equalsIncludingNaN(double,double) this method}.
  610.      *
  611.      * @param x first array
  612.      * @param y second array
  613.      * @return true if the values are both null or have same dimension and
  614.      * equal elements
  615.      * @since 2.2
  616.      */
  617.     public static boolean equalsIncludingNaN(float[] x, float[] y) {
  618.         if (x == null || y == null) {
  619.             return (x == null) == (y == null);
  620.         }
  621.         if (x.length != y.length) {
  622.             return false;
  623.         }
  624.         for (int i = 0; i < x.length; ++i) {
  625.             if (!Precision.equalsIncludingNaN(x[i], y[i])) {
  626.                 return false;
  627.             }
  628.         }
  629.         return true;
  630.     }

  631.     /**
  632.      * Returns {@code true} iff both arguments are {@code null} or have same
  633.      * dimensions and all their elements are equal as defined by
  634.      * {@link Precision#equals(double,double)}.
  635.      *
  636.      * @param x First array.
  637.      * @param y Second array.
  638.      * @return {@code true} if the values are both {@code null} or have same
  639.      * dimension and equal elements.
  640.      */
  641.     public static boolean equals(double[] x, double[] y) {
  642.         if (x == null || y == null) {
  643.             return (x == null) == (y == null);
  644.         }
  645.         if (x.length != y.length) {
  646.             return false;
  647.         }
  648.         for (int i = 0; i < x.length; ++i) {
  649.             if (!Precision.equals(x[i], y[i])) {
  650.                 return false;
  651.             }
  652.         }
  653.         return true;
  654.     }

  655.     /**
  656.      * Returns {@code true} iff both arguments are {@code null} or have same
  657.      * dimensions and all their elements are equal as defined by
  658.      * {@link Precision#equalsIncludingNaN(double,double) this method}.
  659.      *
  660.      * @param x First array.
  661.      * @param y Second array.
  662.      * @return {@code true} if the values are both {@code null} or have same
  663.      * dimension and equal elements.
  664.      * @since 2.2
  665.      */
  666.     public static boolean equalsIncludingNaN(double[] x, double[] y) {
  667.         if (x == null || y == null) {
  668.             return (x == null) == (y == null);
  669.         }
  670.         if (x.length != y.length) {
  671.             return false;
  672.         }
  673.         for (int i = 0; i < x.length; ++i) {
  674.             if (!Precision.equalsIncludingNaN(x[i], y[i])) {
  675.                 return false;
  676.             }
  677.         }
  678.         return true;
  679.     }

  680.     /**
  681.      * Normalizes an array to make it sum to a specified value.
  682.      * Returns the result of the transformation
  683.      * <pre>
  684.      *    x |-&gt; x * normalizedSum / sum
  685.      * </pre>
  686.      * applied to each non-NaN element x of the input array, where sum is the
  687.      * sum of the non-NaN entries in the input array.
  688.      * <p>
  689.      * Throws IllegalArgumentException if {@code normalizedSum} is infinite
  690.      * or NaN and ArithmeticException if the input array contains any infinite elements
  691.      * or sums to 0.
  692.      * <p>
  693.      * Ignores (i.e., copies unchanged to the output array) NaNs in the input array.
  694.      *
  695.      * @param values Input array to be normalized
  696.      * @param normalizedSum Target sum for the normalized array
  697.      * @return the normalized array.
  698.      * @throws MathArithmeticException if the input array contains infinite
  699.      * elements or sums to zero.
  700.      * @throws MathIllegalArgumentException if the target sum is infinite or {@code NaN}.
  701.      * @since 2.1
  702.      */
  703.     public static double[] normalizeArray(double[] values, double normalizedSum) {
  704.         if (Double.isInfinite(normalizedSum)) {
  705.             throw new MathIllegalArgumentException(LocalizedFormats.NORMALIZE_INFINITE);
  706.         }
  707.         if (Double.isNaN(normalizedSum)) {
  708.             throw new MathIllegalArgumentException(LocalizedFormats.NORMALIZE_NAN);
  709.         }
  710.         double sum = 0d;
  711.         final int len = values.length;
  712.         double[] out = new double[len];
  713.         for (int i = 0; i < len; i++) {
  714.             if (Double.isInfinite(values[i])) {
  715.                 throw new MathIllegalArgumentException(LocalizedFormats.INFINITE_ARRAY_ELEMENT, values[i], i);
  716.             }
  717.             if (!Double.isNaN(values[i])) {
  718.                 sum += values[i];
  719.             }
  720.         }
  721.         if (sum == 0) {
  722.             throw new MathArithmeticException(LocalizedFormats.ARRAY_SUMS_TO_ZERO);
  723.         }
  724.         final double scale = normalizedSum / sum;
  725.         for (int i = 0; i < len; i++) {
  726.             if (Double.isNaN(values[i])) {
  727.                 out[i] = Double.NaN;
  728.             } else {
  729.                 out[i] = values[i] * scale;
  730.             }
  731.         }
  732.         return out;
  733.     }

  734.     /** Build an array of elements.
  735.      * <p>
  736.      * Arrays are filled with field.getZero()
  737.      *
  738.      * @param <T> the type of the field elements
  739.      * @param field field to which array elements belong
  740.      * @param length of the array
  741.      * @return a new array
  742.      * @since 3.2
  743.      */
  744.     public static <T> T[] buildArray(final Field<T> field, final int length) {
  745.         @SuppressWarnings("unchecked") // OK because field must be correct class
  746.         T[] array = (T[]) Array.newInstance(field.getRuntimeClass(), length);
  747.         Arrays.fill(array, field.getZero());
  748.         return array;
  749.     }

  750.     /** Build a double dimension  array of elements.
  751.      * <p>
  752.      * Arrays are filled with field.getZero()
  753.      *
  754.      * @param <T> the type of the field elements
  755.      * @param field field to which array elements belong
  756.      * @param rows number of rows in the array
  757.      * @param columns number of columns (may be negative to build partial
  758.      * arrays in the same way <code>new Field[rows][]</code> works)
  759.      * @return a new array
  760.      * @since 3.2
  761.      */
  762.     @SuppressWarnings("unchecked")
  763.     public static <T> T[][] buildArray(final Field<T> field, final int rows, final int columns) {
  764.         final T[][] array;
  765.         if (columns < 0) {
  766.             T[] dummyRow = buildArray(field, 0);
  767.             array = (T[][]) Array.newInstance(dummyRow.getClass(), rows);
  768.         } else {
  769.             array = (T[][]) Array.newInstance(field.getRuntimeClass(),
  770.                                               rows, columns);
  771.             for (int i = 0; i < rows; ++i) {
  772.                 Arrays.fill(array[i], field.getZero());
  773.             }
  774.         }
  775.         return array;
  776.     }

  777.     /**
  778.      * Calculates the <a href="http://en.wikipedia.org/wiki/Convolution">
  779.      * convolution</a> between two sequences.
  780.      * <p>
  781.      * The solution is obtained via straightforward computation of the
  782.      * convolution sum (and not via FFT). Whenever the computation needs
  783.      * an element that would be located at an index outside the input arrays,
  784.      * the value is assumed to be zero.
  785.      *
  786.      * @param x First sequence.
  787.      * Typically, this sequence will represent an input signal to a system.
  788.      * @param h Second sequence.
  789.      * Typically, this sequence will represent the impulse response of the system.
  790.      * @return the convolution of {@code x} and {@code h}.
  791.      * This array's length will be {@code x.length + h.length - 1}.
  792.      * @throws NullArgumentException if either {@code x} or {@code h} is {@code null}.
  793.      * @throws NoDataException if either {@code x} or {@code h} is empty.
  794.      *
  795.      * @since 3.3
  796.      */
  797.     public static double[] convolve(double[] x, double[] h) {
  798.         NullArgumentException.check(x);
  799.         NullArgumentException.check(h);

  800.         final int xLen = x.length;
  801.         final int hLen = h.length;

  802.         if (xLen == 0 || hLen == 0) {
  803.             throw new NoDataException();
  804.         }

  805.         // initialize the output array
  806.         final int totalLength = xLen + hLen - 1;
  807.         final double[] y = new double[totalLength];

  808.         // straightforward implementation of the convolution sum
  809.         for (int n = 0; n < totalLength; n++) {
  810.             double yn = 0;
  811.             int k = JdkMath.max(0, n + 1 - xLen);
  812.             int j = n - k;
  813.             while (k < hLen && j >= 0) {
  814.                 yn += x[j--] * h[k++];
  815.             }
  816.             y[n] = yn;
  817.         }

  818.         return y;
  819.     }

  820.     /**
  821.      * Returns an array representing the natural number {@code n}.
  822.      *
  823.      * @param n Natural number.
  824.      * @return an array whose entries are the numbers 0, 1, ..., {@code n}-1.
  825.      * If {@code n == 0}, the returned array is empty.
  826.      */
  827.     public static int[] natural(int n) {
  828.         return sequence(n, 0, 1);
  829.     }
  830.     /**
  831.      * Returns an array of {@code size} integers starting at {@code start},
  832.      * skipping {@code stride} numbers.
  833.      *
  834.      * @param size Natural number.
  835.      * @param start Natural number.
  836.      * @param stride Natural number.
  837.      * @return an array whose entries are the numbers
  838.      * {@code start, start + stride, ..., start + (size - 1) * stride}.
  839.      * If {@code size == 0}, the returned array is empty.
  840.      *
  841.      * @since 3.4
  842.      */
  843.     public static int[] sequence(int size,
  844.                                  int start,
  845.                                  int stride) {
  846.         final int[] a = new int[size];
  847.         for (int i = 0; i < size; i++) {
  848.             a[i] = start + i * stride;
  849.         }
  850.         return a;
  851.     }
  852.     /**
  853.      * This method is used
  854.      * to verify that the input parameters designate a subarray of positive length.
  855.      * <ul>
  856.      * <li>returns <code>true</code> iff the parameters designate a subarray of
  857.      * positive length</li>
  858.      * <li>throws <code>MathIllegalArgumentException</code> if the array is null or
  859.      * or the indices are invalid</li>
  860.      * <li>returns <code>false</code> if the array is non-null, but
  861.      * <code>length</code> is 0.</li>
  862.      * </ul>
  863.      *
  864.      * @param values the input array
  865.      * @param begin index of the first array element to include
  866.      * @param length the number of elements to include
  867.      * @return true if the parameters are valid and designate a subarray of positive length
  868.      * @throws MathIllegalArgumentException if the indices are invalid or the array is null
  869.      * @since 3.3
  870.      */
  871.     public static boolean verifyValues(final double[] values, final int begin, final int length) {
  872.         return verifyValues(values, begin, length, false);
  873.     }

  874.     /**
  875.      * This method is used
  876.      * to verify that the input parameters designate a subarray of positive length.
  877.      * <ul>
  878.      * <li>returns <code>true</code> iff the parameters designate a subarray of
  879.      * non-negative length</li>
  880.      * <li>throws <code>IllegalArgumentException</code> if the array is null or
  881.      * or the indices are invalid</li>
  882.      * <li>returns <code>false</code> if the array is non-null, but
  883.      * <code>length</code> is 0 unless <code>allowEmpty</code> is <code>true</code></li>
  884.      * </ul>
  885.      *
  886.      * @param values the input array
  887.      * @param begin index of the first array element to include
  888.      * @param length the number of elements to include
  889.      * @param allowEmpty if <code>true</code> then zero length arrays are allowed
  890.      * @return true if the parameters are valid
  891.      * @throws MathIllegalArgumentException if the indices are invalid or the array is null
  892.      * @since 3.3
  893.      */
  894.     public static boolean verifyValues(final double[] values, final int begin,
  895.                                        final int length, final boolean allowEmpty) {

  896.         if (values == null) {
  897.             throw new NullArgumentException(LocalizedFormats.INPUT_ARRAY);
  898.         }

  899.         if (begin < 0) {
  900.             throw new NotPositiveException(LocalizedFormats.START_POSITION, Integer.valueOf(begin));
  901.         }

  902.         if (length < 0) {
  903.             throw new NotPositiveException(LocalizedFormats.LENGTH, Integer.valueOf(length));
  904.         }

  905.         if (begin + length > values.length) {
  906.             throw new NumberIsTooLargeException(LocalizedFormats.SUBARRAY_ENDS_AFTER_ARRAY_END,
  907.                     Integer.valueOf(begin + length), Integer.valueOf(values.length), true);
  908.         }

  909.         return !(length == 0 && !allowEmpty);
  910.     }

  911.     /**
  912.      * This method is used
  913.      * to verify that the begin and length parameters designate a subarray of positive length
  914.      * and the weights are all non-negative, non-NaN, finite, and not all zero.
  915.      * <ul>
  916.      * <li>returns <code>true</code> iff the parameters designate a subarray of
  917.      * positive length and the weights array contains legitimate values.</li>
  918.      * <li>throws <code>IllegalArgumentException</code> if any of the following are true:
  919.      * <ul><li>the values array is null</li>
  920.      *     <li>the weights array is null</li>
  921.      *     <li>the weights array does not have the same length as the values array</li>
  922.      *     <li>the weights array contains one or more infinite values</li>
  923.      *     <li>the weights array contains one or more NaN values</li>
  924.      *     <li>the weights array contains negative values</li>
  925.      *     <li>the weights array does not contain at least one non-zero value (applies when length is non zero)</li>
  926.      *     <li>the start and length arguments do not determine a valid array</li></ul>
  927.      * </li>
  928.      * <li>returns <code>false</code> if the array is non-null, but
  929.      * <code>length</code> is 0.</li>
  930.      * </ul>
  931.      *
  932.      * @param values the input array
  933.      * @param weights the weights array
  934.      * @param begin index of the first array element to include
  935.      * @param length the number of elements to include
  936.      * @return true if the parameters are valid and designate a subarray of positive length
  937.      * @throws MathIllegalArgumentException if the indices are invalid or the array is null
  938.      * @since 3.3
  939.      */
  940.     public static boolean verifyValues(
  941.         final double[] values,
  942.         final double[] weights,
  943.         final int begin,
  944.         final int length) {
  945.         return verifyValues(values, weights, begin, length, false);
  946.     }

  947.     /**
  948.      * This method is used
  949.      * to verify that the begin and length parameters designate a subarray of positive length
  950.      * and the weights are all non-negative, non-NaN, finite, and not all zero.
  951.      * <ul>
  952.      * <li>returns <code>true</code> iff the parameters designate a subarray of
  953.      * non-negative length and the weights array contains legitimate values.</li>
  954.      * <li>throws <code>MathIllegalArgumentException</code> if any of the following are true:
  955.      * <ul><li>the values array is null</li>
  956.      *     <li>the weights array is null</li>
  957.      *     <li>the weights array does not have the same length as the values array</li>
  958.      *     <li>the weights array contains one or more infinite values</li>
  959.      *     <li>the weights array contains one or more NaN values</li>
  960.      *     <li>the weights array contains negative values</li>
  961.      *     <li>the weights array does not contain at least one non-zero value (applies when length is non zero)</li>
  962.      *     <li>the start and length arguments do not determine a valid array</li></ul>
  963.      * </li>
  964.      * <li>returns <code>false</code> if the array is non-null, but
  965.      * <code>length</code> is 0 unless <code>allowEmpty</code> is <code>true</code>.</li>
  966.      * </ul>
  967.      *
  968.      * @param values the input array.
  969.      * @param weights the weights array.
  970.      * @param begin index of the first array element to include.
  971.      * @param length the number of elements to include.
  972.      * @param allowEmpty if {@code true} than allow zero length arrays to pass.
  973.      * @return {@code true} if the parameters are valid.
  974.      * @throws NullArgumentException if either of the arrays are null
  975.      * @throws MathIllegalArgumentException if the array indices are not valid,
  976.      * the weights array contains NaN, infinite or negative elements, or there
  977.      * are no positive weights.
  978.      * @since 3.3
  979.      */
  980.     public static boolean verifyValues(final double[] values, final double[] weights,
  981.                                        final int begin, final int length, final boolean allowEmpty) {

  982.         if (weights == null || values == null) {
  983.             throw new NullArgumentException(LocalizedFormats.INPUT_ARRAY);
  984.         }

  985.         checkEqualLength(weights, values);

  986.         if (length != 0) {
  987.             boolean containsPositiveWeight = false;
  988.             for (int i = begin; i < begin + length; i++) {
  989.                 final double weight = weights[i];
  990.                 if (Double.isNaN(weight)) {
  991.                     throw new MathIllegalArgumentException(LocalizedFormats.NAN_ELEMENT_AT_INDEX, Integer.valueOf(i));
  992.                 }
  993.                 if (Double.isInfinite(weight)) {
  994.                     throw new MathIllegalArgumentException(LocalizedFormats.INFINITE_ARRAY_ELEMENT,
  995.                         Double.valueOf(weight), Integer.valueOf(i));
  996.                 }
  997.                 if (weight < 0) {
  998.                     throw new MathIllegalArgumentException(LocalizedFormats.NEGATIVE_ELEMENT_AT_INDEX,
  999.                         Integer.valueOf(i), Double.valueOf(weight));
  1000.                 }
  1001.                 if (!containsPositiveWeight && weight > 0.0) {
  1002.                     containsPositiveWeight = true;
  1003.                 }
  1004.             }

  1005.             if (!containsPositiveWeight) {
  1006.                 throw new MathIllegalArgumentException(LocalizedFormats.WEIGHT_AT_LEAST_ONE_NON_ZERO);
  1007.             }
  1008.         }

  1009.         return verifyValues(values, begin, length, allowEmpty);
  1010.     }

  1011.     /**
  1012.      * Concatenates a sequence of arrays. The return array consists of the
  1013.      * entries of the input arrays concatenated in the order they appear in
  1014.      * the argument list.  Null arrays cause NullPointerExceptions; zero
  1015.      * length arrays are allowed (contributing nothing to the output array).
  1016.      *
  1017.      * @param x list of double[] arrays to concatenate
  1018.      * @return a new array consisting of the entries of the argument arrays
  1019.      * @throws NullPointerException if any of the arrays are null
  1020.      * @since 3.6
  1021.      */
  1022.     public static double[] concatenate(double[]... x) {
  1023.         int combinedLength = 0;
  1024.         for (double[] a : x) {
  1025.             combinedLength += a.length;
  1026.         }
  1027.         int offset = 0;
  1028.         int curLength = 0;
  1029.         final double[] combined = new double[combinedLength];
  1030.         for (int i = 0; i < x.length; i++) {
  1031.             curLength = x[i].length;
  1032.             System.arraycopy(x[i], 0, combined, offset, curLength);
  1033.             offset += curLength;
  1034.         }
  1035.         return combined;
  1036.     }

  1037.     /**
  1038.      * Returns an array consisting of the unique values in {@code data}.
  1039.      * The return array is sorted in descending order.  Empty arrays
  1040.      * are allowed, but null arrays result in NullPointerException.
  1041.      * Infinities are allowed.  NaN values are allowed with maximum
  1042.      * sort order - i.e., if there are NaN values in {@code data},
  1043.      * {@code Double.NaN} will be the first element of the output array,
  1044.      * even if the array also contains {@code Double.POSITIVE_INFINITY}.
  1045.      *
  1046.      * @param data array to scan
  1047.      * @return descending list of values included in the input array
  1048.      * @throws NullPointerException if data is null
  1049.      * @since 3.6
  1050.      */
  1051.     public static double[] unique(double[] data) {
  1052.         TreeSet<Double> values = new TreeSet<>();
  1053.         for (int i = 0; i < data.length; i++) {
  1054.             values.add(data[i]);
  1055.         }
  1056.         final int count = values.size();
  1057.         final double[] out = new double[count];
  1058.         Iterator<Double> iterator = values.descendingIterator();
  1059.         int i = 0;
  1060.         while (iterator.hasNext()) {
  1061.             out[i++] = iterator.next();
  1062.         }
  1063.         return out;
  1064.     }
  1065. }