Development Class Java

/*
 * LingPipe v. 3.9
 * Copyright (C) 2003-2010 Alias-i
 *
 * This program is licensed under the Alias-i Royalty Free License
 * Version 1 WITHOUT ANY WARRANTY, without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the Alias-i
 * Royalty Free License Version 1 for more details.
 *
 * You should have received a copy of the Alias-i Royalty Free License
 * Version 1 along with this program; if not, visit
 * http://alias-i.com/lingpipe/licenses/lingpipe-license-1.txt or contact
 * Alias-i, Inc. at 181 North 11th Street, Suite 401, Brooklyn, NY 11211,
 * +1 (718) 290-9170.
 */
//package com.aliasi.util;
/**
 * A math utility class with static methods.
 *
 * @author  Bob Carpenter
 * @version 4.0.0
 * @since   LingPipe1.0
 */
public class Math {
    // forbid instances
    private Math() {
        /* no instances */
    }
    /**
     * The value of the golden ratio.  The golden ratio is defined to
     * be the value φ such that:
     *
     * 

     * φ = (φ + 1) / φ
     * 

     *
     * Note that this is a quadratic equation (multiply both sides by
     * φ) with the solution roughly 1.61803399.
     *
     * 

See the following for a fascinating tour of the properties
     * of the golden ratio:
     *
     * 


         * 
  •      *>Mathworld: Golden Ratio

  •      * 

     */
    public static final double GOLDEN_RATIO =  (1.0 + java.lang.Math.sqrt(5))/2.0;
    /**
     * The natural logarithm of 2.
     */
    public static final double LN_2 = java.lang.Math.log(2.0);
    static final double INV_LN_2 = 1.0/LN_2;
    /**
     * An array of the Fibonacci sequence up the maximum value
     * representable as a long integer.  The array is defined as
     * follows:
     *
     * 

     * FIBONACCI_SEQUENCE[0] = 1
     * FIBONACCI_SEQUENCE[1] = 2
     * FIBONACCI_SEQUENCE[n+2] = FIBONACCI_SEQUENCE[n+1] + FIBONACCI_SEQUENCE[n]
     * 

     *
     * So FIBONACCI_SEQUENCE[0] represents the second
     * Fibonacci number in the traditional numbering.  The inital entries
     * are:
     *
     * 

     * 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597,
     * 2584, ...
     * 

     *
     * The length of the array is 91, and the largest value is:
     *
     * 

     * FIBONACCI_SEQUENCE[90] = 7540113804746346429
     *
     * 

     *
     * 

See the following references for more information on
     * the fascinating properties of Fibonacci numbers:
     *
     * 


         * 
  •  Wikipedia: Fibonacci Number
         * 
  •  Mathworld: Fibonacci Number
         */
        public static final long[] FIBONACCI_SEQUENCE = new long[] {
        1l,
        2l,
        3l,
        5l,
        8l,
        13l,
        21l,
        34l,
        55l,
        89l,
        144l,
        233l,
        377l,
        610l,
        987l,
        1597l,
        2584l,
        4181l,
        6765l,
        10946l,
        17711l,
        28657l,
        46368l,
        75025l,
        121393l,
        196418l,
        317811l,
        514229l,
        832040l,
        1346269l,
        2178309l,
        3524578l,
        5702887l,
        9227465l,
        14930352l,
        24157817l,
        39088169l,
        63245986l,
        102334155l,
        165580141l,
        267914296l,
        433494437l,
        701408733l,
        1134903170l,
        1836311903l,
        2971215073l,
        4807526976l,
        7778742049l,
        12586269025l,
        20365011074l,
        32951280099l,
        53316291173l,
        86267571272l,
        139583862445l,
        225851433717l,
        365435296162l,
        591286729879l,
        956722026041l,
        1548008755920l,
        2504730781961l,
        4052739537881l,
        6557470319842l,
        10610209857723l,
        17167680177565l,
        27777890035288l,
        44945570212853l,
        72723460248141l,
        117669030460994l,
        190392490709135l,
        308061521170129l,
        498454011879264l,
        806515533049393l,
        1304969544928657l,
        2111485077978050l,
        3416454622906707l,
        5527939700884757l,
        8944394323791464l,
        14472334024676221l,
        23416728348467685l,
        37889062373143906l,
        61305790721611591l,
        99194853094755497l,
        160500643816367088l,
        259695496911122585l,
        420196140727489673l,
        679891637638612258l,
        1100087778366101931l,
        1779979416004714189l,
        2880067194370816120l,
        4660046610375530309l,
        7540113804746346429l
        };
        /**
         * Returns true if the specified number is prime.  A
         * prime is a positive number greater than 1 with no
         * divisors other than 1 and itself, thus
         * {2,3,5,7,11,13,...}.
         *
         * @param num Number to test for primality.
         * @return true if the specified number is prime.
         */
        public static boolean isPrime(int num) {
            if (num < 2) return false;
            for (int i = 2; i <= num/2; ++i)
                if (num % i == 0) return false;
            return true;
        }
        /**
         * Returns the smallest prime number that is strictly larger than
         * the specified integer.  See {@link #isPrime(int)} for the
         * definition of primality.
         *
         * @param num Base from which to look for the next prime.
         * @return Smallest prime number strictly larget than specified
         * number.
         */
        public static int nextPrime(int num) {
            if (num < 2) return 2;
            for (int i = num + 1; ; ++i)
                if (isPrime(i)) return i;
        }
        /**
         * Converts a natural logarithm to a base 2 logarithm.
         * This inverts the operation of {@link #logBase2ToNaturalLog(double)}.
         * 

    If the input is x = ln z, then
         * the return value is log2 z.
         * Recall that log2 z = ln z / ln 2.
         *
         * @param x Natural log of value.
         * @return Log base 2 of value.
         */
        public static double naturalLogToBase2Log(double x) {
            return x * INV_LN_2;
        }
        /**
         * Returns the log base 2 of the specivied value.
         *
         * @param x Value whose log is taken.
         * @return Log of specified value.
         */
        public static double log2(double x) {
            return naturalLogToBase2Log(java.lang.Math.log(x));
        }
        /**
         * Returns the integer value of reading the specified byte as an
         * unsigned value.  The computation is carried out by subtracting
         * the minimum value, as defined by the constant {@link
         * Byte#MIN_VALUE}.
         *
         * @param b Byte to convert.
         * @return Unsigned value of specified byte.
         */
        public static int byteAsUnsigned(byte b) {
            return (b >= 0) ? (int)b : (256+(int)b);
        }
        /**
         * Returns the log (base 2) of the factorial of the specified long
         * integer.  The factorial of n is defined for
         * n > 0 by:
         *
         * 


         *  n!
         *  = Πi < 0 <= n i
         * 

         *
         * Taking logs of both sides gives:
         *
         * 

         *  log2 n!
         *  = Σi < 0 <= n
         *    log2 i
         * 

         *
         * By convention, 0! is taken to be 1, and hence ln 0! = 0.
         *
         * @param n Specified long integer.
         * @return Log of factorial of specified integer.
         * @throws IllegalArgumentException If the argument is negative.
         */
        public static double log2Factorial(long n) {
            if (n < 0) {
                String msg = "Factorials only defined for non-negative arguments."
                    + " Found argument=" + n;
                throw new IllegalArgumentException(msg);
            }
            double sum = 0.0;
            for (long i = 1; i <= n; ++i)
                sum += log2(i);
            return sum;
        }
        /**
         * Returns the sum of the specified array of double values.
         *
         * @param xs Variable length list of values, or an array of values.
         * @return The sum of the values.
         */
        public static double sum(double... xs) {
            double sum = 0.0;
            for (int i = 0; i < xs.length; ++i)
                sum += xs[i];
            return sum;
        }
        /**
         * Returns the minimum of the specified array of double values.
         * If the length of the array is zero, the result is {@link
         * Double#NaN}.
         *
         * @param xs Variable length list of values, or an array.
         * @return Minimum value in array.
         */
        public static double minimum(double... xs) {
            if (xs.length == 0) return Double.NaN;
            double min = xs[0];
            for (int i = 1; i < xs.length; ++i)
                if (xs[i] < min) min = xs[i];
            return min;
        }
        /**
         * Returns the maximum of the specified array of double values.
         * If the length of the array is zero, the result is {@link
         * Double#NaN}.
         *
         * @param xs Variable length list of values, or an array.
         * @return Maximum value in array.
         */
        public static double maximum(double... xs) {
            if (xs.length == 0) return Double.NaN;
            double max = xs[0];
            for (int i = 1; i < xs.length; ++i)
                if (xs[i] > max) max = xs[i];
            return max;
        }
        /**
         * Returns the log (base 2) of the binomial coefficient of the
         * specified arguments.  The binomial coefficient is equal to the
         * number of ways to choose a subset of size m from a
         * set of n objects, which is pronounced "n choose
         * m", and is given by:
         *
         * 

         *   choose(n,m) = n! / ( m! * (n-m)!)
         *   

         *   log2 choose(n,m)
         *    = log2 n - log2 m
         *      - log2 (n-m)
         * 

         *
         * @return The log (base 2) of the binomial coefficient of the
         * specified arguments.
         */
        public static double log2BinomialCoefficient(long n, long m) {
            return log2(n) - log2(m) - log2(n-m);
        }
        static double[] LANCZOS_COEFFS = new double[] {
            0.99999999999980993,
            676.5203681218851,
            -1259.1392167224028,
            771.32342877765313,
            -176.61502916214059,
            12.507343278686905,
            -0.13857109526572012,
            9.9843695780195716e-6,
            1.5056327351493116e-7
        };
        static double SQRT_2_PI = java.lang.Math.sqrt(2.0 * java.lang.Math.PI);
        // assumes input in [0.5,1.5] inclusive
        static double lanczosGamma(double z) {
            double zMinus1 = z - 1;
            double x = LANCZOS_COEFFS[0];
            for (int i = 1; i < LANCZOS_COEFFS.length - 2; ++i)
                x += LANCZOS_COEFFS[i] / (zMinus1 + i);
            double t = zMinus1 + (LANCZOS_COEFFS.length - 2) + 0.5;
            return SQRT_2_PI
                * java.lang.Math.pow(t, zMinus1 + 0.5)
                * java.lang.Math.exp(-t) * x;
        }
        /**
         * Returns the value of the digamma function for the specified
         * value.  The returned values are accurate to at least 13
         * decimal places.
         *
         * 

    The digamma function is the derivative of the log of the
         * gamma function; see the method documentation for {@link
         * #log2Gamma(double)} for more information on the gamma function
         * itself.
         *
         * 


         * Ψ(z)
         * = d log Γ(z) / dz
         * = Γ'(z) / Γ(z)
         * 

         *
         * 

    The numerical approximation is derived from:
         *
         * 


           * 
    • Richard J. Mathar. 2005.
           * Chebyshev Series Expansion of Inverse Polynomials.
           * 

    •      * 
    • Richard J. Mathar. 2005.
           * digamma.c.
           * (C Program implementing algorithm.)
           * 

    •      * 

         *
         * Implementation Note: The recursive calls in the C
         * implementation have been transformed into loops and
         * accumulators, and the recursion for values greater than three
         * replaced with a simpler reduction.  The number of loops
         * required before the fixed length expansion is approximately
         * integer value of the absolute value of the input.  Each loop
         * requires a floating point division, two additions and a local
         * variable assignment.  The fixed portion of the algorithm is
         * roughly 30 steps requiring four multiplications, three
         * additions, one static final array lookup, and four assignments per
         * loop iteration.
         *
         * @param x Value at which to evaluate the digamma function.
         * @return The value of the digamma function at the specified
         * value.
         */
        public static double digamma(double x)
        {
            if (x <= 0.0 && (x == (double)((long) x)))
                return Double.NaN;
            double accum = 0.0;
            if (x < 0.0) {
                accum += java.lang.Math.PI
                    / java.lang.Math.tan(java.lang.Math.PI * (1.0 - x));
                x = 1.0 - x;
            }
            if (x < 1.0 ) {
                while (x < 1.0)
                    accum -= 1.0 / x++;
            }
            if (x == 1.0)
                return accum - NEGATIVE_DIGAMMA_1;
            if (x == 2.0)
                return accum + 1.0 - NEGATIVE_DIGAMMA_1;
            if (x == 3.0)
                return accum + 1.5 - NEGATIVE_DIGAMMA_1;
            // simpler recursion than Mahar to reduce recursion
            if (x > 3.0) {
                while (x > 3.0)
                    accum += 1.0 / --x;
                return accum + digamma(x);
            }
            x -= 2.0;
            double tNMinus1 = 1.0;
            double tN = x;
            double digamma = DIGAMMA_COEFFS[0] + DIGAMMA_COEFFS[1] * tN;
            for (int n = 2; n < DIGAMMA_COEFFS.length; n++) {
                double tN1 = 2.0 * x * tN - tNMinus1;
                digamma += DIGAMMA_COEFFS[n] * tN1;
                tNMinus1 = tN;
                tN = tN1;
            }
            return accum + digamma;
        }
        /**
         * The γ constant for computing the digamma function.
         *
         * 

    The value is defined as the negative of the digamma funtion
         * evaluated at 1:
         *
         * 


         * γ = - Ψ(1)
         *
         */
        static double NEGATIVE_DIGAMMA_1 = 0.5772156649015328606065120900824024;
        private static final double DIGAMMA_COEFFS[]
            = {
            .30459198558715155634315638246624251,
            .72037977439182833573548891941219706,
            -.12454959243861367729528855995001087,
            .27769457331927827002810119567456810e-1,
            -.67762371439822456447373550186163070e-2,
            .17238755142247705209823876688592170e-2,
            -.44817699064252933515310345718960928e-3,
            .11793660000155572716272710617753373e-3,
            -.31253894280980134452125172274246963e-4,
            .83173997012173283398932708991137488e-5,
            -.22191427643780045431149221890172210e-5,
            .59302266729329346291029599913617915e-6,
            -.15863051191470655433559920279603632e-6,
            .42459203983193603241777510648681429e-7,
            -.11369129616951114238848106591780146e-7,
            .304502217295931698401459168423403510e-8,
            -.81568455080753152802915013641723686e-9,
            .21852324749975455125936715817306383e-9,
            -.58546491441689515680751900276454407e-10,
            .15686348450871204869813586459513648e-10,
            -.42029496273143231373796179302482033e-11,
            .11261435719264907097227520956710754e-11,
            -.30174353636860279765375177200637590e-12,
            .80850955256389526647406571868193768e-13,
            -.21663779809421233144009565199997351e-13,
            .58047634271339391495076374966835526e-14,
            -.15553767189204733561108869588173845e-14,
            .41676108598040807753707828039353330e-15,
            -.11167065064221317094734023242188463e-15 };
        /**
         * Returns the relative absolute difference between the specified
         * values, defined to be:
         *
         * 

         * relAbsDiff(x,y) = abs(x-y) / (abs(x) + abs(y))

         *
         * @param x First value.
         * @param y Second value.
         * @return The absolute relative difference between the values.
         */
        public static double relativeAbsoluteDifference(double x, double y) {
            return (Double.isInfinite(x) || Double.isInfinite(y))
                ? Double.POSITIVE_INFINITY
                : (java.lang.Math.abs(x - y)
                   / (java.lang.Math.abs(x) + java.lang.Math.abs(y)));
        }
        /**
         * This method returns the log of the sum of the natural
         * exponentiated values in the specified array.  Mathematically,
         * the result is
         *
         * 

         * logSumOfExponentials(xs) = log ( Σi exp(xs[i]) )

         *
         * But the result is not calculated directly.  Instead, the
         * calculation performed is:
         *
         * 

         * logSumOfExponentials(xs) = max(xs) + log ( Σi exp(xs[i] - max(xs)) )

         *
         * which produces the same result, but is much more arithmetically
         * stable, because the largest value for which exp()
         * is calculated is 0.0.
         *
         * 

    Values of {@code Double.NEGATIVE_INFINITY} are treated as
         * having exponentials of 0 and logs of negative infinity.
         * That is, they are ignored for the purposes of this computation.
         *
         * @param xs Array of values.
         * @return The log of the sum of the exponentiated values in the
         * array.
         */
        public static double logSumOfExponentials(double[] xs) {
            if (xs.length == 1) return xs[0];
            double max = maximum(xs);
            double sum = 0.0;
            for (int i = 0; i < xs.length; ++i)
                if (xs[i] != Double.NEGATIVE_INFINITY)
                    sum += java.lang.Math.exp(xs[i] - max);
            return max + java.lang.Math.log(sum);
        }
        /**
         * Returns the maximum value of an element in xs.  If any of the
         * values are {@code Double.NaN}, or if the input array is empty,
         * the result is {@code Double.NaN}.
         *
         * @param xs Array in which to find maximum.
         * @return Maximum value in array.
         */
        public static double max(double... xs) {
            if (xs.length == 0)
                return Double.NaN;
            double max = xs[0];
            for (int i = 1; i < xs.length; ++i)
                max = java.lang.Math.max(max,xs[i]);
            return max;
        }
        /**
         * Returns the maximum value of an element in the specified array.
         *
         * @param xs Array in which to find maximum.
         * @return Maximum value in the array.
         * @throws ArrayIndexOutOfBoundsException If the specified array does
         * not contai at least one element.
         */
        public static int max(int... xs) {
            int max = xs[0];
            for (int i = 1; i < xs.length; ++i)
                if (xs[i] > max)
                    max = xs[i];
            return max;
        }
        /**
         * Returns the sum of the specified integer array.  Note that
         * there is no check for overflow.  If the array is of length 0,
         * the sum is defined to be 0.
         *
         * @param xs Array of integers to sum.
         * @return Sum of the array.
         */
        public static int sum(int... xs) {
            int sum = 0;
            for (int i = 0; i < xs.length; ++i)
                sum += xs[i];
            return sum;
        }
    }