diff options
author | Karl Shaffer <karlshaffer@google.com> | 2023-08-10 21:04:00 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2023-08-10 21:04:00 +0000 |
commit | b3715644fba79ef08acd9a2e157d078865281767 (patch) | |
tree | ace24ba4307d4978ee3134f7da671a77ad172da0 /src/main/java/org/apache/commons/math3/util | |
parent | c6daa20e87158ebdc049f6c921257ddbf1af6b0d (diff) | |
parent | 0018f64b87f6b2df2a4c866aa3eb8ab2e45efbea (diff) | |
download | apache-commons-math-b3715644fba79ef08acd9a2e157d078865281767.tar.gz |
Check-in commons-math 3.6.1 am: 1354beaf45 am: 0018f64b87
Original change: https://android-review.googlesource.com/c/platform/external/apache-commons-math/+/2702413
Change-Id: Ic2a78fec4bb3bb3448de42350306644ba2bd021d
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
Diffstat (limited to 'src/main/java/org/apache/commons/math3/util')
35 files changed, 24041 insertions, 0 deletions
diff --git a/src/main/java/org/apache/commons/math3/util/ArithmeticUtils.java b/src/main/java/org/apache/commons/math3/util/ArithmeticUtils.java new file mode 100644 index 0000000..8f07818 --- /dev/null +++ b/src/main/java/org/apache/commons/math3/util/ArithmeticUtils.java @@ -0,0 +1,845 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math3.util; + +import org.apache.commons.math3.exception.MathArithmeticException; +import org.apache.commons.math3.exception.NotPositiveException; +import org.apache.commons.math3.exception.NumberIsTooLargeException; +import org.apache.commons.math3.exception.util.Localizable; +import org.apache.commons.math3.exception.util.LocalizedFormats; + +import java.math.BigInteger; + +/** Some useful, arithmetics related, additions to the built-in functions in {@link Math}. */ +public final class ArithmeticUtils { + + /** Private constructor. */ + private ArithmeticUtils() { + super(); + } + + /** + * Add two integers, checking for overflow. + * + * @param x an addend + * @param y an addend + * @return the sum {@code x+y} + * @throws MathArithmeticException if the result can not be represented as an {@code int}. + * @since 1.1 + */ + public static int addAndCheck(int x, int y) throws MathArithmeticException { + long s = (long) x + (long) y; + if (s < Integer.MIN_VALUE || s > Integer.MAX_VALUE) { + throw new MathArithmeticException(LocalizedFormats.OVERFLOW_IN_ADDITION, x, y); + } + return (int) s; + } + + /** + * Add two long integers, checking for overflow. + * + * @param a an addend + * @param b an addend + * @return the sum {@code a+b} + * @throws MathArithmeticException if the result can not be represented as an long + * @since 1.2 + */ + public static long addAndCheck(long a, long b) throws MathArithmeticException { + return addAndCheck(a, b, LocalizedFormats.OVERFLOW_IN_ADDITION); + } + + /** + * Returns an exact representation of the <a + * href="http://mathworld.wolfram.com/BinomialCoefficient.html">Binomial Coefficient</a>, + * "{@code n choose k}", the number of {@code k}-element subsets that can be selected from an + * {@code n}-element set. + * + * <p><Strong>Preconditions</strong>: + * + * <ul> + * <li>{@code 0 <= k <= n } (otherwise {@code IllegalArgumentException} is thrown) + * <li>The result is small enough to fit into a {@code long}. The largest value of {@code n} + * for which all coefficients are {@code < Long.MAX_VALUE} is 66. If the computed value + * exceeds {@code Long.MAX_VALUE} an {@code ArithMeticException} is thrown. + * </ul> + * + * @param n the size of the set + * @param k the size of the subsets to be counted + * @return {@code n choose k} + * @throws NotPositiveException if {@code n < 0}. + * @throws NumberIsTooLargeException if {@code k > n}. + * @throws MathArithmeticException if the result is too large to be represented by a long + * integer. + * @deprecated use {@link CombinatoricsUtils#binomialCoefficient(int, int)} + */ + @Deprecated + public static long binomialCoefficient(final int n, final int k) + throws NotPositiveException, NumberIsTooLargeException, MathArithmeticException { + return CombinatoricsUtils.binomialCoefficient(n, k); + } + + /** + * Returns a {@code double} representation of the <a + * href="http://mathworld.wolfram.com/BinomialCoefficient.html">Binomial Coefficient</a>, + * "{@code n choose k}", the number of {@code k}-element subsets that can be selected from an + * {@code n}-element set. + * + * <p><Strong>Preconditions</strong>: + * + * <ul> + * <li>{@code 0 <= k <= n } (otherwise {@code IllegalArgumentException} is thrown) + * <li>The result is small enough to fit into a {@code double}. The largest value of {@code n} + * for which all coefficients are < Double.MAX_VALUE is 1029. If the computed value + * exceeds Double.MAX_VALUE, Double.POSITIVE_INFINITY is returned + * </ul> + * + * @param n the size of the set + * @param k the size of the subsets to be counted + * @return {@code n choose k} + * @throws NotPositiveException if {@code n < 0}. + * @throws NumberIsTooLargeException if {@code k > n}. + * @throws MathArithmeticException if the result is too large to be represented by a long + * integer. + * @deprecated use {@link CombinatoricsUtils#binomialCoefficientDouble(int, int)} + */ + @Deprecated + public static double binomialCoefficientDouble(final int n, final int k) + throws NotPositiveException, NumberIsTooLargeException, MathArithmeticException { + return CombinatoricsUtils.binomialCoefficientDouble(n, k); + } + + /** + * Returns the natural {@code log} of the <a + * href="http://mathworld.wolfram.com/BinomialCoefficient.html">Binomial Coefficient</a>, + * "{@code n choose k}", the number of {@code k}-element subsets that can be selected from an + * {@code n}-element set. + * + * <p><Strong>Preconditions</strong>: + * + * <ul> + * <li>{@code 0 <= k <= n } (otherwise {@code IllegalArgumentException} is thrown) + * </ul> + * + * @param n the size of the set + * @param k the size of the subsets to be counted + * @return {@code n choose k} + * @throws NotPositiveException if {@code n < 0}. + * @throws NumberIsTooLargeException if {@code k > n}. + * @throws MathArithmeticException if the result is too large to be represented by a long + * integer. + * @deprecated use {@link CombinatoricsUtils#binomialCoefficientLog(int, int)} + */ + @Deprecated + public static double binomialCoefficientLog(final int n, final int k) + throws NotPositiveException, NumberIsTooLargeException, MathArithmeticException { + return CombinatoricsUtils.binomialCoefficientLog(n, k); + } + + /** + * Returns n!. Shorthand for {@code n} <a href="http://mathworld.wolfram.com/Factorial.html"> + * Factorial</a>, the product of the numbers {@code 1,...,n}. + * + * <p><Strong>Preconditions</strong>: + * + * <ul> + * <li>{@code n >= 0} (otherwise {@code IllegalArgumentException} is thrown) + * <li>The result is small enough to fit into a {@code long}. The largest value of {@code n} + * for which {@code n!} < Long.MAX_VALUE} is 20. If the computed value exceeds {@code + * Long.MAX_VALUE} an {@code ArithMeticException } is thrown. + * </ul> + * + * @param n argument + * @return {@code n!} + * @throws MathArithmeticException if the result is too large to be represented by a {@code + * long}. + * @throws NotPositiveException if {@code n < 0}. + * @throws MathArithmeticException if {@code n > 20}: The factorial value is too large to fit in + * a {@code long}. + * @deprecated use {@link CombinatoricsUtils#factorial(int)} + */ + @Deprecated + public static long factorial(final int n) throws NotPositiveException, MathArithmeticException { + return CombinatoricsUtils.factorial(n); + } + + /** + * Compute n!, the<a href="http://mathworld.wolfram.com/Factorial.html">factorial</a> of {@code + * n} (the product of the numbers 1 to n), as a {@code double}. The result should be small + * enough to fit into a {@code double}: The largest {@code n} for which {@code n! < + * Double.MAX_VALUE} is 170. If the computed value exceeds {@code Double.MAX_VALUE}, {@code + * Double.POSITIVE_INFINITY} is returned. + * + * @param n Argument. + * @return {@code n!} + * @throws NotPositiveException if {@code n < 0}. + * @deprecated use {@link CombinatoricsUtils#factorialDouble(int)} + */ + @Deprecated + public static double factorialDouble(final int n) throws NotPositiveException { + return CombinatoricsUtils.factorialDouble(n); + } + + /** + * Compute the natural logarithm of the factorial of {@code n}. + * + * @param n Argument. + * @return {@code n!} + * @throws NotPositiveException if {@code n < 0}. + * @deprecated use {@link CombinatoricsUtils#factorialLog(int)} + */ + @Deprecated + public static double factorialLog(final int n) throws NotPositiveException { + return CombinatoricsUtils.factorialLog(n); + } + + /** + * Computes the greatest common divisor of the absolute value of two numbers, using a modified + * version of the "binary gcd" method. See Knuth 4.5.2 algorithm B. The algorithm is due to + * Josef Stein (1961). <br> + * Special cases: + * + * <ul> + * <li>The invocations {@code gcd(Integer.MIN_VALUE, Integer.MIN_VALUE)}, {@code + * gcd(Integer.MIN_VALUE, 0)} and {@code gcd(0, Integer.MIN_VALUE)} throw an {@code + * ArithmeticException}, because the result would be 2^31, which is too large for an int + * value. + * <li>The result of {@code gcd(x, x)}, {@code gcd(0, x)} and {@code gcd(x, 0)} is the + * absolute value of {@code x}, except for the special cases above. + * <li>The invocation {@code gcd(0, 0)} is the only one which returns {@code 0}. + * </ul> + * + * @param p Number. + * @param q Number. + * @return the greatest common divisor (never negative). + * @throws MathArithmeticException if the result cannot be represented as a non-negative {@code + * int} value. + * @since 1.1 + */ + public static int gcd(int p, int q) throws MathArithmeticException { + int a = p; + int b = q; + if (a == 0 || b == 0) { + if (a == Integer.MIN_VALUE || b == Integer.MIN_VALUE) { + throw new MathArithmeticException(LocalizedFormats.GCD_OVERFLOW_32_BITS, p, q); + } + return FastMath.abs(a + b); + } + + long al = a; + long bl = b; + boolean useLong = false; + if (a < 0) { + if (Integer.MIN_VALUE == a) { + useLong = true; + } else { + a = -a; + } + al = -al; + } + if (b < 0) { + if (Integer.MIN_VALUE == b) { + useLong = true; + } else { + b = -b; + } + bl = -bl; + } + if (useLong) { + if (al == bl) { + throw new MathArithmeticException(LocalizedFormats.GCD_OVERFLOW_32_BITS, p, q); + } + long blbu = bl; + bl = al; + al = blbu % al; + if (al == 0) { + if (bl > Integer.MAX_VALUE) { + throw new MathArithmeticException(LocalizedFormats.GCD_OVERFLOW_32_BITS, p, q); + } + return (int) bl; + } + blbu = bl; + + // Now "al" and "bl" fit in an "int". + b = (int) al; + a = (int) (blbu % al); + } + + return gcdPositive(a, b); + } + + /** + * Computes the greatest common divisor of two <em>positive</em> numbers (this precondition is + * <em>not</em> checked and the result is undefined if not fulfilled) using the "binary gcd" + * method which avoids division and modulo operations. See Knuth 4.5.2 algorithm B. The + * algorithm is due to Josef Stein (1961). <br> + * Special cases: + * + * <ul> + * <li>The result of {@code gcd(x, x)}, {@code gcd(0, x)} and {@code gcd(x, 0)} is the value + * of {@code x}. + * <li>The invocation {@code gcd(0, 0)} is the only one which returns {@code 0}. + * </ul> + * + * @param a Positive number. + * @param b Positive number. + * @return the greatest common divisor. + */ + private static int gcdPositive(int a, int b) { + if (a == 0) { + return b; + } else if (b == 0) { + return a; + } + + // Make "a" and "b" odd, keeping track of common power of 2. + final int aTwos = Integer.numberOfTrailingZeros(a); + a >>= aTwos; + final int bTwos = Integer.numberOfTrailingZeros(b); + b >>= bTwos; + final int shift = FastMath.min(aTwos, bTwos); + + // "a" and "b" are positive. + // If a > b then "gdc(a, b)" is equal to "gcd(a - b, b)". + // If a < b then "gcd(a, b)" is equal to "gcd(b - a, a)". + // Hence, in the successive iterations: + // "a" becomes the absolute difference of the current values, + // "b" becomes the minimum of the current values. + while (a != b) { + final int delta = a - b; + b = Math.min(a, b); + a = Math.abs(delta); + + // Remove any power of 2 in "a" ("b" is guaranteed to be odd). + a >>= Integer.numberOfTrailingZeros(a); + } + + // Recover the common power of 2. + return a << shift; + } + + /** + * Gets the greatest common divisor of the absolute value of two numbers, using the "binary gcd" + * method which avoids division and modulo operations. See Knuth 4.5.2 algorithm B. This + * algorithm is due to Josef Stein (1961). Special cases: + * + * <ul> + * <li>The invocations {@code gcd(Long.MIN_VALUE, Long.MIN_VALUE)}, {@code gcd(Long.MIN_VALUE, + * 0L)} and {@code gcd(0L, Long.MIN_VALUE)} throw an {@code ArithmeticException}, because + * the result would be 2^63, which is too large for a long value. + * <li>The result of {@code gcd(x, x)}, {@code gcd(0L, x)} and {@code gcd(x, 0L)} is the + * absolute value of {@code x}, except for the special cases above. + * <li>The invocation {@code gcd(0L, 0L)} is the only one which returns {@code 0L}. + * </ul> + * + * @param p Number. + * @param q Number. + * @return the greatest common divisor, never negative. + * @throws MathArithmeticException if the result cannot be represented as a non-negative {@code + * long} value. + * @since 2.1 + */ + public static long gcd(final long p, final long q) throws MathArithmeticException { + long u = p; + long v = q; + if ((u == 0) || (v == 0)) { + if ((u == Long.MIN_VALUE) || (v == Long.MIN_VALUE)) { + throw new MathArithmeticException(LocalizedFormats.GCD_OVERFLOW_64_BITS, p, q); + } + return FastMath.abs(u) + FastMath.abs(v); + } + // keep u and v negative, as negative integers range down to + // -2^63, while positive numbers can only be as large as 2^63-1 + // (i.e. we can't necessarily negate a negative number without + // overflow) + /* assert u!=0 && v!=0; */ + if (u > 0) { + u = -u; + } // make u negative + if (v > 0) { + v = -v; + } // make v negative + // B1. [Find power of 2] + int k = 0; + while ((u & 1) == 0 && (v & 1) == 0 && k < 63) { // while u and v are + // both even... + u /= 2; + v /= 2; + k++; // cast out twos. + } + if (k == 63) { + throw new MathArithmeticException(LocalizedFormats.GCD_OVERFLOW_64_BITS, p, q); + } + // B2. Initialize: u and v have been divided by 2^k and at least + // one is odd. + long t = ((u & 1) == 1) ? v : -(u / 2) /* B3 */; + // t negative: u was odd, v may be even (t replaces v) + // t positive: u was even, v is odd (t replaces u) + do { + /* assert u<0 && v<0; */ + // B4/B3: cast out twos from t. + while ((t & 1) == 0) { // while t is even.. + t /= 2; // cast out twos + } + // B5 [reset max(u,v)] + if (t > 0) { + u = -t; + } else { + v = t; + } + // B6/B3. at this point both u and v should be odd. + t = (v - u) / 2; + // |u| larger: t positive (replace u) + // |v| larger: t negative (replace v) + } while (t != 0); + return -u * (1L << k); // gcd is u*2^k + } + + /** + * Returns the least common multiple of the absolute value of two numbers, using the formula + * {@code lcm(a,b) = (a / gcd(a,b)) * b}. Special cases: + * + * <ul> + * <li>The invocations {@code lcm(Integer.MIN_VALUE, n)} and {@code lcm(n, + * Integer.MIN_VALUE)}, where {@code abs(n)} is a power of 2, throw an {@code + * ArithmeticException}, because the result would be 2^31, which is too large for an int + * value. + * <li>The result of {@code lcm(0, x)} and {@code lcm(x, 0)} is {@code 0} for any {@code x}. + * </ul> + * + * @param a Number. + * @param b Number. + * @return the least common multiple, never negative. + * @throws MathArithmeticException if the result cannot be represented as a non-negative {@code + * int} value. + * @since 1.1 + */ + public static int lcm(int a, int b) throws MathArithmeticException { + if (a == 0 || b == 0) { + return 0; + } + int lcm = FastMath.abs(ArithmeticUtils.mulAndCheck(a / gcd(a, b), b)); + if (lcm == Integer.MIN_VALUE) { + throw new MathArithmeticException(LocalizedFormats.LCM_OVERFLOW_32_BITS, a, b); + } + return lcm; + } + + /** + * Returns the least common multiple of the absolute value of two numbers, using the formula + * {@code lcm(a,b) = (a / gcd(a,b)) * b}. Special cases: + * + * <ul> + * <li>The invocations {@code lcm(Long.MIN_VALUE, n)} and {@code lcm(n, Long.MIN_VALUE)}, + * where {@code abs(n)} is a power of 2, throw an {@code ArithmeticException}, because the + * result would be 2^63, which is too large for an int value. + * <li>The result of {@code lcm(0L, x)} and {@code lcm(x, 0L)} is {@code 0L} for any {@code + * x}. + * </ul> + * + * @param a Number. + * @param b Number. + * @return the least common multiple, never negative. + * @throws MathArithmeticException if the result cannot be represented as a non-negative {@code + * long} value. + * @since 2.1 + */ + public static long lcm(long a, long b) throws MathArithmeticException { + if (a == 0 || b == 0) { + return 0; + } + long lcm = FastMath.abs(ArithmeticUtils.mulAndCheck(a / gcd(a, b), b)); + if (lcm == Long.MIN_VALUE) { + throw new MathArithmeticException(LocalizedFormats.LCM_OVERFLOW_64_BITS, a, b); + } + return lcm; + } + + /** + * Multiply two integers, checking for overflow. + * + * @param x Factor. + * @param y Factor. + * @return the product {@code x * y}. + * @throws MathArithmeticException if the result can not be represented as an {@code int}. + * @since 1.1 + */ + public static int mulAndCheck(int x, int y) throws MathArithmeticException { + long m = ((long) x) * ((long) y); + if (m < Integer.MIN_VALUE || m > Integer.MAX_VALUE) { + throw new MathArithmeticException(); + } + return (int) m; + } + + /** + * Multiply two long integers, checking for overflow. + * + * @param a Factor. + * @param b Factor. + * @return the product {@code a * b}. + * @throws MathArithmeticException if the result can not be represented as a {@code long}. + * @since 1.2 + */ + public static long mulAndCheck(long a, long b) throws MathArithmeticException { + long ret; + if (a > b) { + // use symmetry to reduce boundary cases + ret = mulAndCheck(b, a); + } else { + if (a < 0) { + if (b < 0) { + // check for positive overflow with negative a, negative b + if (a >= Long.MAX_VALUE / b) { + ret = a * b; + } else { + throw new MathArithmeticException(); + } + } else if (b > 0) { + // check for negative overflow with negative a, positive b + if (Long.MIN_VALUE / b <= a) { + ret = a * b; + } else { + throw new MathArithmeticException(); + } + } else { + // assert b == 0 + ret = 0; + } + } else if (a > 0) { + // assert a > 0 + // assert b > 0 + + // check for positive overflow with positive a, positive b + if (a <= Long.MAX_VALUE / b) { + ret = a * b; + } else { + throw new MathArithmeticException(); + } + } else { + // assert a == 0 + ret = 0; + } + } + return ret; + } + + /** + * Subtract two integers, checking for overflow. + * + * @param x Minuend. + * @param y Subtrahend. + * @return the difference {@code x - y}. + * @throws MathArithmeticException if the result can not be represented as an {@code int}. + * @since 1.1 + */ + public static int subAndCheck(int x, int y) throws MathArithmeticException { + long s = (long) x - (long) y; + if (s < Integer.MIN_VALUE || s > Integer.MAX_VALUE) { + throw new MathArithmeticException(LocalizedFormats.OVERFLOW_IN_SUBTRACTION, x, y); + } + return (int) s; + } + + /** + * Subtract two long integers, checking for overflow. + * + * @param a Value. + * @param b Value. + * @return the difference {@code a - b}. + * @throws MathArithmeticException if the result can not be represented as a {@code long}. + * @since 1.2 + */ + public static long subAndCheck(long a, long b) throws MathArithmeticException { + long ret; + if (b == Long.MIN_VALUE) { + if (a < 0) { + ret = a - b; + } else { + throw new MathArithmeticException(LocalizedFormats.OVERFLOW_IN_ADDITION, a, -b); + } + } else { + // use additive inverse + ret = addAndCheck(a, -b, LocalizedFormats.OVERFLOW_IN_ADDITION); + } + return ret; + } + + /** + * Raise an int to an int power. + * + * @param k Number to raise. + * @param e Exponent (must be positive or zero). + * @return \( k^e \) + * @throws NotPositiveException if {@code e < 0}. + * @throws MathArithmeticException if the result would overflow. + */ + public static int pow(final int k, final int e) + throws NotPositiveException, MathArithmeticException { + if (e < 0) { + throw new NotPositiveException(LocalizedFormats.EXPONENT, e); + } + + try { + int exp = e; + int result = 1; + int k2p = k; + while (true) { + if ((exp & 0x1) != 0) { + result = mulAndCheck(result, k2p); + } + + exp >>= 1; + if (exp == 0) { + break; + } + + k2p = mulAndCheck(k2p, k2p); + } + + return result; + } catch (MathArithmeticException mae) { + // Add context information. + mae.getContext().addMessage(LocalizedFormats.OVERFLOW); + mae.getContext().addMessage(LocalizedFormats.BASE, k); + mae.getContext().addMessage(LocalizedFormats.EXPONENT, e); + + // Rethrow. + throw mae; + } + } + + /** + * Raise an int to a long power. + * + * @param k Number to raise. + * @param e Exponent (must be positive or zero). + * @return k<sup>e</sup> + * @throws NotPositiveException if {@code e < 0}. + * @deprecated As of 3.3. Please use {@link #pow(int,int)} instead. + */ + @Deprecated + public static int pow(final int k, long e) throws NotPositiveException { + if (e < 0) { + throw new NotPositiveException(LocalizedFormats.EXPONENT, e); + } + + int result = 1; + int k2p = k; + while (e != 0) { + if ((e & 0x1) != 0) { + result *= k2p; + } + k2p *= k2p; + e >>= 1; + } + + return result; + } + + /** + * Raise a long to an int power. + * + * @param k Number to raise. + * @param e Exponent (must be positive or zero). + * @return \( k^e \) + * @throws NotPositiveException if {@code e < 0}. + * @throws MathArithmeticException if the result would overflow. + */ + public static long pow(final long k, final int e) + throws NotPositiveException, MathArithmeticException { + if (e < 0) { + throw new NotPositiveException(LocalizedFormats.EXPONENT, e); + } + + try { + int exp = e; + long result = 1; + long k2p = k; + while (true) { + if ((exp & 0x1) != 0) { + result = mulAndCheck(result, k2p); + } + + exp >>= 1; + if (exp == 0) { + break; + } + + k2p = mulAndCheck(k2p, k2p); + } + + return result; + } catch (MathArithmeticException mae) { + // Add context information. + mae.getContext().addMessage(LocalizedFormats.OVERFLOW); + mae.getContext().addMessage(LocalizedFormats.BASE, k); + mae.getContext().addMessage(LocalizedFormats.EXPONENT, e); + + // Rethrow. + throw mae; + } + } + + /** + * Raise a long to a long power. + * + * @param k Number to raise. + * @param e Exponent (must be positive or zero). + * @return k<sup>e</sup> + * @throws NotPositiveException if {@code e < 0}. + * @deprecated As of 3.3. Please use {@link #pow(long,int)} instead. + */ + @Deprecated + public static long pow(final long k, long e) throws NotPositiveException { + if (e < 0) { + throw new NotPositiveException(LocalizedFormats.EXPONENT, e); + } + + long result = 1l; + long k2p = k; + while (e != 0) { + if ((e & 0x1) != 0) { + result *= k2p; + } + k2p *= k2p; + e >>= 1; + } + + return result; + } + + /** + * Raise a BigInteger to an int power. + * + * @param k Number to raise. + * @param e Exponent (must be positive or zero). + * @return k<sup>e</sup> + * @throws NotPositiveException if {@code e < 0}. + */ + public static BigInteger pow(final BigInteger k, int e) throws NotPositiveException { + if (e < 0) { + throw new NotPositiveException(LocalizedFormats.EXPONENT, e); + } + + return k.pow(e); + } + + /** + * Raise a BigInteger to a long power. + * + * @param k Number to raise. + * @param e Exponent (must be positive or zero). + * @return k<sup>e</sup> + * @throws NotPositiveException if {@code e < 0}. + */ + public static BigInteger pow(final BigInteger k, long e) throws NotPositiveException { + if (e < 0) { + throw new NotPositiveException(LocalizedFormats.EXPONENT, e); + } + + BigInteger result = BigInteger.ONE; + BigInteger k2p = k; + while (e != 0) { + if ((e & 0x1) != 0) { + result = result.multiply(k2p); + } + k2p = k2p.multiply(k2p); + e >>= 1; + } + + return result; + } + + /** + * Raise a BigInteger to a BigInteger power. + * + * @param k Number to raise. + * @param e Exponent (must be positive or zero). + * @return k<sup>e</sup> + * @throws NotPositiveException if {@code e < 0}. + */ + public static BigInteger pow(final BigInteger k, BigInteger e) throws NotPositiveException { + if (e.compareTo(BigInteger.ZERO) < 0) { + throw new NotPositiveException(LocalizedFormats.EXPONENT, e); + } + + BigInteger result = BigInteger.ONE; + BigInteger k2p = k; + while (!BigInteger.ZERO.equals(e)) { + if (e.testBit(0)) { + result = result.multiply(k2p); + } + k2p = k2p.multiply(k2p); + e = e.shiftRight(1); + } + + return result; + } + + /** + * Returns the <a href="http://mathworld.wolfram.com/StirlingNumberoftheSecondKind.html"> + * Stirling number of the second kind</a>, "{@code S(n,k)}", the number of ways of partitioning + * an {@code n}-element set into {@code k} non-empty subsets. + * + * <p>The preconditions are {@code 0 <= k <= n } (otherwise {@code NotPositiveException} is + * thrown) + * + * @param n the size of the set + * @param k the number of non-empty subsets + * @return {@code S(n,k)} + * @throws NotPositiveException if {@code k < 0}. + * @throws NumberIsTooLargeException if {@code k > n}. + * @throws MathArithmeticException if some overflow happens, typically for n exceeding 25 and k + * between 20 and n-2 (S(n,n-1) is handled specifically and does not overflow) + * @since 3.1 + * @deprecated use {@link CombinatoricsUtils#stirlingS2(int, int)} + */ + @Deprecated + public static long stirlingS2(final int n, final int k) + throws NotPositiveException, NumberIsTooLargeException, MathArithmeticException { + return CombinatoricsUtils.stirlingS2(n, k); + } + + /** + * Add two long integers, checking for overflow. + * + * @param a Addend. + * @param b Addend. + * @param pattern Pattern to use for any thrown exception. + * @return the sum {@code a + b}. + * @throws MathArithmeticException if the result cannot be represented as a {@code long}. + * @since 1.2 + */ + private static long addAndCheck(long a, long b, Localizable pattern) + throws MathArithmeticException { + final long result = a + b; + if (!((a ^ b) < 0 | (a ^ result) >= 0)) { + throw new MathArithmeticException(pattern, a, b); + } + return result; + } + + /** + * Returns true if the argument is a power of two. + * + * @param n the number to test + * @return true if the argument is a power of two + */ + public static boolean isPowerOfTwo(long n) { + return (n > 0) && ((n & (n - 1)) == 0); + } +} diff --git a/src/main/java/org/apache/commons/math3/util/BigReal.java b/src/main/java/org/apache/commons/math3/util/BigReal.java new file mode 100644 index 0000000..54c59e8 --- /dev/null +++ b/src/main/java/org/apache/commons/math3/util/BigReal.java @@ -0,0 +1,362 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math3.util; + +import org.apache.commons.math3.Field; +import org.apache.commons.math3.FieldElement; +import org.apache.commons.math3.exception.MathArithmeticException; +import org.apache.commons.math3.exception.util.LocalizedFormats; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.math.MathContext; +import java.math.RoundingMode; + +/** + * Arbitrary precision decimal number. + * + * <p>This class is a simple wrapper around the standard <code>BigDecimal</code> in order to + * implement the {@link FieldElement} interface. + * + * @since 2.0 + */ +public class BigReal implements FieldElement<BigReal>, Comparable<BigReal>, Serializable { + + /** A big real representing 0. */ + public static final BigReal ZERO = new BigReal(BigDecimal.ZERO); + + /** A big real representing 1. */ + public static final BigReal ONE = new BigReal(BigDecimal.ONE); + + /** Serializable version identifier. */ + private static final long serialVersionUID = 4984534880991310382L; + + /** Underlying BigDecimal. */ + private final BigDecimal d; + + /** Rounding mode for divisions. * */ + private RoundingMode roundingMode = RoundingMode.HALF_UP; + + /*** BigDecimal scale ***/ + private int scale = 64; + + /** + * Build an instance from a BigDecimal. + * + * @param val value of the instance + */ + public BigReal(BigDecimal val) { + d = val; + } + + /** + * Build an instance from a BigInteger. + * + * @param val value of the instance + */ + public BigReal(BigInteger val) { + d = new BigDecimal(val); + } + + /** + * Build an instance from an unscaled BigInteger. + * + * @param unscaledVal unscaled value + * @param scale scale to use + */ + public BigReal(BigInteger unscaledVal, int scale) { + d = new BigDecimal(unscaledVal, scale); + } + + /** + * Build an instance from an unscaled BigInteger. + * + * @param unscaledVal unscaled value + * @param scale scale to use + * @param mc to used + */ + public BigReal(BigInteger unscaledVal, int scale, MathContext mc) { + d = new BigDecimal(unscaledVal, scale, mc); + } + + /** + * Build an instance from a BigInteger. + * + * @param val value of the instance + * @param mc context to use + */ + public BigReal(BigInteger val, MathContext mc) { + d = new BigDecimal(val, mc); + } + + /** + * Build an instance from a characters representation. + * + * @param in character representation of the value + */ + public BigReal(char[] in) { + d = new BigDecimal(in); + } + + /** + * Build an instance from a characters representation. + * + * @param in character representation of the value + * @param offset offset of the first character to analyze + * @param len length of the array slice to analyze + */ + public BigReal(char[] in, int offset, int len) { + d = new BigDecimal(in, offset, len); + } + + /** + * Build an instance from a characters representation. + * + * @param in character representation of the value + * @param offset offset of the first character to analyze + * @param len length of the array slice to analyze + * @param mc context to use + */ + public BigReal(char[] in, int offset, int len, MathContext mc) { + d = new BigDecimal(in, offset, len, mc); + } + + /** + * Build an instance from a characters representation. + * + * @param in character representation of the value + * @param mc context to use + */ + public BigReal(char[] in, MathContext mc) { + d = new BigDecimal(in, mc); + } + + /** + * Build an instance from a double. + * + * @param val value of the instance + */ + public BigReal(double val) { + d = new BigDecimal(val); + } + + /** + * Build an instance from a double. + * + * @param val value of the instance + * @param mc context to use + */ + public BigReal(double val, MathContext mc) { + d = new BigDecimal(val, mc); + } + + /** + * Build an instance from an int. + * + * @param val value of the instance + */ + public BigReal(int val) { + d = new BigDecimal(val); + } + + /** + * Build an instance from an int. + * + * @param val value of the instance + * @param mc context to use + */ + public BigReal(int val, MathContext mc) { + d = new BigDecimal(val, mc); + } + + /** + * Build an instance from a long. + * + * @param val value of the instance + */ + public BigReal(long val) { + d = new BigDecimal(val); + } + + /** + * Build an instance from a long. + * + * @param val value of the instance + * @param mc context to use + */ + public BigReal(long val, MathContext mc) { + d = new BigDecimal(val, mc); + } + + /** + * Build an instance from a String representation. + * + * @param val character representation of the value + */ + public BigReal(String val) { + d = new BigDecimal(val); + } + + /** + * Build an instance from a String representation. + * + * @param val character representation of the value + * @param mc context to use + */ + public BigReal(String val, MathContext mc) { + d = new BigDecimal(val, mc); + } + + /*** + * Gets the rounding mode for division operations + * The default is {@code RoundingMode.HALF_UP} + * @return the rounding mode. + * @since 2.1 + */ + public RoundingMode getRoundingMode() { + return roundingMode; + } + + /*** + * Sets the rounding mode for decimal divisions. + * @param roundingMode rounding mode for decimal divisions + * @since 2.1 + */ + public void setRoundingMode(RoundingMode roundingMode) { + this.roundingMode = roundingMode; + } + + /*** + * Sets the scale for division operations. + * The default is 64 + * @return the scale + * @since 2.1 + */ + public int getScale() { + return scale; + } + + /*** + * Sets the scale for division operations. + * @param scale scale for division operations + * @since 2.1 + */ + public void setScale(int scale) { + this.scale = scale; + } + + /** {@inheritDoc} */ + public BigReal add(BigReal a) { + return new BigReal(d.add(a.d)); + } + + /** {@inheritDoc} */ + public BigReal subtract(BigReal a) { + return new BigReal(d.subtract(a.d)); + } + + /** {@inheritDoc} */ + public BigReal negate() { + return new BigReal(d.negate()); + } + + /** + * {@inheritDoc} + * + * @throws MathArithmeticException if {@code a} is zero + */ + public BigReal divide(BigReal a) throws MathArithmeticException { + try { + return new BigReal(d.divide(a.d, scale, roundingMode)); + } catch (ArithmeticException e) { + // Division by zero has occurred + throw new MathArithmeticException(LocalizedFormats.ZERO_NOT_ALLOWED); + } + } + + /** + * {@inheritDoc} + * + * @throws MathArithmeticException if {@code this} is zero + */ + public BigReal reciprocal() throws MathArithmeticException { + try { + return new BigReal(BigDecimal.ONE.divide(d, scale, roundingMode)); + } catch (ArithmeticException e) { + // Division by zero has occurred + throw new MathArithmeticException(LocalizedFormats.ZERO_NOT_ALLOWED); + } + } + + /** {@inheritDoc} */ + public BigReal multiply(BigReal a) { + return new BigReal(d.multiply(a.d)); + } + + /** {@inheritDoc} */ + public BigReal multiply(final int n) { + return new BigReal(d.multiply(new BigDecimal(n))); + } + + /** {@inheritDoc} */ + public int compareTo(BigReal a) { + return d.compareTo(a.d); + } + + /** + * Get the double value corresponding to the instance. + * + * @return double value corresponding to the instance + */ + public double doubleValue() { + return d.doubleValue(); + } + + /** + * Get the BigDecimal value corresponding to the instance. + * + * @return BigDecimal value corresponding to the instance + */ + public BigDecimal bigDecimalValue() { + return d; + } + + /** {@inheritDoc} */ + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + + if (other instanceof BigReal) { + return d.equals(((BigReal) other).d); + } + return false; + } + + /** {@inheritDoc} */ + @Override + public int hashCode() { + return d.hashCode(); + } + + /** {@inheritDoc} */ + public Field<BigReal> getField() { + return BigRealField.getInstance(); + } +} diff --git a/src/main/java/org/apache/commons/math3/util/BigRealField.java b/src/main/java/org/apache/commons/math3/util/BigRealField.java new file mode 100644 index 0000000..cde8d34 --- /dev/null +++ b/src/main/java/org/apache/commons/math3/util/BigRealField.java @@ -0,0 +1,87 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.math3.util; + +import org.apache.commons.math3.Field; +import org.apache.commons.math3.FieldElement; + +import java.io.Serializable; + +/** + * Representation of real numbers with arbitrary precision field. + * + * <p>This class is a singleton. + * + * @see BigReal + * @since 2.0 + */ +public class BigRealField implements Field<BigReal>, Serializable { + + /** Serializable version identifier */ + private static final long serialVersionUID = 4756431066541037559L; + + /** Private constructor for the singleton. */ + private BigRealField() {} + + /** + * Get the unique instance. + * + * @return the unique instance + */ + public static BigRealField getInstance() { + return LazyHolder.INSTANCE; + } + + /** {@inheritDoc} */ + public BigReal getOne() { + return BigReal.ONE; + } + + /** {@inheritDoc} */ + public BigReal getZero() { + return BigReal.ZERO; + } + + /** {@inheritDoc} */ + public Class<? extends FieldElement<BigReal>> getRuntimeClass() { + return BigReal.class; + } + + // CHECKSTYLE: stop HideUtilityClassConstructor + /** + * Holder for the instance. + * + * <p>We use here the Initialization On Demand Holder Idiom. + */ + private static class LazyHolder { + /** Cached field instance. */ + private static final BigRealField INSTANCE = new BigRealField(); + } + + // CHECKSTYLE: resume HideUtilityClassConstructor + + /** + * Handle deserialization of the singleton. + * + * @return the singleton instance + */ + private Object readResolve() { + // return the singleton instance + return LazyHolder.INSTANCE; + } +} diff --git a/src/main/java/org/apache/commons/math3/util/CentralPivotingStrategy.java b/src/main/java/org/apache/commons/math3/util/CentralPivotingStrategy.java new file mode 100644 index 0000000..3762b8e --- /dev/null +++ b/src/main/java/org/apache/commons/math3/util/CentralPivotingStrategy.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math3.util; + +import org.apache.commons.math3.exception.MathIllegalArgumentException; + +import java.io.Serializable; + +/** + * A mid point strategy based on the average of begin and end indices. + * + * @since 3.4 + */ +public class CentralPivotingStrategy implements PivotingStrategyInterface, Serializable { + + /** Serializable UID. */ + private static final long serialVersionUID = 20140713L; + + /** + * {@inheritDoc} This in particular picks a average of begin and end indices + * + * @return The index corresponding to a simple average of the first and the last element indices + * of the array slice + * @throws MathIllegalArgumentException when indices exceeds range + */ + public int pivotIndex(final double[] work, final int begin, final int end) + throws MathIllegalArgumentException { + MathArrays.verifyValues(work, begin, end - begin); + return begin + (end - begin) / 2; + } +} diff --git a/src/main/java/org/apache/commons/math3/util/Combinations.java b/src/main/java/org/apache/commons/math3/util/Combinations.java new file mode 100644 index 0000000..8721dae --- /dev/null +++ b/src/main/java/org/apache/commons/math3/util/Combinations.java @@ -0,0 +1,384 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math3.util; + +import org.apache.commons.math3.exception.DimensionMismatchException; +import org.apache.commons.math3.exception.MathInternalError; +import org.apache.commons.math3.exception.OutOfRangeException; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.Comparator; +import java.util.Iterator; +import java.util.NoSuchElementException; + +/** + * Utility to create <a href="http://en.wikipedia.org/wiki/Combination">combinations</a> {@code (n, + * k)} of {@code k} elements in a set of {@code n} elements. + * + * @since 3.3 + */ +public class Combinations implements Iterable<int[]> { + /** Size of the set from which combinations are drawn. */ + private final int n; + + /** Number of elements in each combination. */ + private final int k; + + /** Iteration order. */ + private final IterationOrder iterationOrder; + + /** Describes the type of iteration performed by the {@link #iterator() iterator}. */ + private enum IterationOrder { + /** Lexicographic order. */ + LEXICOGRAPHIC + } + + /** + * Creates an instance whose range is the k-element subsets of {0, ..., n - 1} represented as + * {@code int[]} arrays. + * + * <p>The iteration order is lexicographic: the arrays returned by the {@link #iterator() + * iterator} are sorted in descending order and they are visited in lexicographic order with + * significance from right to left. For example, {@code new Combinations(4, 2).iterator()} + * returns an iterator that will generate the following sequence of arrays on successive calls + * to {@code next()}:<br> + * {@code [0, 1], [0, 2], [1, 2], [0, 3], [1, 3], [2, 3]} If {@code k == 0} an iterator + * containing an empty array is returned; if {@code k == n} an iterator containing [0, ..., n - + * 1] is returned. + * + * @param n Size of the set from which subsets are selected. + * @param k Size of the subsets to be enumerated. + * @throws org.apache.commons.math3.exception.NotPositiveException if {@code n < 0}. + * @throws org.apache.commons.math3.exception.NumberIsTooLargeException if {@code k > n}. + */ + public Combinations(int n, int k) { + this(n, k, IterationOrder.LEXICOGRAPHIC); + } + + /** + * Creates an instance whose range is the k-element subsets of {0, ..., n - 1} represented as + * {@code int[]} arrays. + * + * <p>If the {@code iterationOrder} argument is set to {@link IterationOrder#LEXICOGRAPHIC}, the + * arrays returned by the {@link #iterator() iterator} are sorted in descending order and they + * are visited in lexicographic order with significance from right to left. For example, {@code + * new Combinations(4, 2).iterator()} returns an iterator that will generate the following + * sequence of arrays on successive calls to {@code next()}:<br> + * {@code [0, 1], [0, 2], [1, 2], [0, 3], [1, 3], [2, 3]} If {@code k == 0} an iterator + * containing an empty array is returned; if {@code k == n} an iterator containing [0, ..., n - + * 1] is returned. + * + * @param n Size of the set from which subsets are selected. + * @param k Size of the subsets to be enumerated. + * @param iterationOrder Specifies the {@link #iterator() iteration order}. + * @throws org.apache.commons.math3.exception.NotPositiveException if {@code n < 0}. + * @throws org.apache.commons.math3.exception.NumberIsTooLargeException if {@code k > n}. + */ + private Combinations(int n, int k, IterationOrder iterationOrder) { + CombinatoricsUtils.checkBinomial(n, k); + this.n = n; + this.k = k; + this.iterationOrder = iterationOrder; + } + + /** + * Gets the size of the set from which combinations are drawn. + * + * @return the size of the universe. + */ + public int getN() { + return n; + } + + /** + * Gets the number of elements in each combination. + * + * @return the size of the subsets to be enumerated. + */ + public int getK() { + return k; + } + + /** {@inheritDoc} */ + public Iterator<int[]> iterator() { + if (k == 0 || k == n) { + return new SingletonIterator(MathArrays.natural(k)); + } + + switch (iterationOrder) { + case LEXICOGRAPHIC: + return new LexicographicIterator(n, k); + default: + throw new MathInternalError(); // Should never happen. + } + } + + /** + * Defines a lexicographic ordering of combinations. The returned comparator allows to compare + * any two combinations that can be produced by this instance's {@link #iterator() iterator}. + * Its {@code compare(int[],int[])} method will throw exceptions if passed combinations that are + * inconsistent with this instance: + * + * <ul> + * <li>{@code DimensionMismatchException} if the array lengths are not equal to {@code k}, + * <li>{@code OutOfRangeException} if an element of the array is not within the interval [0, + * {@code n}). + * </ul> + * + * @return a lexicographic comparator. + */ + public Comparator<int[]> comparator() { + return new LexicographicComparator(n, k); + } + + /** + * Lexicographic combinations iterator. + * + * <p>Implementation follows Algorithm T in <i>The Art of Computer Programming</i> Internet + * Draft (PRE-FASCICLE 3A), "A Draft of Section 7.2.1.3 Generating All Combinations</a>, D. + * Knuth, 2004. + * + * <p>The degenerate cases {@code k == 0} and {@code k == n} are NOT handled by this + * implementation. If constructor arguments satisfy {@code k == 0} or {@code k >= n}, no + * exception is generated, but the iterator is empty. + */ + private static class LexicographicIterator implements Iterator<int[]> { + /** Size of subsets returned by the iterator */ + private final int k; + + /** + * c[1], ..., c[k] stores the next combination; c[k + 1], c[k + 2] are sentinels. + * + * <p>Note that c[0] is "wasted" but this makes it a little easier to follow the code. + */ + private final int[] c; + + /** Return value for {@link #hasNext()} */ + private boolean more = true; + + /** Marker: smallest index such that c[j + 1] > j */ + private int j; + + /** + * Construct a CombinationIterator to enumerate k-sets from n. + * + * <p>NOTE: If {@code k === 0} or {@code k >= n}, the Iterator will be empty (that is, + * {@link #hasNext()} will return {@code false} immediately. + * + * @param n size of the set from which subsets are enumerated + * @param k size of the subsets to enumerate + */ + LexicographicIterator(int n, int k) { + this.k = k; + c = new int[k + 3]; + if (k == 0 || k >= n) { + more = false; + return; + } + // Initialize c to start with lexicographically first k-set + for (int i = 1; i <= k; i++) { + c[i] = i - 1; + } + // Initialize sentinels + c[k + 1] = n; + c[k + 2] = 0; + j = k; // Set up invariant: j is smallest index such that c[j + 1] > j + } + + /** {@inheritDoc} */ + public boolean hasNext() { + return more; + } + + /** {@inheritDoc} */ + public int[] next() { + if (!more) { + throw new NoSuchElementException(); + } + // Copy return value (prepared by last activation) + final int[] ret = new int[k]; + System.arraycopy(c, 1, ret, 0, k); + + // Prepare next iteration + // T2 and T6 loop + int x = 0; + if (j > 0) { + x = j; + c[j] = x; + j--; + return ret; + } + // T3 + if (c[1] + 1 < c[2]) { + c[1]++; + return ret; + } else { + j = 2; + } + // T4 + boolean stepDone = false; + while (!stepDone) { + c[j - 1] = j - 2; + x = c[j] + 1; + if (x == c[j + 1]) { + j++; + } else { + stepDone = true; + } + } + // T5 + if (j > k) { + more = false; + return ret; + } + // T6 + c[j] = x; + j--; + return ret; + } + + /** Not supported. */ + public void remove() { + throw new UnsupportedOperationException(); + } + } + + /** + * Iterator with just one element to handle degenerate cases (full array, empty array) for + * combination iterator. + */ + private static class SingletonIterator implements Iterator<int[]> { + /** Singleton array */ + private final int[] singleton; + + /** True on initialization, false after first call to next */ + private boolean more = true; + + /** + * Create a singleton iterator providing the given array. + * + * @param singleton array returned by the iterator + */ + SingletonIterator(final int[] singleton) { + this.singleton = singleton; + } + + /** + * @return True until next is called the first time, then false + */ + public boolean hasNext() { + return more; + } + + /** + * @return the singleton in first activation; throws NSEE thereafter + */ + public int[] next() { + if (more) { + more = false; + return singleton; + } else { + throw new NoSuchElementException(); + } + } + + /** Not supported */ + public void remove() { + throw new UnsupportedOperationException(); + } + } + + /** + * Defines the lexicographic ordering of combinations, using the {@link #lexNorm(int[])} method. + */ + private static class LexicographicComparator implements Comparator<int[]>, Serializable { + /** Serializable version identifier. */ + private static final long serialVersionUID = 20130906L; + + /** Size of the set from which combinations are drawn. */ + private final int n; + + /** Number of elements in each combination. */ + private final int k; + + /** + * @param n Size of the set from which subsets are selected. + * @param k Size of the subsets to be enumerated. + */ + LexicographicComparator(int n, int k) { + this.n = n; + this.k = k; + } + + /** + * {@inheritDoc} + * + * @throws DimensionMismatchException if the array lengths are not equal to {@code k}. + * @throws OutOfRangeException if an element of the array is not within the interval [0, + * {@code n}). + */ + public int compare(int[] c1, int[] c2) { + if (c1.length != k) { + throw new DimensionMismatchException(c1.length, k); + } + if (c2.length != k) { + throw new DimensionMismatchException(c2.length, k); + } + + // Method "lexNorm" works with ordered arrays. + final int[] c1s = MathArrays.copyOf(c1); + Arrays.sort(c1s); + final int[] c2s = MathArrays.copyOf(c2); + Arrays.sort(c2s); + + final long v1 = lexNorm(c1s); + final long v2 = lexNorm(c2s); + + if (v1 < v2) { + return -1; + } else if (v1 > v2) { + return 1; + } else { + return 0; + } + } + + /** + * Computes the value (in base 10) represented by the digit (interpreted in base {@code n}) + * in the input array in reverse order. For example if {@code c} is {@code {3, 2, 1}}, and + * {@code n} is 3, the method will return 18. + * + * @param c Input array. + * @return the lexicographic norm. + * @throws OutOfRangeException if an element of the array is not within the interval [0, + * {@code n}). + */ + private long lexNorm(int[] c) { + long ret = 0; + for (int i = 0; i < c.length; i++) { + final int digit = c[i]; + if (digit < 0 || digit >= n) { + throw new OutOfRangeException(digit, 0, n - 1); + } + + ret += c[i] * ArithmeticUtils.pow(n, i); + } + return ret; + } + } +} diff --git a/src/main/java/org/apache/commons/math3/util/CombinatoricsUtils.java b/src/main/java/org/apache/commons/math3/util/CombinatoricsUtils.java new file mode 100644 index 0000000..9743a6b --- /dev/null +++ b/src/main/java/org/apache/commons/math3/util/CombinatoricsUtils.java @@ -0,0 +1,460 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math3.util; + +import org.apache.commons.math3.exception.MathArithmeticException; +import org.apache.commons.math3.exception.NotPositiveException; +import org.apache.commons.math3.exception.NumberIsTooLargeException; +import org.apache.commons.math3.exception.util.LocalizedFormats; + +import java.util.Iterator; +import java.util.concurrent.atomic.AtomicReference; + +/** + * Combinatorial utilities. + * + * @since 3.3 + */ +public final class CombinatoricsUtils { + + /** All long-representable factorials */ + static final long[] FACTORIALS = + new long[] { + 1l, + 1l, + 2l, + 6l, + 24l, + 120l, + 720l, + 5040l, + 40320l, + 362880l, + 3628800l, + 39916800l, + 479001600l, + 6227020800l, + 87178291200l, + 1307674368000l, + 20922789888000l, + 355687428096000l, + 6402373705728000l, + 121645100408832000l, + 2432902008176640000l + }; + + /** Stirling numbers of the second kind. */ + static final AtomicReference<long[][]> STIRLING_S2 = new AtomicReference<long[][]>(null); + + /** Private constructor (class contains only static methods). */ + private CombinatoricsUtils() {} + + /** + * Returns an exact representation of the <a + * href="http://mathworld.wolfram.com/BinomialCoefficient.html">Binomial Coefficient</a>, + * "{@code n choose k}", the number of {@code k}-element subsets that can be selected from an + * {@code n}-element set. + * + * <p><Strong>Preconditions</strong>: + * + * <ul> + * <li>{@code 0 <= k <= n } (otherwise {@code MathIllegalArgumentException} is thrown) + * <li>The result is small enough to fit into a {@code long}. The largest value of {@code n} + * for which all coefficients are {@code < Long.MAX_VALUE} is 66. If the computed value + * exceeds {@code Long.MAX_VALUE} a {@code MathArithMeticException} is thrown. + * </ul> + * + * @param n the size of the set + * @param k the size of the subsets to be counted + * @return {@code n choose k} + * @throws NotPositiveException if {@code n < 0}. + * @throws NumberIsTooLargeException if {@code k > n}. + * @throws MathArithmeticException if the result is too large to be represented by a long + * integer. + */ + public static long binomialCoefficient(final int n, final int k) + throws NotPositiveException, NumberIsTooLargeException, MathArithmeticException { + CombinatoricsUtils.checkBinomial(n, k); + if ((n == k) || (k == 0)) { + return 1; + } + if ((k == 1) || (k == n - 1)) { + return n; + } + // Use symmetry for large k + if (k > n / 2) { + return binomialCoefficient(n, n - k); + } + + // We use the formula + // (n choose k) = n! / (n-k)! / k! + // (n choose k) == ((n-k+1)*...*n) / (1*...*k) + // which could be written + // (n choose k) == (n-1 choose k-1) * n / k + long result = 1; + if (n <= 61) { + // For n <= 61, the naive implementation cannot overflow. + int i = n - k + 1; + for (int j = 1; j <= k; j++) { + result = result * i / j; + i++; + } + } else if (n <= 66) { + // For n > 61 but n <= 66, the result cannot overflow, + // but we must take care not to overflow intermediate values. + int i = n - k + 1; + for (int j = 1; j <= k; j++) { + // We know that (result * i) is divisible by j, + // but (result * i) may overflow, so we split j: + // Filter out the gcd, d, so j/d and i/d are integer. + // result is divisible by (j/d) because (j/d) + // is relative prime to (i/d) and is a divisor of + // result * (i/d). + final long d = ArithmeticUtils.gcd(i, j); + result = (result / (j / d)) * (i / d); + i++; + } + } else { + // For n > 66, a result overflow might occur, so we check + // the multiplication, taking care to not overflow + // unnecessary. + int i = n - k + 1; + for (int j = 1; j <= k; j++) { + final long d = ArithmeticUtils.gcd(i, j); + result = ArithmeticUtils.mulAndCheck(result / (j / d), i / d); + i++; + } + } + return result; + } + + /** + * Returns a {@code double} representation of the <a + * href="http://mathworld.wolfram.com/BinomialCoefficient.html">Binomial Coefficient</a>, + * "{@code n choose k}", the number of {@code k}-element subsets that can be selected from an + * {@code n}-element set. + * + * <p><Strong>Preconditions</strong>: + * + * <ul> + * <li>{@code 0 <= k <= n } (otherwise {@code IllegalArgumentException} is thrown) + * <li>The result is small enough to fit into a {@code double}. The largest value of {@code n} + * for which all coefficients are less than Double.MAX_VALUE is 1029. If the computed + * value exceeds Double.MAX_VALUE, Double.POSITIVE_INFINITY is returned + * </ul> + * + * @param n the size of the set + * @param k the size of the subsets to be counted + * @return {@code n choose k} + * @throws NotPositiveException if {@code n < 0}. + * @throws NumberIsTooLargeException if {@code k > n}. + * @throws MathArithmeticException if the result is too large to be represented by a long + * integer. + */ + public static double binomialCoefficientDouble(final int n, final int k) + throws NotPositiveException, NumberIsTooLargeException, MathArithmeticException { + CombinatoricsUtils.checkBinomial(n, k); + if ((n == k) || (k == 0)) { + return 1d; + } + if ((k == 1) || (k == n - 1)) { + return n; + } + if (k > n / 2) { + return binomialCoefficientDouble(n, n - k); + } + if (n < 67) { + return binomialCoefficient(n, k); + } + + double result = 1d; + for (int i = 1; i <= k; i++) { + result *= (double) (n - k + i) / (double) i; + } + + return FastMath.floor(result + 0.5); + } + + /** + * Returns the natural {@code log} of the <a + * href="http://mathworld.wolfram.com/BinomialCoefficient.html">Binomial Coefficient</a>, + * "{@code n choose k}", the number of {@code k}-element subsets that can be selected from an + * {@code n}-element set. + * + * <p><Strong>Preconditions</strong>: + * + * <ul> + * <li>{@code 0 <= k <= n } (otherwise {@code MathIllegalArgumentException} is thrown) + * </ul> + * + * @param n the size of the set + * @param k the size of the subsets to be counted + * @return {@code n choose k} + * @throws NotPositiveException if {@code n < 0}. + * @throws NumberIsTooLargeException if {@code k > n}. + * @throws MathArithmeticException if the result is too large to be represented by a long + * integer. + */ + public static double binomialCoefficientLog(final int n, final int k) + throws NotPositiveException, NumberIsTooLargeException, MathArithmeticException { + CombinatoricsUtils.checkBinomial(n, k); + if ((n == k) || (k == 0)) { + return 0; + } + if ((k == 1) || (k == n - 1)) { + return FastMath.log(n); + } + + /* + * For values small enough to do exact integer computation, + * return the log of the exact value + */ + if (n < 67) { + return FastMath.log(binomialCoefficient(n, k)); + } + + /* + * Return the log of binomialCoefficientDouble for values that will not + * overflow binomialCoefficientDouble + */ + if (n < 1030) { + return FastMath.log(binomialCoefficientDouble(n, k)); + } + + if (k > n / 2) { + return binomialCoefficientLog(n, n - k); + } + + /* + * Sum logs for values that could overflow + */ + double logSum = 0; + + // n!/(n-k)! + for (int i = n - k + 1; i <= n; i++) { + logSum += FastMath.log(i); + } + + // divide by k! + for (int i = 2; i <= k; i++) { + logSum -= FastMath.log(i); + } + + return logSum; + } + + /** + * Returns n!. Shorthand for {@code n} <a href="http://mathworld.wolfram.com/Factorial.html"> + * Factorial</a>, the product of the numbers {@code 1,...,n}. + * + * <p><Strong>Preconditions</strong>: + * + * <ul> + * <li>{@code n >= 0} (otherwise {@code MathIllegalArgumentException} is thrown) + * <li>The result is small enough to fit into a {@code long}. The largest value of {@code n} + * for which {@code n!} does not exceed Long.MAX_VALUE} is 20. If the computed value + * exceeds {@code Long.MAX_VALUE} an {@code MathArithMeticException } is thrown. + * </ul> + * + * @param n argument + * @return {@code n!} + * @throws MathArithmeticException if the result is too large to be represented by a {@code + * long}. + * @throws NotPositiveException if {@code n < 0}. + * @throws MathArithmeticException if {@code n > 20}: The factorial value is too large to fit in + * a {@code long}. + */ + public static long factorial(final int n) throws NotPositiveException, MathArithmeticException { + if (n < 0) { + throw new NotPositiveException(LocalizedFormats.FACTORIAL_NEGATIVE_PARAMETER, n); + } + if (n > 20) { + throw new MathArithmeticException(); + } + return FACTORIALS[n]; + } + + /** + * Compute n!, the<a href="http://mathworld.wolfram.com/Factorial.html">factorial</a> of {@code + * n} (the product of the numbers 1 to n), as a {@code double}. The result should be small + * enough to fit into a {@code double}: The largest {@code n} for which {@code n!} does not + * exceed {@code Double.MAX_VALUE} is 170. If the computed value exceeds {@code + * Double.MAX_VALUE}, {@code Double.POSITIVE_INFINITY} is returned. + * + * @param n Argument. + * @return {@code n!} + * @throws NotPositiveException if {@code n < 0}. + */ + public static double factorialDouble(final int n) throws NotPositiveException { + if (n < 0) { + throw new NotPositiveException(LocalizedFormats.FACTORIAL_NEGATIVE_PARAMETER, n); + } + if (n < 21) { + return FACTORIALS[n]; + } + return FastMath.floor(FastMath.exp(CombinatoricsUtils.factorialLog(n)) + 0.5); + } + + /** + * Compute the natural logarithm of the factorial of {@code n}. + * + * @param n Argument. + * @return {@code n!} + * @throws NotPositiveException if {@code n < 0}. + */ + public static double factorialLog(final int n) throws NotPositiveException { + if (n < 0) { + throw new NotPositiveException(LocalizedFormats.FACTORIAL_NEGATIVE_PARAMETER, n); + } + if (n < 21) { + return FastMath.log(FACTORIALS[n]); + } + double logSum = 0; + for (int i = 2; i <= n; i++) { + logSum += FastMath.log(i); + } + return logSum; + } + + /** + * Returns the <a href="http://mathworld.wolfram.com/StirlingNumberoftheSecondKind.html"> + * Stirling number of the second kind</a>, "{@code S(n,k)}", the number of ways of partitioning + * an {@code n}-element set into {@code k} non-empty subsets. + * + * <p>The preconditions are {@code 0 <= k <= n } (otherwise {@code NotPositiveException} is + * thrown) + * + * @param n the size of the set + * @param k the number of non-empty subsets + * @return {@code S(n,k)} + * @throws NotPositiveException if {@code k < 0}. + * @throws NumberIsTooLargeException if {@code k > n}. + * @throws MathArithmeticException if some overflow happens, typically for n exceeding 25 and k + * between 20 and n-2 (S(n,n-1) is handled specifically and does not overflow) + * @since 3.1 + */ + public static long stirlingS2(final int n, final int k) + throws NotPositiveException, NumberIsTooLargeException, MathArithmeticException { + if (k < 0) { + throw new NotPositiveException(k); + } + if (k > n) { + throw new NumberIsTooLargeException(k, n, true); + } + + long[][] stirlingS2 = STIRLING_S2.get(); + + if (stirlingS2 == null) { + // the cache has never been initialized, compute the first numbers + // by direct recurrence relation + + // as S(26,9) = 11201516780955125625 is larger than Long.MAX_VALUE + // we must stop computation at row 26 + final int maxIndex = 26; + stirlingS2 = new long[maxIndex][]; + stirlingS2[0] = new long[] {1l}; + for (int i = 1; i < stirlingS2.length; ++i) { + stirlingS2[i] = new long[i + 1]; + stirlingS2[i][0] = 0; + stirlingS2[i][1] = 1; + stirlingS2[i][i] = 1; + for (int j = 2; j < i; ++j) { + stirlingS2[i][j] = j * stirlingS2[i - 1][j] + stirlingS2[i - 1][j - 1]; + } + } + + // atomically save the cache + STIRLING_S2.compareAndSet(null, stirlingS2); + } + + if (n < stirlingS2.length) { + // the number is in the small cache + return stirlingS2[n][k]; + } else { + // use explicit formula to compute the number without caching it + if (k == 0) { + return 0; + } else if (k == 1 || k == n) { + return 1; + } else if (k == 2) { + return (1l << (n - 1)) - 1l; + } else if (k == n - 1) { + return binomialCoefficient(n, 2); + } else { + // definition formula: note that this may trigger some overflow + long sum = 0; + long sign = ((k & 0x1) == 0) ? 1 : -1; + for (int j = 1; j <= k; ++j) { + sign = -sign; + sum += sign * binomialCoefficient(k, j) * ArithmeticUtils.pow(j, n); + if (sum < 0) { + // there was an overflow somewhere + throw new MathArithmeticException( + LocalizedFormats.ARGUMENT_OUTSIDE_DOMAIN, + n, + 0, + stirlingS2.length - 1); + } + } + return sum / factorial(k); + } + } + } + + /** + * Returns an iterator whose range is the k-element subsets of {0, ..., n - 1} represented as + * {@code int[]} arrays. + * + * <p>The arrays returned by the iterator are sorted in descending order and they are visited in + * lexicographic order with significance from right to left. For example, + * combinationsIterator(4, 2) returns an Iterator that will generate the following sequence of + * arrays on successive calls to {@code next()}: + * + * <p>{@code [0, 1], [0, 2], [1, 2], [0, 3], [1, 3], [2, 3]} + * + * <p>If {@code k == 0} an Iterator containing an empty array is returned and if {@code k == n} + * an Iterator containing [0, ..., n -1] is returned. + * + * @param n Size of the set from which subsets are selected. + * @param k Size of the subsets to be enumerated. + * @return an {@link Iterator iterator} over the k-sets in n. + * @throws NotPositiveException if {@code n < 0}. + * @throws NumberIsTooLargeException if {@code k > n}. + */ + public static Iterator<int[]> combinationsIterator(int n, int k) { + return new Combinations(n, k).iterator(); + } + + /** + * Check binomial preconditions. + * + * @param n Size of the set. + * @param k Size of the subsets to be counted. + * @throws NotPositiveException if {@code n < 0}. + * @throws NumberIsTooLargeException if {@code k > n}. + */ + public static void checkBinomial(final int n, final int k) + throws NumberIsTooLargeException, NotPositiveException { + if (n < k) { + throw new NumberIsTooLargeException( + LocalizedFormats.BINOMIAL_INVALID_PARAMETERS_ORDER, k, n, true); + } + if (n < 0) { + throw new NotPositiveException(LocalizedFormats.BINOMIAL_NEGATIVE_PARAMETER, n); + } + } +} diff --git a/src/main/java/org/apache/commons/math3/util/CompositeFormat.java b/src/main/java/org/apache/commons/math3/util/CompositeFormat.java new file mode 100644 index 0000000..63dfd59 --- /dev/null +++ b/src/main/java/org/apache/commons/math3/util/CompositeFormat.java @@ -0,0 +1,215 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math3.util; + +import java.text.FieldPosition; +import java.text.NumberFormat; +import java.text.ParsePosition; +import java.util.Locale; + +/** Base class for formatters of composite objects (complex numbers, vectors ...). */ +public class CompositeFormat { + + /** Class contains only static methods. */ + private CompositeFormat() {} + + /** + * Create a default number format. The default number format is based on {@link + * NumberFormat#getInstance()} with the only customizing that the maximum number of fraction + * digits is set to 10. + * + * @return the default number format. + */ + public static NumberFormat getDefaultNumberFormat() { + return getDefaultNumberFormat(Locale.getDefault()); + } + + /** + * Create a default number format. The default number format is based on {@link + * NumberFormat#getInstance(java.util.Locale)} with the only customizing that the maximum number + * of fraction digits is set to 10. + * + * @param locale the specific locale used by the format. + * @return the default number format specific to the given locale. + */ + public static NumberFormat getDefaultNumberFormat(final Locale locale) { + final NumberFormat nf = NumberFormat.getInstance(locale); + nf.setMaximumFractionDigits(10); + return nf; + } + + /** + * Parses <code>source</code> until a non-whitespace character is found. + * + * @param source the string to parse + * @param pos input/output parsing parameter. On output, <code>pos</code> holds the index of the + * next non-whitespace character. + */ + public static void parseAndIgnoreWhitespace(final String source, final ParsePosition pos) { + parseNextCharacter(source, pos); + pos.setIndex(pos.getIndex() - 1); + } + + /** + * Parses <code>source</code> until a non-whitespace character is found. + * + * @param source the string to parse + * @param pos input/output parsing parameter. + * @return the first non-whitespace character. + */ + public static char parseNextCharacter(final String source, final ParsePosition pos) { + int index = pos.getIndex(); + final int n = source.length(); + char ret = 0; + + if (index < n) { + char c; + do { + c = source.charAt(index++); + } while (Character.isWhitespace(c) && index < n); + pos.setIndex(index); + + if (index < n) { + ret = c; + } + } + + return ret; + } + + /** + * Parses <code>source</code> for special double values. These values include Double.NaN, + * Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY. + * + * @param source the string to parse + * @param value the special value to parse. + * @param pos input/output parsing parameter. + * @return the special number. + */ + private static Number parseNumber( + final String source, final double value, final ParsePosition pos) { + Number ret = null; + + StringBuilder sb = new StringBuilder(); + sb.append('('); + sb.append(value); + sb.append(')'); + + final int n = sb.length(); + final int startIndex = pos.getIndex(); + final int endIndex = startIndex + n; + if (endIndex < source.length() + && source.substring(startIndex, endIndex).compareTo(sb.toString()) == 0) { + ret = Double.valueOf(value); + pos.setIndex(endIndex); + } + + return ret; + } + + /** + * Parses <code>source</code> for a number. This method can parse normal, numeric values as well + * as special values. These special values include Double.NaN, Double.POSITIVE_INFINITY, + * Double.NEGATIVE_INFINITY. + * + * @param source the string to parse + * @param format the number format used to parse normal, numeric values. + * @param pos input/output parsing parameter. + * @return the parsed number. + */ + public static Number parseNumber( + final String source, final NumberFormat format, final ParsePosition pos) { + final int startIndex = pos.getIndex(); + Number number = format.parse(source, pos); + final int endIndex = pos.getIndex(); + + // check for error parsing number + if (startIndex == endIndex) { + // try parsing special numbers + final double[] special = { + Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY + }; + for (int i = 0; i < special.length; ++i) { + number = parseNumber(source, special[i], pos); + if (number != null) { + break; + } + } + } + + return number; + } + + /** + * Parse <code>source</code> for an expected fixed string. + * + * @param source the string to parse + * @param expected expected string + * @param pos input/output parsing parameter. + * @return true if the expected string was there + */ + public static boolean parseFixedstring( + final String source, final String expected, final ParsePosition pos) { + + final int startIndex = pos.getIndex(); + final int endIndex = startIndex + expected.length(); + if ((startIndex >= source.length()) + || (endIndex > source.length()) + || (source.substring(startIndex, endIndex).compareTo(expected) != 0)) { + // set index back to start, error index should be the start index + pos.setIndex(startIndex); + pos.setErrorIndex(startIndex); + return false; + } + + // the string was here + pos.setIndex(endIndex); + return true; + } + + /** + * Formats a double value to produce a string. In general, the value is formatted using the + * formatting rules of <code>format</code>. There are three exceptions to this: + * + * <ol> + * <li>NaN is formatted as '(NaN)' + * <li>Positive infinity is formatted as '(Infinity)' + * <li>Negative infinity is formatted as '(-Infinity)' + * </ol> + * + * @param value the double to format. + * @param format the format used. + * @param toAppendTo where the text is to be appended + * @param pos On input: an alignment field, if desired. On output: the offsets of the alignment + * field + * @return the value passed in as toAppendTo. + */ + public static StringBuffer formatDouble( + final double value, + final NumberFormat format, + final StringBuffer toAppendTo, + final FieldPosition pos) { + if (Double.isNaN(value) || Double.isInfinite(value)) { + toAppendTo.append('('); + toAppendTo.append(value); + toAppendTo.append(')'); + } else { + format.format(value, toAppendTo, pos); + } + return toAppendTo; + } +} diff --git a/src/main/java/org/apache/commons/math3/util/ContinuedFraction.java b/src/main/java/org/apache/commons/math3/util/ContinuedFraction.java new file mode 100644 index 0000000..69b4964 --- /dev/null +++ b/src/main/java/org/apache/commons/math3/util/ContinuedFraction.java @@ -0,0 +1,181 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math3.util; + +import org.apache.commons.math3.exception.ConvergenceException; +import org.apache.commons.math3.exception.MaxCountExceededException; +import org.apache.commons.math3.exception.util.LocalizedFormats; + +/** + * Provides a generic means to evaluate continued fractions. Subclasses simply provided the a and b + * coefficients to evaluate the continued fraction. + * + * <p>References: + * + * <ul> + * <li><a href="http://mathworld.wolfram.com/ContinuedFraction.html">Continued Fraction</a> + * </ul> + */ +public abstract class ContinuedFraction { + /** Maximum allowed numerical error. */ + private static final double DEFAULT_EPSILON = 10e-9; + + /** Default constructor. */ + protected ContinuedFraction() { + super(); + } + + /** + * Access the n-th a coefficient of the continued fraction. Since a can be a function of the + * evaluation point, x, that is passed in as well. + * + * @param n the coefficient index to retrieve. + * @param x the evaluation point. + * @return the n-th a coefficient. + */ + protected abstract double getA(int n, double x); + + /** + * Access the n-th b coefficient of the continued fraction. Since b can be a function of the + * evaluation point, x, that is passed in as well. + * + * @param n the coefficient index to retrieve. + * @param x the evaluation point. + * @return the n-th b coefficient. + */ + protected abstract double getB(int n, double x); + + /** + * Evaluates the continued fraction at the value x. + * + * @param x the evaluation point. + * @return the value of the continued fraction evaluated at x. + * @throws ConvergenceException if the algorithm fails to converge. + */ + public double evaluate(double x) throws ConvergenceException { + return evaluate(x, DEFAULT_EPSILON, Integer.MAX_VALUE); + } + + /** + * Evaluates the continued fraction at the value x. + * + * @param x the evaluation point. + * @param epsilon maximum error allowed. + * @return the value of the continued fraction evaluated at x. + * @throws ConvergenceException if the algorithm fails to converge. + */ + public double evaluate(double x, double epsilon) throws ConvergenceException { + return evaluate(x, epsilon, Integer.MAX_VALUE); + } + + /** + * Evaluates the continued fraction at the value x. + * + * @param x the evaluation point. + * @param maxIterations maximum number of convergents + * @return the value of the continued fraction evaluated at x. + * @throws ConvergenceException if the algorithm fails to converge. + * @throws MaxCountExceededException if maximal number of iterations is reached + */ + public double evaluate(double x, int maxIterations) + throws ConvergenceException, MaxCountExceededException { + return evaluate(x, DEFAULT_EPSILON, maxIterations); + } + + /** + * Evaluates the continued fraction at the value x. + * + * <p>The implementation of this method is based on the modified Lentz algorithm as described on + * page 18 ff. in: + * + * <ul> + * <li>I. J. Thompson, A. R. Barnett. "Coulomb and Bessel Functions of Complex Arguments and + * Order." <a target="_blank" + * href="http://www.fresco.org.uk/papers/Thompson-JCP64p490.pdf"> + * http://www.fresco.org.uk/papers/Thompson-JCP64p490.pdf</a> + * </ul> + * + * <b>Note:</b> the implementation uses the terms a<sub>i</sub> and b<sub>i</sub> as defined in + * <a href="http://mathworld.wolfram.com/ContinuedFraction.html">Continued Fraction @ + * MathWorld</a>. + * + * @param x the evaluation point. + * @param epsilon maximum error allowed. + * @param maxIterations maximum number of convergents + * @return the value of the continued fraction evaluated at x. + * @throws ConvergenceException if the algorithm fails to converge. + * @throws MaxCountExceededException if maximal number of iterations is reached + */ + public double evaluate(double x, double epsilon, int maxIterations) + throws ConvergenceException, MaxCountExceededException { + final double small = 1e-50; + double hPrev = getA(0, x); + + // use the value of small as epsilon criteria for zero checks + if (Precision.equals(hPrev, 0.0, small)) { + hPrev = small; + } + + int n = 1; + double dPrev = 0.0; + double cPrev = hPrev; + double hN = hPrev; + + while (n < maxIterations) { + final double a = getA(n, x); + final double b = getB(n, x); + + double dN = a + b * dPrev; + if (Precision.equals(dN, 0.0, small)) { + dN = small; + } + double cN = a + b / cPrev; + if (Precision.equals(cN, 0.0, small)) { + cN = small; + } + + dN = 1 / dN; + final double deltaN = cN * dN; + hN = hPrev * deltaN; + + if (Double.isInfinite(hN)) { + throw new ConvergenceException( + LocalizedFormats.CONTINUED_FRACTION_INFINITY_DIVERGENCE, x); + } + if (Double.isNaN(hN)) { + throw new ConvergenceException( + LocalizedFormats.CONTINUED_FRACTION_NAN_DIVERGENCE, x); + } + + if (FastMath.abs(deltaN - 1.0) < epsilon) { + break; + } + + dPrev = dN; + cPrev = cN; + hPrev = hN; + n++; + } + + if (n >= maxIterations) { + throw new MaxCountExceededException( + LocalizedFormats.NON_CONVERGENT_CONTINUED_FRACTION, maxIterations, x); + } + + return hN; + } +} diff --git a/src/main/java/org/apache/commons/math3/util/Decimal64.java b/src/main/java/org/apache/commons/math3/util/Decimal64.java new file mode 100644 index 0000000..4d25339 --- /dev/null +++ b/src/main/java/org/apache/commons/math3/util/Decimal64.java @@ -0,0 +1,806 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math3.util; + +import org.apache.commons.math3.Field; +import org.apache.commons.math3.RealFieldElement; +import org.apache.commons.math3.exception.DimensionMismatchException; + +/** + * This class wraps a {@code double} value in an object. It is similar to the standard class {@link + * Double}, while also implementing the {@link RealFieldElement} interface. + * + * @since 3.1 + */ +public class Decimal64 extends Number + implements RealFieldElement<Decimal64>, Comparable<Decimal64> { + + /** The constant value of {@code 0d} as a {@code Decimal64}. */ + public static final Decimal64 ZERO; + + /** The constant value of {@code 1d} as a {@code Decimal64}. */ + public static final Decimal64 ONE; + + /** The constant value of {@link Double#NEGATIVE_INFINITY} as a {@code Decimal64}. */ + public static final Decimal64 NEGATIVE_INFINITY; + + /** The constant value of {@link Double#POSITIVE_INFINITY} as a {@code Decimal64}. */ + public static final Decimal64 POSITIVE_INFINITY; + + /** The constant value of {@link Double#NaN} as a {@code Decimal64}. */ + public static final Decimal64 NAN; + + /** */ + private static final long serialVersionUID = 20120227L; + + static { + ZERO = new Decimal64(0d); + ONE = new Decimal64(1d); + NEGATIVE_INFINITY = new Decimal64(Double.NEGATIVE_INFINITY); + POSITIVE_INFINITY = new Decimal64(Double.POSITIVE_INFINITY); + NAN = new Decimal64(Double.NaN); + } + + /** The primitive {@code double} value of this object. */ + private final double value; + + /** + * Creates a new instance of this class. + * + * @param x the primitive {@code double} value of the object to be created + */ + public Decimal64(final double x) { + this.value = x; + } + + /* + * Methods from the FieldElement interface. + */ + + /** {@inheritDoc} */ + public Field<Decimal64> getField() { + return Decimal64Field.getInstance(); + } + + /** + * {@inheritDoc} + * + * <p>The current implementation strictly enforces {@code this.add(a).equals(new + * Decimal64(this.doubleValue() + a.doubleValue()))}. + */ + public Decimal64 add(final Decimal64 a) { + return new Decimal64(this.value + a.value); + } + + /** + * {@inheritDoc} + * + * <p>The current implementation strictly enforces {@code this.subtract(a).equals(new + * Decimal64(this.doubleValue() - a.doubleValue()))}. + */ + public Decimal64 subtract(final Decimal64 a) { + return new Decimal64(this.value - a.value); + } + + /** + * {@inheritDoc} + * + * <p>The current implementation strictly enforces {@code this.negate().equals(new + * Decimal64(-this.doubleValue()))}. + */ + public Decimal64 negate() { + return new Decimal64(-this.value); + } + + /** + * {@inheritDoc} + * + * <p>The current implementation strictly enforces {@code this.multiply(a).equals(new + * Decimal64(this.doubleValue() * a.doubleValue()))}. + */ + public Decimal64 multiply(final Decimal64 a) { + return new Decimal64(this.value * a.value); + } + + /** + * {@inheritDoc} + * + * <p>The current implementation strictly enforces {@code this.multiply(n).equals(new + * Decimal64(n * this.doubleValue()))}. + */ + public Decimal64 multiply(final int n) { + return new Decimal64(n * this.value); + } + + /** + * {@inheritDoc} + * + * <p>The current implementation strictly enforces {@code this.divide(a).equals(new + * Decimal64(this.doubleValue() / a.doubleValue()))}. + */ + public Decimal64 divide(final Decimal64 a) { + return new Decimal64(this.value / a.value); + } + + /** + * {@inheritDoc} + * + * <p>The current implementation strictly enforces {@code this.reciprocal().equals(new + * Decimal64(1.0 / this.doubleValue()))}. + */ + public Decimal64 reciprocal() { + return new Decimal64(1.0 / this.value); + } + + /* + * Methods from the Number abstract class + */ + + /** + * {@inheritDoc} + * + * <p>The current implementation performs casting to a {@code byte}. + */ + @Override + public byte byteValue() { + return (byte) value; + } + + /** + * {@inheritDoc} + * + * <p>The current implementation performs casting to a {@code short}. + */ + @Override + public short shortValue() { + return (short) value; + } + + /** + * {@inheritDoc} + * + * <p>The current implementation performs casting to a {@code int}. + */ + @Override + public int intValue() { + return (int) value; + } + + /** + * {@inheritDoc} + * + * <p>The current implementation performs casting to a {@code long}. + */ + @Override + public long longValue() { + return (long) value; + } + + /** + * {@inheritDoc} + * + * <p>The current implementation performs casting to a {@code float}. + */ + @Override + public float floatValue() { + return (float) value; + } + + /** {@inheritDoc} */ + @Override + public double doubleValue() { + return value; + } + + /* + * Methods from the Comparable interface. + */ + + /** + * {@inheritDoc} + * + * <p>The current implementation returns the same value as <center> {@code new + * Double(this.doubleValue()).compareTo(new Double(o.doubleValue()))} </center> + * + * @see Double#compareTo(Double) + */ + public int compareTo(final Decimal64 o) { + return Double.compare(this.value, o.value); + } + + /* + * Methods from the Object abstract class. + */ + + /** {@inheritDoc} */ + @Override + public boolean equals(final Object obj) { + if (obj instanceof Decimal64) { + final Decimal64 that = (Decimal64) obj; + return Double.doubleToLongBits(this.value) == Double.doubleToLongBits(that.value); + } + return false; + } + + /** + * {@inheritDoc} + * + * <p>The current implementation returns the same value as {@code new + * Double(this.doubleValue()).hashCode()} + * + * @see Double#hashCode() + */ + @Override + public int hashCode() { + long v = Double.doubleToLongBits(value); + return (int) (v ^ (v >>> 32)); + } + + /** + * {@inheritDoc} + * + * <p>The returned {@code String} is equal to {@code Double.toString(this.doubleValue())} + * + * @see Double#toString(double) + */ + @Override + public String toString() { + return Double.toString(value); + } + + /* + * Methods inspired by the Double class. + */ + + /** + * Returns {@code true} if {@code this} double precision number is infinite ({@link + * Double#POSITIVE_INFINITY} or {@link Double#NEGATIVE_INFINITY}). + * + * @return {@code true} if {@code this} number is infinite + */ + public boolean isInfinite() { + return Double.isInfinite(value); + } + + /** + * Returns {@code true} if {@code this} double precision number is Not-a-Number ({@code NaN}), + * false otherwise. + * + * @return {@code true} if {@code this} is {@code NaN} + */ + public boolean isNaN() { + return Double.isNaN(value); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public double getReal() { + return value; + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 add(final double a) { + return new Decimal64(value + a); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 subtract(final double a) { + return new Decimal64(value - a); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 multiply(final double a) { + return new Decimal64(value * a); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 divide(final double a) { + return new Decimal64(value / a); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 remainder(final double a) { + return new Decimal64(FastMath.IEEEremainder(value, a)); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 remainder(final Decimal64 a) { + return new Decimal64(FastMath.IEEEremainder(value, a.value)); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 abs() { + return new Decimal64(FastMath.abs(value)); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 ceil() { + return new Decimal64(FastMath.ceil(value)); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 floor() { + return new Decimal64(FastMath.floor(value)); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 rint() { + return new Decimal64(FastMath.rint(value)); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public long round() { + return FastMath.round(value); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 signum() { + return new Decimal64(FastMath.signum(value)); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 copySign(final Decimal64 sign) { + return new Decimal64(FastMath.copySign(value, sign.value)); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 copySign(final double sign) { + return new Decimal64(FastMath.copySign(value, sign)); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 scalb(final int n) { + return new Decimal64(FastMath.scalb(value, n)); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 hypot(final Decimal64 y) { + return new Decimal64(FastMath.hypot(value, y.value)); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 sqrt() { + return new Decimal64(FastMath.sqrt(value)); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 cbrt() { + return new Decimal64(FastMath.cbrt(value)); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 rootN(final int n) { + if (value < 0) { + return new Decimal64(-FastMath.pow(-value, 1.0 / n)); + } else { + return new Decimal64(FastMath.pow(value, 1.0 / n)); + } + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 pow(final double p) { + return new Decimal64(FastMath.pow(value, p)); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 pow(final int n) { + return new Decimal64(FastMath.pow(value, n)); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 pow(final Decimal64 e) { + return new Decimal64(FastMath.pow(value, e.value)); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 exp() { + return new Decimal64(FastMath.exp(value)); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 expm1() { + return new Decimal64(FastMath.expm1(value)); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 log() { + return new Decimal64(FastMath.log(value)); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 log1p() { + return new Decimal64(FastMath.log1p(value)); + } + + /** + * Base 10 logarithm. + * + * @return base 10 logarithm of the instance + * @since 3.2 + */ + public Decimal64 log10() { + return new Decimal64(FastMath.log10(value)); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 cos() { + return new Decimal64(FastMath.cos(value)); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 sin() { + return new Decimal64(FastMath.sin(value)); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 tan() { + return new Decimal64(FastMath.tan(value)); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 acos() { + return new Decimal64(FastMath.acos(value)); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 asin() { + return new Decimal64(FastMath.asin(value)); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 atan() { + return new Decimal64(FastMath.atan(value)); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 atan2(final Decimal64 x) { + return new Decimal64(FastMath.atan2(value, x.value)); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 cosh() { + return new Decimal64(FastMath.cosh(value)); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 sinh() { + return new Decimal64(FastMath.sinh(value)); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 tanh() { + return new Decimal64(FastMath.tanh(value)); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 acosh() { + return new Decimal64(FastMath.acosh(value)); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 asinh() { + return new Decimal64(FastMath.asinh(value)); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 atanh() { + return new Decimal64(FastMath.atanh(value)); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 linearCombination(final Decimal64[] a, final Decimal64[] b) + throws DimensionMismatchException { + if (a.length != b.length) { + throw new DimensionMismatchException(a.length, b.length); + } + final double[] aDouble = new double[a.length]; + final double[] bDouble = new double[b.length]; + for (int i = 0; i < a.length; ++i) { + aDouble[i] = a[i].value; + bDouble[i] = b[i].value; + } + return new Decimal64(MathArrays.linearCombination(aDouble, bDouble)); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 linearCombination(final double[] a, final Decimal64[] b) + throws DimensionMismatchException { + if (a.length != b.length) { + throw new DimensionMismatchException(a.length, b.length); + } + final double[] bDouble = new double[b.length]; + for (int i = 0; i < a.length; ++i) { + bDouble[i] = b[i].value; + } + return new Decimal64(MathArrays.linearCombination(a, bDouble)); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 linearCombination( + final Decimal64 a1, final Decimal64 b1, final Decimal64 a2, final Decimal64 b2) { + return new Decimal64( + MathArrays.linearCombination( + a1.value, b1.value, + a2.value, b2.value)); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 linearCombination( + final double a1, final Decimal64 b1, final double a2, final Decimal64 b2) { + return new Decimal64( + MathArrays.linearCombination( + a1, b1.value, + a2, b2.value)); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 linearCombination( + final Decimal64 a1, + final Decimal64 b1, + final Decimal64 a2, + final Decimal64 b2, + final Decimal64 a3, + final Decimal64 b3) { + return new Decimal64( + MathArrays.linearCombination( + a1.value, b1.value, + a2.value, b2.value, + a3.value, b3.value)); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 linearCombination( + final double a1, + final Decimal64 b1, + final double a2, + final Decimal64 b2, + final double a3, + final Decimal64 b3) { + return new Decimal64( + MathArrays.linearCombination( + a1, b1.value, + a2, b2.value, + a3, b3.value)); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 linearCombination( + final Decimal64 a1, + final Decimal64 b1, + final Decimal64 a2, + final Decimal64 b2, + final Decimal64 a3, + final Decimal64 b3, + final Decimal64 a4, + final Decimal64 b4) { + return new Decimal64( + MathArrays.linearCombination( + a1.value, b1.value, + a2.value, b2.value, + a3.value, b3.value, + a4.value, b4.value)); + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public Decimal64 linearCombination( + final double a1, + final Decimal64 b1, + final double a2, + final Decimal64 b2, + final double a3, + final Decimal64 b3, + final double a4, + final Decimal64 b4) { + return new Decimal64( + MathArrays.linearCombination( + a1, b1.value, + a2, b2.value, + a3, b3.value, + a4, b4.value)); + } +} diff --git a/src/main/java/org/apache/commons/math3/util/Decimal64Field.java b/src/main/java/org/apache/commons/math3/util/Decimal64Field.java new file mode 100644 index 0000000..2b07826 --- /dev/null +++ b/src/main/java/org/apache/commons/math3/util/Decimal64Field.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math3.util; + +import org.apache.commons.math3.Field; +import org.apache.commons.math3.FieldElement; + +/** + * The field of double precision floating-point numbers. + * + * @since 3.1 + * @see Decimal64 + */ +public class Decimal64Field implements Field<Decimal64> { + + /** The unique instance of this class. */ + private static final Decimal64Field INSTANCE = new Decimal64Field(); + + /** Default constructor. */ + private Decimal64Field() { + // Do nothing + } + + /** + * Returns the unique instance of this class. + * + * @return the unique instance of this class + */ + public static final Decimal64Field getInstance() { + return INSTANCE; + } + + /** {@inheritDoc} */ + public Decimal64 getZero() { + return Decimal64.ZERO; + } + + /** {@inheritDoc} */ + public Decimal64 getOne() { + return Decimal64.ONE; + } + + /** {@inheritDoc} */ + public Class<? extends FieldElement<Decimal64>> getRuntimeClass() { + return Decimal64.class; + } +} diff --git a/src/main/java/org/apache/commons/math3/util/DefaultTransformer.java b/src/main/java/org/apache/commons/math3/util/DefaultTransformer.java new file mode 100644 index 0000000..ba92d1b --- /dev/null +++ b/src/main/java/org/apache/commons/math3/util/DefaultTransformer.java @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.math3.util; + +import org.apache.commons.math3.exception.MathIllegalArgumentException; +import org.apache.commons.math3.exception.NullArgumentException; +import org.apache.commons.math3.exception.util.LocalizedFormats; + +import java.io.Serializable; + +/** + * A Default NumberTransformer for java.lang.Numbers and Numeric Strings. This provides some simple + * conversion capabilities to turn any java.lang.Number into a primitive double or to turn a String + * representation of a Number into a double. + */ +public class DefaultTransformer implements NumberTransformer, Serializable { + + /** Serializable version identifier */ + private static final long serialVersionUID = 4019938025047800455L; + + /** + * @param o the object that gets transformed. + * @return a double primitive representation of the Object o. + * @throws NullArgumentException if Object <code>o</code> is {@code null}. + * @throws MathIllegalArgumentException if Object <code>o</code> cannot successfully be + * transformed + * @see <a + * href="http://commons.apache.org/collections/api-release/org/apache/commons/collections/Transformer.html">Commons + * Collections Transformer</a> + */ + public double transform(Object o) throws NullArgumentException, MathIllegalArgumentException { + + if (o == null) { + throw new NullArgumentException(LocalizedFormats.OBJECT_TRANSFORMATION); + } + + if (o instanceof Number) { + return ((Number) o).doubleValue(); + } + + try { + return Double.parseDouble(o.toString()); + } catch (NumberFormatException e) { + throw new MathIllegalArgumentException( + LocalizedFormats.CANNOT_TRANSFORM_TO_DOUBLE, o.toString()); + } + } + + /** {@inheritDoc} */ + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + return other instanceof DefaultTransformer; + } + + /** {@inheritDoc} */ + @Override + public int hashCode() { + // some arbitrary number ... + return 401993047; + } +} diff --git a/src/main/java/org/apache/commons/math3/util/DoubleArray.java b/src/main/java/org/apache/commons/math3/util/DoubleArray.java new file mode 100644 index 0000000..f5762a9 --- /dev/null +++ b/src/main/java/org/apache/commons/math3/util/DoubleArray.java @@ -0,0 +1,96 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math3.util; + +/** + * Provides a standard interface for double arrays. Allows different array implementations to + * support various storage mechanisms such as automatic expansion, contraction, and array "rolling". + */ +public interface DoubleArray { + + /** + * Returns the number of elements currently in the array. Please note that this may be different + * from the length of the internal storage array. + * + * @return number of elements + */ + int getNumElements(); + + /** + * Returns the element at the specified index. Note that if an out of bounds index is supplied a + * ArrayIndexOutOfBoundsException will be thrown. + * + * @param index index to fetch a value from + * @return value stored at the specified index + * @throws ArrayIndexOutOfBoundsException if <code>index</code> is less than zero or is greater + * than <code>getNumElements() - 1</code>. + */ + double getElement(int index); + + /** + * Sets the element at the specified index. If the specified index is greater than <code> + * getNumElements() - 1</code>, the <code>numElements</code> property is increased to <code> + * index +1</code> and additional storage is allocated (if necessary) for the new element and + * all (uninitialized) elements between the new element and the previous end of the array). + * + * @param index index to store a value in + * @param value value to store at the specified index + * @throws ArrayIndexOutOfBoundsException if <code>index</code> is less than zero. + */ + void setElement(int index, double value); + + /** + * Adds an element to the end of this expandable array + * + * @param value to be added to end of array + */ + void addElement(double value); + + /** + * Adds elements to the end of this expandable array + * + * @param values to be added to end of array + */ + void addElements(double[] values); + + /** + * Adds an element to the end of the array and removes the first element in the array. Returns + * the discarded first element. The effect is similar to a push operation in a FIFO queue. + * + * <p>Example: If the array contains the elements 1, 2, 3, 4 (in that order) and + * addElementRolling(5) is invoked, the result is an array containing the entries 2, 3, 4, 5 and + * the value returned is 1. + * + * @param value the value to be added to the array + * @return the value which has been discarded or "pushed" out of the array by this rolling + * insert + */ + double addElementRolling(double value); + + /** + * Returns a double[] array containing the elements of this <code>DoubleArray</code>. If the + * underlying implementation is array-based, this method should always return a copy, rather + * than a reference to the underlying array so that changes made to the returned array have no + * effect on the <code>DoubleArray.</code> + * + * @return all elements added to the array + */ + double[] getElements(); + + /** Clear the double array */ + void clear(); +} diff --git a/src/main/java/org/apache/commons/math3/util/FastMath.java b/src/main/java/org/apache/commons/math3/util/FastMath.java new file mode 100644 index 0000000..f40961e --- /dev/null +++ b/src/main/java/org/apache/commons/math3/util/FastMath.java @@ -0,0 +1,4508 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math3.util; + +import org.apache.commons.math3.exception.MathArithmeticException; +import org.apache.commons.math3.exception.util.LocalizedFormats; + +import java.io.PrintStream; + +/** + * Faster, more accurate, portable alternative to {@link Math} and {@link StrictMath} for large + * scale computation. + * + * <p>FastMath is a drop-in replacement for both Math and StrictMath. This means that for any method + * in Math (say {@code Math.sin(x)} or {@code Math.cbrt(y)}), user can directly change the class and + * use the methods as is (using {@code FastMath.sin(x)} or {@code FastMath.cbrt(y)} in the previous + * example). + * + * <p>FastMath speed is achieved by relying heavily on optimizing compilers to native code present + * in many JVMs today and use of large tables. The larger tables are lazily initialised on first + * use, so that the setup time does not penalise methods that don't need them. + * + * <p>Note that FastMath is extensively used inside Apache Commons Math, so by calling some + * algorithms, the overhead when the the tables need to be intialised will occur regardless of the + * end-user calling FastMath methods directly or not. Performance figures for a specific JVM and + * hardware can be evaluated by running the FastMathTestPerformance tests in the test directory of + * the source distribution. + * + * <p>FastMath accuracy should be mostly independent of the JVM as it relies only on IEEE-754 basic + * operations and on embedded tables. Almost all operations are accurate to about 0.5 ulp throughout + * the domain range. This statement, of course is only a rough global observed behavior, it is + * <em>not</em> a guarantee for <em>every</em> double numbers input (see William Kahan's <a + * href="http://en.wikipedia.org/wiki/Rounding#The_table-maker.27s_dilemma">Table Maker's + * Dilemma</a>). + * + * <p>FastMath additionally implements the following methods not found in Math/StrictMath: + * + * <ul> + * <li>{@link #asinh(double)} + * <li>{@link #acosh(double)} + * <li>{@link #atanh(double)} + * </ul> + * + * The following methods are found in Math/StrictMath since 1.6 only, they are provided by FastMath + * even in 1.5 Java virtual machines + * + * <ul> + * <li>{@link #copySign(double, double)} + * <li>{@link #getExponent(double)} + * <li>{@link #nextAfter(double,double)} + * <li>{@link #nextUp(double)} + * <li>{@link #scalb(double, int)} + * <li>{@link #copySign(float, float)} + * <li>{@link #getExponent(float)} + * <li>{@link #nextAfter(float,double)} + * <li>{@link #nextUp(float)} + * <li>{@link #scalb(float, int)} + * </ul> + * + * @since 2.2 + */ +public class FastMath { + /** Archimede's constant PI, ratio of circle circumference to diameter. */ + public static final double PI = 105414357.0 / 33554432.0 + 1.984187159361080883e-9; + + /** Napier's constant e, base of the natural logarithm. */ + public static final double E = 2850325.0 / 1048576.0 + 8.254840070411028747e-8; + + /** Index of exp(0) in the array of integer exponentials. */ + static final int EXP_INT_TABLE_MAX_INDEX = 750; + + /** Length of the array of integer exponentials. */ + static final int EXP_INT_TABLE_LEN = EXP_INT_TABLE_MAX_INDEX * 2; + + /** Logarithm table length. */ + static final int LN_MANT_LEN = 1024; + + /** Exponential fractions table length. */ + static final int EXP_FRAC_TABLE_LEN = 1025; // 0, 1/1024, ... 1024/1024 + + /** StrictMath.log(Double.MAX_VALUE): {@value} */ + private static final double LOG_MAX_VALUE = StrictMath.log(Double.MAX_VALUE); + + /** + * Indicator for tables initialization. + * + * <p>This compile-time constant should be set to true only if one explicitly wants to compute + * the tables at class loading time instead of using the already computed ones provided as + * literal arrays below. + */ + private static final boolean RECOMPUTE_TABLES_AT_RUNTIME = false; + + /** log(2) (high bits). */ + private static final double LN_2_A = 0.693147063255310059; + + /** log(2) (low bits). */ + private static final double LN_2_B = 1.17304635250823482e-7; + + /** Coefficients for log, when input 0.99 < x < 1.01. */ + private static final double LN_QUICK_COEF[][] = { + {1.0, 5.669184079525E-24}, + {-0.25, -0.25}, + {0.3333333134651184, 1.986821492305628E-8}, + {-0.25, -6.663542893624021E-14}, + {0.19999998807907104, 1.1921056801463227E-8}, + {-0.1666666567325592, -7.800414592973399E-9}, + {0.1428571343421936, 5.650007086920087E-9}, + {-0.12502530217170715, -7.44321345601866E-11}, + {0.11113807559013367, 9.219544613762692E-9}, + }; + + /** Coefficients for log in the range of 1.0 < x < 1.0 + 2^-10. */ + private static final double LN_HI_PREC_COEF[][] = { + {1.0, -6.032174644509064E-23}, + {-0.25, -0.25}, + {0.3333333134651184, 1.9868161777724352E-8}, + {-0.2499999701976776, -2.957007209750105E-8}, + {0.19999954104423523, 1.5830993332061267E-10}, + {-0.16624879837036133, -2.6033824355191673E-8} + }; + + /** Sine, Cosine, Tangent tables are for 0, 1/8, 2/8, ... 13/8 = PI/2 approx. */ + private static final int SINE_TABLE_LEN = 14; + + /** Sine table (high bits). */ + private static final double SINE_TABLE_A[] = { + +0.0d, + +0.1246747374534607d, + +0.24740394949913025d, + +0.366272509098053d, + +0.4794255495071411d, + +0.5850973129272461d, + +0.6816387176513672d, + +0.7675435543060303d, + +0.8414709568023682d, + +0.902267575263977d, + +0.9489846229553223d, + +0.9808930158615112d, + +0.9974949359893799d, + +0.9985313415527344d, + }; + + /** Sine table (low bits). */ + private static final double SINE_TABLE_B[] = { + +0.0d, + -4.068233003401932E-9d, + +9.755392680573412E-9d, + +1.9987994582857286E-8d, + -1.0902938113007961E-8d, + -3.9986783938944604E-8d, + +4.23719669792332E-8d, + -5.207000323380292E-8d, + +2.800552834259E-8d, + +1.883511811213715E-8d, + -3.5997360512765566E-9d, + +4.116164446561962E-8d, + +5.0614674548127384E-8d, + -1.0129027912496858E-9d, + }; + + /** Cosine table (high bits). */ + private static final double COSINE_TABLE_A[] = { + +1.0d, + +0.9921976327896118d, + +0.9689123630523682d, + +0.9305076599121094d, + +0.8775825500488281d, + +0.8109631538391113d, + +0.7316888570785522d, + +0.6409968137741089d, + +0.5403022766113281d, + +0.4311765432357788d, + +0.3153223395347595d, + +0.19454771280288696d, + +0.07073719799518585d, + -0.05417713522911072d, + }; + + /** Cosine table (low bits). */ + private static final double COSINE_TABLE_B[] = { + +0.0d, + +3.4439717236742845E-8d, + +5.865827662008209E-8d, + -3.7999795083850525E-8d, + +1.184154459111628E-8d, + -3.43338934259355E-8d, + +1.1795268640216787E-8d, + +4.438921624363781E-8d, + +2.925681159240093E-8d, + -2.6437112632041807E-8d, + +2.2860509143963117E-8d, + -4.813899778443457E-9d, + +3.6725170580355583E-9d, + +2.0217439756338078E-10d, + }; + + /** Tangent table, used by atan() (high bits). */ + private static final double TANGENT_TABLE_A[] = { + +0.0d, + +0.1256551444530487d, + +0.25534194707870483d, + +0.3936265707015991d, + +0.5463024377822876d, + +0.7214844226837158d, + +0.9315965175628662d, + +1.1974215507507324d, + +1.5574076175689697d, + +2.092571258544922d, + +3.0095696449279785d, + +5.041914939880371d, + +14.101419448852539d, + -18.430862426757812d, + }; + + /** Tangent table, used by atan() (low bits). */ + private static final double TANGENT_TABLE_B[] = { + +0.0d, + -7.877917738262007E-9d, + -2.5857668567479893E-8d, + +5.2240336371356666E-9d, + +5.206150291559893E-8d, + +1.8307188599677033E-8d, + -5.7618793749770706E-8d, + +7.848361555046424E-8d, + +1.0708593250394448E-7d, + +1.7827257129423813E-8d, + +2.893485277253286E-8d, + +3.1660099222737955E-7d, + +4.983191803254889E-7d, + -3.356118100840571E-7d, + }; + + /** Bits of 1/(2*pi), need for reducePayneHanek(). */ + private static final long RECIP_2PI[] = + new long[] { + (0x28be60dbL << 32) | 0x9391054aL, + (0x7f09d5f4L << 32) | 0x7d4d3770L, + (0x36d8a566L << 32) | 0x4f10e410L, + (0x7f9458eaL << 32) | 0xf7aef158L, + (0x6dc91b8eL << 32) | 0x909374b8L, + (0x01924bbaL << 32) | 0x82746487L, + (0x3f877ac7L << 32) | 0x2c4a69cfL, + (0xba208d7dL << 32) | 0x4baed121L, + (0x3a671c09L << 32) | 0xad17df90L, + (0x4e64758eL << 32) | 0x60d4ce7dL, + (0x272117e2L << 32) | 0xef7e4a0eL, + (0xc7fe25ffL << 32) | 0xf7816603L, + (0xfbcbc462L << 32) | 0xd6829b47L, + (0xdb4d9fb3L << 32) | 0xc9f2c26dL, + (0xd3d18fd9L << 32) | 0xa797fa8bL, + (0x5d49eeb1L << 32) | 0xfaf97c5eL, + (0xcf41ce7dL << 32) | 0xe294a4baL, + 0x9afed7ecL << 32 + }; + + /** Bits of pi/4, need for reducePayneHanek(). */ + private static final long PI_O_4_BITS[] = + new long[] {(0xc90fdaa2L << 32) | 0x2168c234L, (0xc4c6628bL << 32) | 0x80dc1cd1L}; + + /** + * Eighths. This is used by sinQ, because its faster to do a table lookup than a multiply in + * this time-critical routine + */ + private static final double EIGHTHS[] = { + 0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1.0, 1.125, 1.25, 1.375, 1.5, 1.625 + }; + + /** Table of 2^((n+2)/3) */ + private static final double CBRTTWO[] = { + 0.6299605249474366, 0.7937005259840998, 1.0, 1.2599210498948732, 1.5874010519681994 + }; + + /* + * There are 52 bits in the mantissa of a double. + * For additional precision, the code splits double numbers into two parts, + * by clearing the low order 30 bits if possible, and then performs the arithmetic + * on each half separately. + */ + + /** + * 0x40000000 - used to split a double into two parts, both with the low order bits cleared. + * Equivalent to 2^30. + */ + private static final long HEX_40000000 = 0x40000000L; // 1073741824L + + /** Mask used to clear low order 30 bits */ + private static final long MASK_30BITS = -1L - (HEX_40000000 - 1); // 0xFFFFFFFFC0000000L; + + /** Mask used to clear the non-sign part of an int. */ + private static final int MASK_NON_SIGN_INT = 0x7fffffff; + + /** Mask used to clear the non-sign part of a long. */ + private static final long MASK_NON_SIGN_LONG = 0x7fffffffffffffffl; + + /** Mask used to extract exponent from double bits. */ + private static final long MASK_DOUBLE_EXPONENT = 0x7ff0000000000000L; + + /** Mask used to extract mantissa from double bits. */ + private static final long MASK_DOUBLE_MANTISSA = 0x000fffffffffffffL; + + /** Mask used to add implicit high order bit for normalized double. */ + private static final long IMPLICIT_HIGH_BIT = 0x0010000000000000L; + + /** 2^52 - double numbers this large must be integral (no fraction) or NaN or Infinite */ + private static final double TWO_POWER_52 = 4503599627370496.0; + + /** Constant: {@value}. */ + private static final double F_1_3 = 1d / 3d; + + /** Constant: {@value}. */ + private static final double F_1_5 = 1d / 5d; + + /** Constant: {@value}. */ + private static final double F_1_7 = 1d / 7d; + + /** Constant: {@value}. */ + private static final double F_1_9 = 1d / 9d; + + /** Constant: {@value}. */ + private static final double F_1_11 = 1d / 11d; + + /** Constant: {@value}. */ + private static final double F_1_13 = 1d / 13d; + + /** Constant: {@value}. */ + private static final double F_1_15 = 1d / 15d; + + /** Constant: {@value}. */ + private static final double F_1_17 = 1d / 17d; + + /** Constant: {@value}. */ + private static final double F_3_4 = 3d / 4d; + + /** Constant: {@value}. */ + private static final double F_15_16 = 15d / 16d; + + /** Constant: {@value}. */ + private static final double F_13_14 = 13d / 14d; + + /** Constant: {@value}. */ + private static final double F_11_12 = 11d / 12d; + + /** Constant: {@value}. */ + private static final double F_9_10 = 9d / 10d; + + /** Constant: {@value}. */ + private static final double F_7_8 = 7d / 8d; + + /** Constant: {@value}. */ + private static final double F_5_6 = 5d / 6d; + + /** Constant: {@value}. */ + private static final double F_1_2 = 1d / 2d; + + /** Constant: {@value}. */ + private static final double F_1_4 = 1d / 4d; + + /** Private Constructor */ + private FastMath() {} + + // Generic helper methods + + /** + * Get the high order bits from the mantissa. Equivalent to adding and subtracting HEX_40000 but + * also works for very large numbers + * + * @param d the value to split + * @return the high order part of the mantissa + */ + private static double doubleHighPart(double d) { + if (d > -Precision.SAFE_MIN && d < Precision.SAFE_MIN) { + return d; // These are un-normalised - don't try to convert + } + long xl = + Double.doubleToRawLongBits( + d); // can take raw bits because just gonna convert it back + xl &= MASK_30BITS; // Drop low order bits + return Double.longBitsToDouble(xl); + } + + /** + * Compute the square root of a number. + * + * <p><b>Note:</b> this implementation currently delegates to {@link Math#sqrt} + * + * @param a number on which evaluation is done + * @return square root of a + */ + public static double sqrt(final double a) { + return Math.sqrt(a); + } + + /** + * Compute the hyperbolic cosine of a number. + * + * @param x number on which evaluation is done + * @return hyperbolic cosine of x + */ + public static double cosh(double x) { + if (x != x) { + return x; + } + + // cosh[z] = (exp(z) + exp(-z))/2 + + // for numbers with magnitude 20 or so, + // exp(-z) can be ignored in comparison with exp(z) + + if (x > 20) { + if (x >= LOG_MAX_VALUE) { + // Avoid overflow (MATH-905). + final double t = exp(0.5 * x); + return (0.5 * t) * t; + } else { + return 0.5 * exp(x); + } + } else if (x < -20) { + if (x <= -LOG_MAX_VALUE) { + // Avoid overflow (MATH-905). + final double t = exp(-0.5 * x); + return (0.5 * t) * t; + } else { + return 0.5 * exp(-x); + } + } + + final double hiPrec[] = new double[2]; + if (x < 0.0) { + x = -x; + } + exp(x, 0.0, hiPrec); + + double ya = hiPrec[0] + hiPrec[1]; + double yb = -(ya - hiPrec[0] - hiPrec[1]); + + double temp = ya * HEX_40000000; + double yaa = ya + temp - temp; + double yab = ya - yaa; + + // recip = 1/y + double recip = 1.0 / ya; + temp = recip * HEX_40000000; + double recipa = recip + temp - temp; + double recipb = recip - recipa; + + // Correct for rounding in division + recipb += (1.0 - yaa * recipa - yaa * recipb - yab * recipa - yab * recipb) * recip; + // Account for yb + recipb += -yb * recip * recip; + + // y = y + 1/y + temp = ya + recipa; + yb += -(temp - ya - recipa); + ya = temp; + temp = ya + recipb; + yb += -(temp - ya - recipb); + ya = temp; + + double result = ya + yb; + result *= 0.5; + return result; + } + + /** + * Compute the hyperbolic sine of a number. + * + * @param x number on which evaluation is done + * @return hyperbolic sine of x + */ + public static double sinh(double x) { + boolean negate = false; + if (x != x) { + return x; + } + + // sinh[z] = (exp(z) - exp(-z) / 2 + + // for values of z larger than about 20, + // exp(-z) can be ignored in comparison with exp(z) + + if (x > 20) { + if (x >= LOG_MAX_VALUE) { + // Avoid overflow (MATH-905). + final double t = exp(0.5 * x); + return (0.5 * t) * t; + } else { + return 0.5 * exp(x); + } + } else if (x < -20) { + if (x <= -LOG_MAX_VALUE) { + // Avoid overflow (MATH-905). + final double t = exp(-0.5 * x); + return (-0.5 * t) * t; + } else { + return -0.5 * exp(-x); + } + } + + if (x == 0) { + return x; + } + + if (x < 0.0) { + x = -x; + negate = true; + } + + double result; + + if (x > 0.25) { + double hiPrec[] = new double[2]; + exp(x, 0.0, hiPrec); + + double ya = hiPrec[0] + hiPrec[1]; + double yb = -(ya - hiPrec[0] - hiPrec[1]); + + double temp = ya * HEX_40000000; + double yaa = ya + temp - temp; + double yab = ya - yaa; + + // recip = 1/y + double recip = 1.0 / ya; + temp = recip * HEX_40000000; + double recipa = recip + temp - temp; + double recipb = recip - recipa; + + // Correct for rounding in division + recipb += (1.0 - yaa * recipa - yaa * recipb - yab * recipa - yab * recipb) * recip; + // Account for yb + recipb += -yb * recip * recip; + + recipa = -recipa; + recipb = -recipb; + + // y = y + 1/y + temp = ya + recipa; + yb += -(temp - ya - recipa); + ya = temp; + temp = ya + recipb; + yb += -(temp - ya - recipb); + ya = temp; + + result = ya + yb; + result *= 0.5; + } else { + double hiPrec[] = new double[2]; + expm1(x, hiPrec); + + double ya = hiPrec[0] + hiPrec[1]; + double yb = -(ya - hiPrec[0] - hiPrec[1]); + + /* Compute expm1(-x) = -expm1(x) / (expm1(x) + 1) */ + double denom = 1.0 + ya; + double denomr = 1.0 / denom; + double denomb = -(denom - 1.0 - ya) + yb; + double ratio = ya * denomr; + double temp = ratio * HEX_40000000; + double ra = ratio + temp - temp; + double rb = ratio - ra; + + temp = denom * HEX_40000000; + double za = denom + temp - temp; + double zb = denom - za; + + rb += (ya - za * ra - za * rb - zb * ra - zb * rb) * denomr; + + // Adjust for yb + rb += yb * denomr; // numerator + rb += -ya * denomb * denomr * denomr; // denominator + + // y = y - 1/y + temp = ya + ra; + yb += -(temp - ya - ra); + ya = temp; + temp = ya + rb; + yb += -(temp - ya - rb); + ya = temp; + + result = ya + yb; + result *= 0.5; + } + + if (negate) { + result = -result; + } + + return result; + } + + /** + * Compute the hyperbolic tangent of a number. + * + * @param x number on which evaluation is done + * @return hyperbolic tangent of x + */ + public static double tanh(double x) { + boolean negate = false; + + if (x != x) { + return x; + } + + // tanh[z] = sinh[z] / cosh[z] + // = (exp(z) - exp(-z)) / (exp(z) + exp(-z)) + // = (exp(2x) - 1) / (exp(2x) + 1) + + // for magnitude > 20, sinh[z] == cosh[z] in double precision + + if (x > 20.0) { + return 1.0; + } + + if (x < -20) { + return -1.0; + } + + if (x == 0) { + return x; + } + + if (x < 0.0) { + x = -x; + negate = true; + } + + double result; + if (x >= 0.5) { + double hiPrec[] = new double[2]; + // tanh(x) = (exp(2x) - 1) / (exp(2x) + 1) + exp(x * 2.0, 0.0, hiPrec); + + double ya = hiPrec[0] + hiPrec[1]; + double yb = -(ya - hiPrec[0] - hiPrec[1]); + + /* Numerator */ + double na = -1.0 + ya; + double nb = -(na + 1.0 - ya); + double temp = na + yb; + nb += -(temp - na - yb); + na = temp; + + /* Denominator */ + double da = 1.0 + ya; + double db = -(da - 1.0 - ya); + temp = da + yb; + db += -(temp - da - yb); + da = temp; + + temp = da * HEX_40000000; + double daa = da + temp - temp; + double dab = da - daa; + + // ratio = na/da + double ratio = na / da; + temp = ratio * HEX_40000000; + double ratioa = ratio + temp - temp; + double ratiob = ratio - ratioa; + + // Correct for rounding in division + ratiob += (na - daa * ratioa - daa * ratiob - dab * ratioa - dab * ratiob) / da; + + // Account for nb + ratiob += nb / da; + // Account for db + ratiob += -db * na / da / da; + + result = ratioa + ratiob; + } else { + double hiPrec[] = new double[2]; + // tanh(x) = expm1(2x) / (expm1(2x) + 2) + expm1(x * 2.0, hiPrec); + + double ya = hiPrec[0] + hiPrec[1]; + double yb = -(ya - hiPrec[0] - hiPrec[1]); + + /* Numerator */ + double na = ya; + double nb = yb; + + /* Denominator */ + double da = 2.0 + ya; + double db = -(da - 2.0 - ya); + double temp = da + yb; + db += -(temp - da - yb); + da = temp; + + temp = da * HEX_40000000; + double daa = da + temp - temp; + double dab = da - daa; + + // ratio = na/da + double ratio = na / da; + temp = ratio * HEX_40000000; + double ratioa = ratio + temp - temp; + double ratiob = ratio - ratioa; + + // Correct for rounding in division + ratiob += (na - daa * ratioa - daa * ratiob - dab * ratioa - dab * ratiob) / da; + + // Account for nb + ratiob += nb / da; + // Account for db + ratiob += -db * na / da / da; + + result = ratioa + ratiob; + } + + if (negate) { + result = -result; + } + + return result; + } + + /** + * Compute the inverse hyperbolic cosine of a number. + * + * @param a number on which evaluation is done + * @return inverse hyperbolic cosine of a + */ + public static double acosh(final double a) { + return FastMath.log(a + FastMath.sqrt(a * a - 1)); + } + + /** + * Compute the inverse hyperbolic sine of a number. + * + * @param a number on which evaluation is done + * @return inverse hyperbolic sine of a + */ + public static double asinh(double a) { + boolean negative = false; + if (a < 0) { + negative = true; + a = -a; + } + + double absAsinh; + if (a > 0.167) { + absAsinh = FastMath.log(FastMath.sqrt(a * a + 1) + a); + } else { + final double a2 = a * a; + if (a > 0.097) { + absAsinh = + a + * (1 + - a2 + * (F_1_3 + - a2 + * (F_1_5 + - a2 + * (F_1_7 + - a2 + * (F_1_9 + - a2 + * (F_1_11 + - a2 + * (F_1_13 + - a2 + * (F_1_15 + - a2 + * F_1_17 + * F_15_16) + * F_13_14) + * F_11_12) + * F_9_10) + * F_7_8) + * F_5_6) + * F_3_4) + * F_1_2); + } else if (a > 0.036) { + absAsinh = + a + * (1 + - a2 + * (F_1_3 + - a2 + * (F_1_5 + - a2 + * (F_1_7 + - a2 + * (F_1_9 + - a2 + * (F_1_11 + - a2 + * F_1_13 + * F_11_12) + * F_9_10) + * F_7_8) + * F_5_6) + * F_3_4) + * F_1_2); + } else if (a > 0.0036) { + absAsinh = + a + * (1 + - a2 + * (F_1_3 + - a2 + * (F_1_5 + - a2 + * (F_1_7 + - a2 * F_1_9 + * F_7_8) + * F_5_6) + * F_3_4) + * F_1_2); + } else { + absAsinh = a * (1 - a2 * (F_1_3 - a2 * F_1_5 * F_3_4) * F_1_2); + } + } + + return negative ? -absAsinh : absAsinh; + } + + /** + * Compute the inverse hyperbolic tangent of a number. + * + * @param a number on which evaluation is done + * @return inverse hyperbolic tangent of a + */ + public static double atanh(double a) { + boolean negative = false; + if (a < 0) { + negative = true; + a = -a; + } + + double absAtanh; + if (a > 0.15) { + absAtanh = 0.5 * FastMath.log((1 + a) / (1 - a)); + } else { + final double a2 = a * a; + if (a > 0.087) { + absAtanh = + a + * (1 + + a2 + * (F_1_3 + + a2 + * (F_1_5 + + a2 + * (F_1_7 + + a2 + * (F_1_9 + + a2 + * (F_1_11 + + a2 + * (F_1_13 + + a2 + * (F_1_15 + + a2 + * F_1_17)))))))); + } else if (a > 0.031) { + absAtanh = + a + * (1 + + a2 + * (F_1_3 + + a2 + * (F_1_5 + + a2 + * (F_1_7 + + a2 + * (F_1_9 + + a2 + * (F_1_11 + + a2 + * F_1_13)))))); + } else if (a > 0.003) { + absAtanh = a * (1 + a2 * (F_1_3 + a2 * (F_1_5 + a2 * (F_1_7 + a2 * F_1_9)))); + } else { + absAtanh = a * (1 + a2 * (F_1_3 + a2 * F_1_5)); + } + } + + return negative ? -absAtanh : absAtanh; + } + + /** + * Compute the signum of a number. The signum is -1 for negative numbers, +1 for positive + * numbers and 0 otherwise + * + * @param a number on which evaluation is done + * @return -1.0, -0.0, +0.0, +1.0 or NaN depending on sign of a + */ + public static double signum(final double a) { + return (a < 0.0) ? -1.0 : ((a > 0.0) ? 1.0 : a); // return +0.0/-0.0/NaN depending on a + } + + /** + * Compute the signum of a number. The signum is -1 for negative numbers, +1 for positive + * numbers and 0 otherwise + * + * @param a number on which evaluation is done + * @return -1.0, -0.0, +0.0, +1.0 or NaN depending on sign of a + */ + public static float signum(final float a) { + return (a < 0.0f) ? -1.0f : ((a > 0.0f) ? 1.0f : a); // return +0.0/-0.0/NaN depending on a + } + + /** + * Compute next number towards positive infinity. + * + * @param a number to which neighbor should be computed + * @return neighbor of a towards positive infinity + */ + public static double nextUp(final double a) { + return nextAfter(a, Double.POSITIVE_INFINITY); + } + + /** + * Compute next number towards positive infinity. + * + * @param a number to which neighbor should be computed + * @return neighbor of a towards positive infinity + */ + public static float nextUp(final float a) { + return nextAfter(a, Float.POSITIVE_INFINITY); + } + + /** + * Compute next number towards negative infinity. + * + * @param a number to which neighbor should be computed + * @return neighbor of a towards negative infinity + * @since 3.4 + */ + public static double nextDown(final double a) { + return nextAfter(a, Double.NEGATIVE_INFINITY); + } + + /** + * Compute next number towards negative infinity. + * + * @param a number to which neighbor should be computed + * @return neighbor of a towards negative infinity + * @since 3.4 + */ + public static float nextDown(final float a) { + return nextAfter(a, Float.NEGATIVE_INFINITY); + } + + /** + * Returns a pseudo-random number between 0.0 and 1.0. + * + * <p><b>Note:</b> this implementation currently delegates to {@link Math#random} + * + * @return a random number between 0.0 and 1.0 + */ + public static double random() { + return Math.random(); + } + + /** + * Exponential function. + * + * <p>Computes exp(x), function result is nearly rounded. It will be correctly rounded to the + * theoretical value for 99.9% of input values, otherwise it will have a 1 ULP error. + * + * <p>Method: Lookup intVal = exp(int(x)) Lookup fracVal = exp(int(x-int(x) / 1024.0) * 1024.0 + * ); Compute z as the exponential of the remaining bits by a polynomial minus one exp(x) = + * intVal * fracVal * (1 + z) + * + * <p>Accuracy: Calculation is done with 63 bits of precision, so result should be correctly + * rounded for 99.9% of input values, with less than 1 ULP error otherwise. + * + * @param x a double + * @return double e<sup>x</sup> + */ + public static double exp(double x) { + return exp(x, 0.0, null); + } + + /** + * Internal helper method for exponential function. + * + * @param x original argument of the exponential function + * @param extra extra bits of precision on input (To Be Confirmed) + * @param hiPrec extra bits of precision on output (To Be Confirmed) + * @return exp(x) + */ + private static double exp(double x, double extra, double[] hiPrec) { + double intPartA; + double intPartB; + int intVal = (int) x; + + /* Lookup exp(floor(x)). + * intPartA will have the upper 22 bits, intPartB will have the lower + * 52 bits. + */ + if (x < 0.0) { + + // We don't check against intVal here as conversion of large negative double values + // may be affected by a JIT bug. Subsequent comparisons can safely use intVal + if (x < -746d) { + if (hiPrec != null) { + hiPrec[0] = 0.0; + hiPrec[1] = 0.0; + } + return 0.0; + } + + if (intVal < -709) { + /* This will produce a subnormal output */ + final double result = exp(x + 40.19140625, extra, hiPrec) / 285040095144011776.0; + if (hiPrec != null) { + hiPrec[0] /= 285040095144011776.0; + hiPrec[1] /= 285040095144011776.0; + } + return result; + } + + if (intVal == -709) { + /* exp(1.494140625) is nearly a machine number... */ + final double result = exp(x + 1.494140625, extra, hiPrec) / 4.455505956692756620; + if (hiPrec != null) { + hiPrec[0] /= 4.455505956692756620; + hiPrec[1] /= 4.455505956692756620; + } + return result; + } + + intVal--; + + } else { + if (intVal > 709) { + if (hiPrec != null) { + hiPrec[0] = Double.POSITIVE_INFINITY; + hiPrec[1] = 0.0; + } + return Double.POSITIVE_INFINITY; + } + } + + intPartA = ExpIntTable.EXP_INT_TABLE_A[EXP_INT_TABLE_MAX_INDEX + intVal]; + intPartB = ExpIntTable.EXP_INT_TABLE_B[EXP_INT_TABLE_MAX_INDEX + intVal]; + + /* Get the fractional part of x, find the greatest multiple of 2^-10 less than + * x and look up the exp function of it. + * fracPartA will have the upper 22 bits, fracPartB the lower 52 bits. + */ + final int intFrac = (int) ((x - intVal) * 1024.0); + final double fracPartA = ExpFracTable.EXP_FRAC_TABLE_A[intFrac]; + final double fracPartB = ExpFracTable.EXP_FRAC_TABLE_B[intFrac]; + + /* epsilon is the difference in x from the nearest multiple of 2^-10. It + * has a value in the range 0 <= epsilon < 2^-10. + * Do the subtraction from x as the last step to avoid possible loss of precision. + */ + final double epsilon = x - (intVal + intFrac / 1024.0); + + /* Compute z = exp(epsilon) - 1.0 via a minimax polynomial. z has + full double precision (52 bits). Since z < 2^-10, we will have + 62 bits of precision when combined with the constant 1. This will be + used in the last addition below to get proper rounding. */ + + /* Remez generated polynomial. Converges on the interval [0, 2^-10], error + is less than 0.5 ULP */ + double z = 0.04168701738764507; + z = z * epsilon + 0.1666666505023083; + z = z * epsilon + 0.5000000000042687; + z = z * epsilon + 1.0; + z = z * epsilon + -3.940510424527919E-20; + + /* Compute (intPartA+intPartB) * (fracPartA+fracPartB) by binomial + expansion. + tempA is exact since intPartA and intPartB only have 22 bits each. + tempB will have 52 bits of precision. + */ + double tempA = intPartA * fracPartA; + double tempB = intPartA * fracPartB + intPartB * fracPartA + intPartB * fracPartB; + + /* Compute the result. (1+z)(tempA+tempB). Order of operations is + important. For accuracy add by increasing size. tempA is exact and + much larger than the others. If there are extra bits specified from the + pow() function, use them. */ + final double tempC = tempB + tempA; + + // If tempC is positive infinite, the evaluation below could result in NaN, + // because z could be negative at the same time. + if (tempC == Double.POSITIVE_INFINITY) { + return Double.POSITIVE_INFINITY; + } + + final double result; + if (extra != 0.0) { + result = tempC * extra * z + tempC * extra + tempC * z + tempB + tempA; + } else { + result = tempC * z + tempB + tempA; + } + + if (hiPrec != null) { + // If requesting high precision + hiPrec[0] = tempA; + hiPrec[1] = tempC * extra * z + tempC * extra + tempC * z + tempB; + } + + return result; + } + + /** + * Compute exp(x) - 1 + * + * @param x number to compute shifted exponential + * @return exp(x) - 1 + */ + public static double expm1(double x) { + return expm1(x, null); + } + + /** + * Internal helper method for expm1 + * + * @param x number to compute shifted exponential + * @param hiPrecOut receive high precision result for -1.0 < x < 1.0 + * @return exp(x) - 1 + */ + private static double expm1(double x, double hiPrecOut[]) { + if (x != x || x == 0.0) { // NaN or zero + return x; + } + + if (x <= -1.0 || x >= 1.0) { + // If not between +/- 1.0 + // return exp(x) - 1.0; + double hiPrec[] = new double[2]; + exp(x, 0.0, hiPrec); + if (x > 0.0) { + return -1.0 + hiPrec[0] + hiPrec[1]; + } else { + final double ra = -1.0 + hiPrec[0]; + double rb = -(ra + 1.0 - hiPrec[0]); + rb += hiPrec[1]; + return ra + rb; + } + } + + double baseA; + double baseB; + double epsilon; + boolean negative = false; + + if (x < 0.0) { + x = -x; + negative = true; + } + + { + int intFrac = (int) (x * 1024.0); + double tempA = ExpFracTable.EXP_FRAC_TABLE_A[intFrac] - 1.0; + double tempB = ExpFracTable.EXP_FRAC_TABLE_B[intFrac]; + + double temp = tempA + tempB; + tempB = -(temp - tempA - tempB); + tempA = temp; + + temp = tempA * HEX_40000000; + baseA = tempA + temp - temp; + baseB = tempB + (tempA - baseA); + + epsilon = x - intFrac / 1024.0; + } + + /* Compute expm1(epsilon) */ + double zb = 0.008336750013465571; + zb = zb * epsilon + 0.041666663879186654; + zb = zb * epsilon + 0.16666666666745392; + zb = zb * epsilon + 0.49999999999999994; + zb *= epsilon; + zb *= epsilon; + + double za = epsilon; + double temp = za + zb; + zb = -(temp - za - zb); + za = temp; + + temp = za * HEX_40000000; + temp = za + temp - temp; + zb += za - temp; + za = temp; + + /* Combine the parts. expm1(a+b) = expm1(a) + expm1(b) + expm1(a)*expm1(b) */ + double ya = za * baseA; + // double yb = za*baseB + zb*baseA + zb*baseB; + temp = ya + za * baseB; + double yb = -(temp - ya - za * baseB); + ya = temp; + + temp = ya + zb * baseA; + yb += -(temp - ya - zb * baseA); + ya = temp; + + temp = ya + zb * baseB; + yb += -(temp - ya - zb * baseB); + ya = temp; + + // ya = ya + za + baseA; + // yb = yb + zb + baseB; + temp = ya + baseA; + yb += -(temp - baseA - ya); + ya = temp; + + temp = ya + za; + // yb += (ya > za) ? -(temp - ya - za) : -(temp - za - ya); + yb += -(temp - ya - za); + ya = temp; + + temp = ya + baseB; + // yb += (ya > baseB) ? -(temp - ya - baseB) : -(temp - baseB - ya); + yb += -(temp - ya - baseB); + ya = temp; + + temp = ya + zb; + // yb += (ya > zb) ? -(temp - ya - zb) : -(temp - zb - ya); + yb += -(temp - ya - zb); + ya = temp; + + if (negative) { + /* Compute expm1(-x) = -expm1(x) / (expm1(x) + 1) */ + double denom = 1.0 + ya; + double denomr = 1.0 / denom; + double denomb = -(denom - 1.0 - ya) + yb; + double ratio = ya * denomr; + temp = ratio * HEX_40000000; + final double ra = ratio + temp - temp; + double rb = ratio - ra; + + temp = denom * HEX_40000000; + za = denom + temp - temp; + zb = denom - za; + + rb += (ya - za * ra - za * rb - zb * ra - zb * rb) * denomr; + + // f(x) = x/1+x + // Compute f'(x) + // Product rule: d(uv) = du*v + u*dv + // Chain rule: d(f(g(x)) = f'(g(x))*f(g'(x)) + // d(1/x) = -1/(x*x) + // d(1/1+x) = -1/( (1+x)^2) * 1 = -1/((1+x)*(1+x)) + // d(x/1+x) = -x/((1+x)(1+x)) + 1/1+x = 1 / ((1+x)(1+x)) + + // Adjust for yb + rb += yb * denomr; // numerator + rb += -ya * denomb * denomr * denomr; // denominator + + // negate + ya = -ra; + yb = -rb; + } + + if (hiPrecOut != null) { + hiPrecOut[0] = ya; + hiPrecOut[1] = yb; + } + + return ya + yb; + } + + /** + * Natural logarithm. + * + * @param x a double + * @return log(x) + */ + public static double log(final double x) { + return log(x, null); + } + + /** + * Internal helper method for natural logarithm function. + * + * @param x original argument of the natural logarithm function + * @param hiPrec extra bits of precision on output (To Be Confirmed) + * @return log(x) + */ + private static double log(final double x, final double[] hiPrec) { + if (x == 0) { // Handle special case of +0/-0 + return Double.NEGATIVE_INFINITY; + } + long bits = Double.doubleToRawLongBits(x); + + /* Handle special cases of negative input, and NaN */ + if (((bits & 0x8000000000000000L) != 0 || x != x) && x != 0.0) { + if (hiPrec != null) { + hiPrec[0] = Double.NaN; + } + + return Double.NaN; + } + + /* Handle special cases of Positive infinity. */ + if (x == Double.POSITIVE_INFINITY) { + if (hiPrec != null) { + hiPrec[0] = Double.POSITIVE_INFINITY; + } + + return Double.POSITIVE_INFINITY; + } + + /* Extract the exponent */ + int exp = (int) (bits >> 52) - 1023; + + if ((bits & 0x7ff0000000000000L) == 0) { + // Subnormal! + if (x == 0) { + // Zero + if (hiPrec != null) { + hiPrec[0] = Double.NEGATIVE_INFINITY; + } + + return Double.NEGATIVE_INFINITY; + } + + /* Normalize the subnormal number. */ + bits <<= 1; + while ((bits & 0x0010000000000000L) == 0) { + --exp; + bits <<= 1; + } + } + + if ((exp == -1 || exp == 0) && x < 1.01 && x > 0.99 && hiPrec == null) { + /* The normal method doesn't work well in the range [0.99, 1.01], so call do a straight + polynomial expansion in higer precision. */ + + /* Compute x - 1.0 and split it */ + double xa = x - 1.0; + double xb = xa - x + 1.0; + double tmp = xa * HEX_40000000; + double aa = xa + tmp - tmp; + double ab = xa - aa; + xa = aa; + xb = ab; + + final double[] lnCoef_last = LN_QUICK_COEF[LN_QUICK_COEF.length - 1]; + double ya = lnCoef_last[0]; + double yb = lnCoef_last[1]; + + for (int i = LN_QUICK_COEF.length - 2; i >= 0; i--) { + /* Multiply a = y * x */ + aa = ya * xa; + ab = ya * xb + yb * xa + yb * xb; + /* split, so now y = a */ + tmp = aa * HEX_40000000; + ya = aa + tmp - tmp; + yb = aa - ya + ab; + + /* Add a = y + lnQuickCoef */ + final double[] lnCoef_i = LN_QUICK_COEF[i]; + aa = ya + lnCoef_i[0]; + ab = yb + lnCoef_i[1]; + /* Split y = a */ + tmp = aa * HEX_40000000; + ya = aa + tmp - tmp; + yb = aa - ya + ab; + } + + /* Multiply a = y * x */ + aa = ya * xa; + ab = ya * xb + yb * xa + yb * xb; + /* split, so now y = a */ + tmp = aa * HEX_40000000; + ya = aa + tmp - tmp; + yb = aa - ya + ab; + + return ya + yb; + } + + // lnm is a log of a number in the range of 1.0 - 2.0, so 0 <= lnm < ln(2) + final double[] lnm = lnMant.LN_MANT[(int) ((bits & 0x000ffc0000000000L) >> 42)]; + + /* + double epsilon = x / Double.longBitsToDouble(bits & 0xfffffc0000000000L); + + epsilon -= 1.0; + */ + + // y is the most significant 10 bits of the mantissa + // double y = Double.longBitsToDouble(bits & 0xfffffc0000000000L); + // double epsilon = (x - y) / y; + final double epsilon = + (bits & 0x3ffffffffffL) / (TWO_POWER_52 + (bits & 0x000ffc0000000000L)); + + double lnza = 0.0; + double lnzb = 0.0; + + if (hiPrec != null) { + /* split epsilon -> x */ + double tmp = epsilon * HEX_40000000; + double aa = epsilon + tmp - tmp; + double ab = epsilon - aa; + double xa = aa; + double xb = ab; + + /* Need a more accurate epsilon, so adjust the division. */ + final double numer = bits & 0x3ffffffffffL; + final double denom = TWO_POWER_52 + (bits & 0x000ffc0000000000L); + aa = numer - xa * denom - xb * denom; + xb += aa / denom; + + /* Remez polynomial evaluation */ + final double[] lnCoef_last = LN_HI_PREC_COEF[LN_HI_PREC_COEF.length - 1]; + double ya = lnCoef_last[0]; + double yb = lnCoef_last[1]; + + for (int i = LN_HI_PREC_COEF.length - 2; i >= 0; i--) { + /* Multiply a = y * x */ + aa = ya * xa; + ab = ya * xb + yb * xa + yb * xb; + /* split, so now y = a */ + tmp = aa * HEX_40000000; + ya = aa + tmp - tmp; + yb = aa - ya + ab; + + /* Add a = y + lnHiPrecCoef */ + final double[] lnCoef_i = LN_HI_PREC_COEF[i]; + aa = ya + lnCoef_i[0]; + ab = yb + lnCoef_i[1]; + /* Split y = a */ + tmp = aa * HEX_40000000; + ya = aa + tmp - tmp; + yb = aa - ya + ab; + } + + /* Multiply a = y * x */ + aa = ya * xa; + ab = ya * xb + yb * xa + yb * xb; + + /* split, so now lnz = a */ + /* + tmp = aa * 1073741824.0; + lnza = aa + tmp - tmp; + lnzb = aa - lnza + ab; + */ + lnza = aa + ab; + lnzb = -(lnza - aa - ab); + } else { + /* High precision not required. Eval Remez polynomial + using standard double precision */ + lnza = -0.16624882440418567; + lnza = lnza * epsilon + 0.19999954120254515; + lnza = lnza * epsilon + -0.2499999997677497; + lnza = lnza * epsilon + 0.3333333333332802; + lnza = lnza * epsilon + -0.5; + lnza = lnza * epsilon + 1.0; + lnza *= epsilon; + } + + /* Relative sizes: + * lnzb [0, 2.33E-10] + * lnm[1] [0, 1.17E-7] + * ln2B*exp [0, 1.12E-4] + * lnza [0, 9.7E-4] + * lnm[0] [0, 0.692] + * ln2A*exp [0, 709] + */ + + /* Compute the following sum: + * lnzb + lnm[1] + ln2B*exp + lnza + lnm[0] + ln2A*exp; + */ + + // return lnzb + lnm[1] + ln2B*exp + lnza + lnm[0] + ln2A*exp; + double a = LN_2_A * exp; + double b = 0.0; + double c = a + lnm[0]; + double d = -(c - a - lnm[0]); + a = c; + b += d; + + c = a + lnza; + d = -(c - a - lnza); + a = c; + b += d; + + c = a + LN_2_B * exp; + d = -(c - a - LN_2_B * exp); + a = c; + b += d; + + c = a + lnm[1]; + d = -(c - a - lnm[1]); + a = c; + b += d; + + c = a + lnzb; + d = -(c - a - lnzb); + a = c; + b += d; + + if (hiPrec != null) { + hiPrec[0] = a; + hiPrec[1] = b; + } + + return a + b; + } + + /** + * Computes log(1 + x). + * + * @param x Number. + * @return {@code log(1 + x)}. + */ + public static double log1p(final double x) { + if (x == -1) { + return Double.NEGATIVE_INFINITY; + } + + if (x == Double.POSITIVE_INFINITY) { + return Double.POSITIVE_INFINITY; + } + + if (x > 1e-6 || x < -1e-6) { + final double xpa = 1 + x; + final double xpb = -(xpa - 1 - x); + + final double[] hiPrec = new double[2]; + final double lores = log(xpa, hiPrec); + if (Double.isInfinite(lores)) { // Don't allow this to be converted to NaN + return lores; + } + + // Do a taylor series expansion around xpa: + // f(x+y) = f(x) + f'(x) y + f''(x)/2 y^2 + final double fx1 = xpb / xpa; + final double epsilon = 0.5 * fx1 + 1; + return epsilon * fx1 + hiPrec[1] + hiPrec[0]; + } else { + // Value is small |x| < 1e6, do a Taylor series centered on 1. + final double y = (x * F_1_3 - F_1_2) * x + 1; + return y * x; + } + } + + /** + * Compute the base 10 logarithm. + * + * @param x a number + * @return log10(x) + */ + public static double log10(final double x) { + final double hiPrec[] = new double[2]; + + final double lores = log(x, hiPrec); + if (Double.isInfinite(lores)) { // don't allow this to be converted to NaN + return lores; + } + + final double tmp = hiPrec[0] * HEX_40000000; + final double lna = hiPrec[0] + tmp - tmp; + final double lnb = hiPrec[0] - lna + hiPrec[1]; + + final double rln10a = 0.4342944622039795; + final double rln10b = 1.9699272335463627E-8; + + return rln10b * lnb + rln10b * lna + rln10a * lnb + rln10a * lna; + } + + /** + * Computes the <a href="http://mathworld.wolfram.com/Logarithm.html">logarithm</a> in a given + * base. + * + * <p>Returns {@code NaN} if either argument is negative. If {@code base} is 0 and {@code x} is + * positive, 0 is returned. If {@code base} is positive and {@code x} is 0, {@code + * Double.NEGATIVE_INFINITY} is returned. If both arguments are 0, the result is {@code NaN}. + * + * @param base Base of the logarithm, must be greater than 0. + * @param x Argument, must be greater than 0. + * @return the value of the logarithm, i.e. the number {@code y} such that <code> + * base<sup>y</sup> = x</code>. + * @since 1.2 (previously in {@code MathUtils}, moved as of version 3.0) + */ + public static double log(double base, double x) { + return log(x) / log(base); + } + + /** + * Power function. Compute x^y. + * + * @param x a double + * @param y a double + * @return double + */ + public static double pow(final double x, final double y) { + + if (y == 0) { + // y = -0 or y = +0 + return 1.0; + } else { + + final long yBits = Double.doubleToRawLongBits(y); + final int yRawExp = (int) ((yBits & MASK_DOUBLE_EXPONENT) >> 52); + final long yRawMantissa = yBits & MASK_DOUBLE_MANTISSA; + final long xBits = Double.doubleToRawLongBits(x); + final int xRawExp = (int) ((xBits & MASK_DOUBLE_EXPONENT) >> 52); + final long xRawMantissa = xBits & MASK_DOUBLE_MANTISSA; + + if (yRawExp > 1085) { + // y is either a very large integral value that does not fit in a long or it is a + // special number + + if ((yRawExp == 2047 && yRawMantissa != 0) + || (xRawExp == 2047 && xRawMantissa != 0)) { + // NaN + return Double.NaN; + } else if (xRawExp == 1023 && xRawMantissa == 0) { + // x = -1.0 or x = +1.0 + if (yRawExp == 2047) { + // y is infinite + return Double.NaN; + } else { + // y is a large even integer + return 1.0; + } + } else { + // the absolute value of x is either greater or smaller than 1.0 + + // if yRawExp == 2047 and mantissa is 0, y = -infinity or y = +infinity + // if 1085 < yRawExp < 2047, y is simply a large number, however, due to limited + // accuracy, at this magnitude it behaves just like infinity with regards to x + if ((y > 0) ^ (xRawExp < 1023)) { + // either y = +infinity (or large engouh) and abs(x) > 1.0 + // or y = -infinity (or large engouh) and abs(x) < 1.0 + return Double.POSITIVE_INFINITY; + } else { + // either y = +infinity (or large engouh) and abs(x) < 1.0 + // or y = -infinity (or large engouh) and abs(x) > 1.0 + return +0.0; + } + } + + } else { + // y is a regular non-zero number + + if (yRawExp >= 1023) { + // y may be an integral value, which should be handled specifically + final long yFullMantissa = IMPLICIT_HIGH_BIT | yRawMantissa; + if (yRawExp < 1075) { + // normal number with negative shift that may have a fractional part + final long integralMask = (-1L) << (1075 - yRawExp); + if ((yFullMantissa & integralMask) == yFullMantissa) { + // all fractional bits are 0, the number is really integral + final long l = yFullMantissa >> (1075 - yRawExp); + return FastMath.pow(x, (y < 0) ? -l : l); + } + } else { + // normal number with positive shift, always an integral value + // we know it fits in a primitive long because yRawExp > 1085 has been + // handled above + final long l = yFullMantissa << (yRawExp - 1075); + return FastMath.pow(x, (y < 0) ? -l : l); + } + } + + // y is a non-integral value + + if (x == 0) { + // x = -0 or x = +0 + // the integer powers have already been handled above + return y < 0 ? Double.POSITIVE_INFINITY : +0.0; + } else if (xRawExp == 2047) { + if (xRawMantissa == 0) { + // x = -infinity or x = +infinity + return (y < 0) ? +0.0 : Double.POSITIVE_INFINITY; + } else { + // NaN + return Double.NaN; + } + } else if (x < 0) { + // the integer powers have already been handled above + return Double.NaN; + } else { + + // this is the general case, for regular fractional numbers x and y + + // Split y into ya and yb such that y = ya+yb + final double tmp = y * HEX_40000000; + final double ya = (y + tmp) - tmp; + final double yb = y - ya; + + /* Compute ln(x) */ + final double lns[] = new double[2]; + final double lores = log(x, lns); + if (Double.isInfinite(lores)) { // don't allow this to be converted to NaN + return lores; + } + + double lna = lns[0]; + double lnb = lns[1]; + + /* resplit lns */ + final double tmp1 = lna * HEX_40000000; + final double tmp2 = (lna + tmp1) - tmp1; + lnb += lna - tmp2; + lna = tmp2; + + // y*ln(x) = (aa+ab) + final double aa = lna * ya; + final double ab = lna * yb + lnb * ya + lnb * yb; + + lna = aa + ab; + lnb = -(lna - aa - ab); + + double z = 1.0 / 120.0; + z = z * lnb + (1.0 / 24.0); + z = z * lnb + (1.0 / 6.0); + z = z * lnb + 0.5; + z = z * lnb + 1.0; + z *= lnb; + + final double result = exp(lna, z, null); + // result = result + result * z; + return result; + } + } + } + } + + /** + * Raise a double to an int power. + * + * @param d Number to raise. + * @param e Exponent. + * @return d<sup>e</sup> + * @since 3.1 + */ + public static double pow(double d, int e) { + return pow(d, (long) e); + } + + /** + * Raise a double to a long power. + * + * @param d Number to raise. + * @param e Exponent. + * @return d<sup>e</sup> + * @since 3.6 + */ + public static double pow(double d, long e) { + if (e == 0) { + return 1.0; + } else if (e > 0) { + return new Split(d).pow(e).full; + } else { + return new Split(d).reciprocal().pow(-e).full; + } + } + + /** Class operator on double numbers split into one 26 bits number and one 27 bits number. */ + private static class Split { + + /** Split version of NaN. */ + public static final Split NAN = new Split(Double.NaN, 0); + + /** Split version of positive infinity. */ + public static final Split POSITIVE_INFINITY = new Split(Double.POSITIVE_INFINITY, 0); + + /** Split version of negative infinity. */ + public static final Split NEGATIVE_INFINITY = new Split(Double.NEGATIVE_INFINITY, 0); + + /** Full number. */ + private final double full; + + /** High order bits. */ + private final double high; + + /** Low order bits. */ + private final double low; + + /** + * Simple constructor. + * + * @param x number to split + */ + Split(final double x) { + full = x; + high = Double.longBitsToDouble(Double.doubleToRawLongBits(x) & ((-1L) << 27)); + low = x - high; + } + + /** + * Simple constructor. + * + * @param high high order bits + * @param low low order bits + */ + Split(final double high, final double low) { + this( + high == 0.0 + ? (low == 0.0 + && Double.doubleToRawLongBits(high) + == Long.MIN_VALUE /* negative zero */ + ? -0.0 + : low) + : high + low, + high, + low); + } + + /** + * Simple constructor. + * + * @param full full number + * @param high high order bits + * @param low low order bits + */ + Split(final double full, final double high, final double low) { + this.full = full; + this.high = high; + this.low = low; + } + + /** + * Multiply the instance by another one. + * + * @param b other instance to multiply by + * @return product + */ + public Split multiply(final Split b) { + // beware the following expressions must NOT be simplified, they rely on floating point + // arithmetic properties + final Split mulBasic = new Split(full * b.full); + final double mulError = + low * b.low - (((mulBasic.full - high * b.high) - low * b.high) - high * b.low); + return new Split(mulBasic.high, mulBasic.low + mulError); + } + + /** + * Compute the reciprocal of the instance. + * + * @return reciprocal of the instance + */ + public Split reciprocal() { + + final double approximateInv = 1.0 / full; + final Split splitInv = new Split(approximateInv); + + // if 1.0/d were computed perfectly, remultiplying it by d should give 1.0 + // we want to estimate the error so we can fix the low order bits of approximateInvLow + // beware the following expressions must NOT be simplified, they rely on floating point + // arithmetic properties + final Split product = multiply(splitInv); + final double error = (product.high - 1) + product.low; + + // better accuracy estimate of reciprocal + return Double.isNaN(error) + ? splitInv + : new Split(splitInv.high, splitInv.low - error / full); + } + + /** + * Computes this^e. + * + * @param e exponent (beware, here it MUST be > 0; the only exclusion is Long.MIN_VALUE) + * @return d^e, split in high and low bits + * @since 3.6 + */ + private Split pow(final long e) { + + // prepare result + Split result = new Split(1); + + // d^(2p) + Split d2p = new Split(full, high, low); + + for (long p = e; p != 0; p >>>= 1) { + + if ((p & 0x1) != 0) { + // accurate multiplication result = result * d^(2p) using Veltkamp TwoProduct + // algorithm + result = result.multiply(d2p); + } + + // accurate squaring d^(2(p+1)) = d^(2p) * d^(2p) using Veltkamp TwoProduct + // algorithm + d2p = d2p.multiply(d2p); + } + + if (Double.isNaN(result.full)) { + if (Double.isNaN(full)) { + return Split.NAN; + } else { + // some intermediate numbers exceeded capacity, + // and the low order bits became NaN (because infinity - infinity = NaN) + if (FastMath.abs(full) < 1) { + return new Split(FastMath.copySign(0.0, full), 0.0); + } else if (full < 0 && (e & 0x1) == 1) { + return Split.NEGATIVE_INFINITY; + } else { + return Split.POSITIVE_INFINITY; + } + } + } else { + return result; + } + } + } + + /** + * Computes sin(x) - x, where |x| < 1/16. Use a Remez polynomial approximation. + * + * @param x a number smaller than 1/16 + * @return sin(x) - x + */ + private static double polySine(final double x) { + double x2 = x * x; + + double p = 2.7553817452272217E-6; + p = p * x2 + -1.9841269659586505E-4; + p = p * x2 + 0.008333333333329196; + p = p * x2 + -0.16666666666666666; + // p *= x2; + // p *= x; + p = p * x2 * x; + + return p; + } + + /** + * Computes cos(x) - 1, where |x| < 1/16. Use a Remez polynomial approximation. + * + * @param x a number smaller than 1/16 + * @return cos(x) - 1 + */ + private static double polyCosine(double x) { + double x2 = x * x; + + double p = 2.479773539153719E-5; + p = p * x2 + -0.0013888888689039883; + p = p * x2 + 0.041666666666621166; + p = p * x2 + -0.49999999999999994; + p *= x2; + + return p; + } + + /** + * Compute sine over the first quadrant (0 < x < pi/2). Use combination of table lookup and + * rational polynomial expansion. + * + * @param xa number from which sine is requested + * @param xb extra bits for x (may be 0.0) + * @return sin(xa + xb) + */ + private static double sinQ(double xa, double xb) { + int idx = (int) ((xa * 8.0) + 0.5); + final double epsilon = xa - EIGHTHS[idx]; // idx*0.125; + + // Table lookups + final double sintA = SINE_TABLE_A[idx]; + final double sintB = SINE_TABLE_B[idx]; + final double costA = COSINE_TABLE_A[idx]; + final double costB = COSINE_TABLE_B[idx]; + + // Polynomial eval of sin(epsilon), cos(epsilon) + double sinEpsA = epsilon; + double sinEpsB = polySine(epsilon); + final double cosEpsA = 1.0; + final double cosEpsB = polyCosine(epsilon); + + // Split epsilon xa + xb = x + final double temp = sinEpsA * HEX_40000000; + double temp2 = (sinEpsA + temp) - temp; + sinEpsB += sinEpsA - temp2; + sinEpsA = temp2; + + /* Compute sin(x) by angle addition formula */ + double result; + + /* Compute the following sum: + * + * result = sintA + costA*sinEpsA + sintA*cosEpsB + costA*sinEpsB + + * sintB + costB*sinEpsA + sintB*cosEpsB + costB*sinEpsB; + * + * Ranges of elements + * + * xxxtA 0 PI/2 + * xxxtB -1.5e-9 1.5e-9 + * sinEpsA -0.0625 0.0625 + * sinEpsB -6e-11 6e-11 + * cosEpsA 1.0 + * cosEpsB 0 -0.0625 + * + */ + + // result = sintA + costA*sinEpsA + sintA*cosEpsB + costA*sinEpsB + + // sintB + costB*sinEpsA + sintB*cosEpsB + costB*sinEpsB; + + // result = sintA + sintA*cosEpsB + sintB + sintB * cosEpsB; + // result += costA*sinEpsA + costA*sinEpsB + costB*sinEpsA + costB * sinEpsB; + double a = 0; + double b = 0; + + double t = sintA; + double c = a + t; + double d = -(c - a - t); + a = c; + b += d; + + t = costA * sinEpsA; + c = a + t; + d = -(c - a - t); + a = c; + b += d; + + b = b + sintA * cosEpsB + costA * sinEpsB; + /* + t = sintA*cosEpsB; + c = a + t; + d = -(c - a - t); + a = c; + b = b + d; + + t = costA*sinEpsB; + c = a + t; + d = -(c - a - t); + a = c; + b = b + d; + */ + + b = b + sintB + costB * sinEpsA + sintB * cosEpsB + costB * sinEpsB; + /* + t = sintB; + c = a + t; + d = -(c - a - t); + a = c; + b = b + d; + + t = costB*sinEpsA; + c = a + t; + d = -(c - a - t); + a = c; + b = b + d; + + t = sintB*cosEpsB; + c = a + t; + d = -(c - a - t); + a = c; + b = b + d; + + t = costB*sinEpsB; + c = a + t; + d = -(c - a - t); + a = c; + b = b + d; + */ + + if (xb != 0.0) { + t = + ((costA + costB) * (cosEpsA + cosEpsB) - (sintA + sintB) * (sinEpsA + sinEpsB)) + * xb; // approximate cosine*xb + c = a + t; + d = -(c - a - t); + a = c; + b += d; + } + + result = a + b; + + return result; + } + + /** + * Compute cosine in the first quadrant by subtracting input from PI/2 and then calling sinQ. + * This is more accurate as the input approaches PI/2. + * + * @param xa number from which cosine is requested + * @param xb extra bits for x (may be 0.0) + * @return cos(xa + xb) + */ + private static double cosQ(double xa, double xb) { + final double pi2a = 1.5707963267948966; + final double pi2b = 6.123233995736766E-17; + + final double a = pi2a - xa; + double b = -(a - pi2a + xa); + b += pi2b - xb; + + return sinQ(a, b); + } + + /** + * Compute tangent (or cotangent) over the first quadrant. 0 < x < pi/2 Use combination of table + * lookup and rational polynomial expansion. + * + * @param xa number from which sine is requested + * @param xb extra bits for x (may be 0.0) + * @param cotanFlag if true, compute the cotangent instead of the tangent + * @return tan(xa+xb) (or cotangent, depending on cotanFlag) + */ + private static double tanQ(double xa, double xb, boolean cotanFlag) { + + int idx = (int) ((xa * 8.0) + 0.5); + final double epsilon = xa - EIGHTHS[idx]; // idx*0.125; + + // Table lookups + final double sintA = SINE_TABLE_A[idx]; + final double sintB = SINE_TABLE_B[idx]; + final double costA = COSINE_TABLE_A[idx]; + final double costB = COSINE_TABLE_B[idx]; + + // Polynomial eval of sin(epsilon), cos(epsilon) + double sinEpsA = epsilon; + double sinEpsB = polySine(epsilon); + final double cosEpsA = 1.0; + final double cosEpsB = polyCosine(epsilon); + + // Split epsilon xa + xb = x + double temp = sinEpsA * HEX_40000000; + double temp2 = (sinEpsA + temp) - temp; + sinEpsB += sinEpsA - temp2; + sinEpsA = temp2; + + /* Compute sin(x) by angle addition formula */ + + /* Compute the following sum: + * + * result = sintA + costA*sinEpsA + sintA*cosEpsB + costA*sinEpsB + + * sintB + costB*sinEpsA + sintB*cosEpsB + costB*sinEpsB; + * + * Ranges of elements + * + * xxxtA 0 PI/2 + * xxxtB -1.5e-9 1.5e-9 + * sinEpsA -0.0625 0.0625 + * sinEpsB -6e-11 6e-11 + * cosEpsA 1.0 + * cosEpsB 0 -0.0625 + * + */ + + // result = sintA + costA*sinEpsA + sintA*cosEpsB + costA*sinEpsB + + // sintB + costB*sinEpsA + sintB*cosEpsB + costB*sinEpsB; + + // result = sintA + sintA*cosEpsB + sintB + sintB * cosEpsB; + // result += costA*sinEpsA + costA*sinEpsB + costB*sinEpsA + costB * sinEpsB; + double a = 0; + double b = 0; + + // Compute sine + double t = sintA; + double c = a + t; + double d = -(c - a - t); + a = c; + b += d; + + t = costA * sinEpsA; + c = a + t; + d = -(c - a - t); + a = c; + b += d; + + b += sintA * cosEpsB + costA * sinEpsB; + b += sintB + costB * sinEpsA + sintB * cosEpsB + costB * sinEpsB; + + double sina = a + b; + double sinb = -(sina - a - b); + + // Compute cosine + + a = b = c = d = 0.0; + + t = costA * cosEpsA; + c = a + t; + d = -(c - a - t); + a = c; + b += d; + + t = -sintA * sinEpsA; + c = a + t; + d = -(c - a - t); + a = c; + b += d; + + b += costB * cosEpsA + costA * cosEpsB + costB * cosEpsB; + b -= sintB * sinEpsA + sintA * sinEpsB + sintB * sinEpsB; + + double cosa = a + b; + double cosb = -(cosa - a - b); + + if (cotanFlag) { + double tmp; + tmp = cosa; + cosa = sina; + sina = tmp; + tmp = cosb; + cosb = sinb; + sinb = tmp; + } + + /* estimate and correct, compute 1.0/(cosa+cosb) */ + /* + double est = (sina+sinb)/(cosa+cosb); + double err = (sina - cosa*est) + (sinb - cosb*est); + est += err/(cosa+cosb); + err = (sina - cosa*est) + (sinb - cosb*est); + */ + + // f(x) = 1/x, f'(x) = -1/x^2 + + double est = sina / cosa; + + /* Split the estimate to get more accurate read on division rounding */ + temp = est * HEX_40000000; + double esta = (est + temp) - temp; + double estb = est - esta; + + temp = cosa * HEX_40000000; + double cosaa = (cosa + temp) - temp; + double cosab = cosa - cosaa; + + // double err = (sina - est*cosa)/cosa; // Correction for division rounding + double err = + (sina - esta * cosaa - esta * cosab - estb * cosaa - estb * cosab) + / cosa; // Correction for division rounding + err += sinb / cosa; // Change in est due to sinb + err += -sina * cosb / cosa / cosa; // Change in est due to cosb + + if (xb != 0.0) { + // tan' = 1 + tan^2 cot' = -(1 + cot^2) + // Approximate impact of xb + double xbadj = xb + est * est * xb; + if (cotanFlag) { + xbadj = -xbadj; + } + + err += xbadj; + } + + return est + err; + } + + /** + * Reduce the input argument using the Payne and Hanek method. This is good for all inputs 0.0 < + * x < inf Output is remainder after dividing by PI/2 The result array should contain 3 numbers. + * result[0] is the integer portion, so mod 4 this gives the quadrant. result[1] is the upper + * bits of the remainder result[2] is the lower bits of the remainder + * + * @param x number to reduce + * @param result placeholder where to put the result + */ + private static void reducePayneHanek(double x, double result[]) { + /* Convert input double to bits */ + long inbits = Double.doubleToRawLongBits(x); + int exponent = (int) ((inbits >> 52) & 0x7ff) - 1023; + + /* Convert to fixed point representation */ + inbits &= 0x000fffffffffffffL; + inbits |= 0x0010000000000000L; + + /* Normalize input to be between 0.5 and 1.0 */ + exponent++; + inbits <<= 11; + + /* Based on the exponent, get a shifted copy of recip2pi */ + long shpi0; + long shpiA; + long shpiB; + int idx = exponent >> 6; + int shift = exponent - (idx << 6); + + if (shift != 0) { + shpi0 = (idx == 0) ? 0 : (RECIP_2PI[idx - 1] << shift); + shpi0 |= RECIP_2PI[idx] >>> (64 - shift); + shpiA = (RECIP_2PI[idx] << shift) | (RECIP_2PI[idx + 1] >>> (64 - shift)); + shpiB = (RECIP_2PI[idx + 1] << shift) | (RECIP_2PI[idx + 2] >>> (64 - shift)); + } else { + shpi0 = (idx == 0) ? 0 : RECIP_2PI[idx - 1]; + shpiA = RECIP_2PI[idx]; + shpiB = RECIP_2PI[idx + 1]; + } + + /* Multiply input by shpiA */ + long a = inbits >>> 32; + long b = inbits & 0xffffffffL; + + long c = shpiA >>> 32; + long d = shpiA & 0xffffffffL; + + long ac = a * c; + long bd = b * d; + long bc = b * c; + long ad = a * d; + + long prodB = bd + (ad << 32); + long prodA = ac + (ad >>> 32); + + boolean bita = (bd & 0x8000000000000000L) != 0; + boolean bitb = (ad & 0x80000000L) != 0; + boolean bitsum = (prodB & 0x8000000000000000L) != 0; + + /* Carry */ + if ((bita && bitb) || ((bita || bitb) && !bitsum)) { + prodA++; + } + + bita = (prodB & 0x8000000000000000L) != 0; + bitb = (bc & 0x80000000L) != 0; + + prodB += bc << 32; + prodA += bc >>> 32; + + bitsum = (prodB & 0x8000000000000000L) != 0; + + /* Carry */ + if ((bita && bitb) || ((bita || bitb) && !bitsum)) { + prodA++; + } + + /* Multiply input by shpiB */ + c = shpiB >>> 32; + d = shpiB & 0xffffffffL; + ac = a * c; + bc = b * c; + ad = a * d; + + /* Collect terms */ + ac += (bc + ad) >>> 32; + + bita = (prodB & 0x8000000000000000L) != 0; + bitb = (ac & 0x8000000000000000L) != 0; + prodB += ac; + bitsum = (prodB & 0x8000000000000000L) != 0; + /* Carry */ + if ((bita && bitb) || ((bita || bitb) && !bitsum)) { + prodA++; + } + + /* Multiply by shpi0 */ + c = shpi0 >>> 32; + d = shpi0 & 0xffffffffL; + + bd = b * d; + bc = b * c; + ad = a * d; + + prodA += bd + ((bc + ad) << 32); + + /* + * prodA, prodB now contain the remainder as a fraction of PI. We want this as a fraction of + * PI/2, so use the following steps: + * 1.) multiply by 4. + * 2.) do a fixed point muliply by PI/4. + * 3.) Convert to floating point. + * 4.) Multiply by 2 + */ + + /* This identifies the quadrant */ + int intPart = (int) (prodA >>> 62); + + /* Multiply by 4 */ + prodA <<= 2; + prodA |= prodB >>> 62; + prodB <<= 2; + + /* Multiply by PI/4 */ + a = prodA >>> 32; + b = prodA & 0xffffffffL; + + c = PI_O_4_BITS[0] >>> 32; + d = PI_O_4_BITS[0] & 0xffffffffL; + + ac = a * c; + bd = b * d; + bc = b * c; + ad = a * d; + + long prod2B = bd + (ad << 32); + long prod2A = ac + (ad >>> 32); + + bita = (bd & 0x8000000000000000L) != 0; + bitb = (ad & 0x80000000L) != 0; + bitsum = (prod2B & 0x8000000000000000L) != 0; + + /* Carry */ + if ((bita && bitb) || ((bita || bitb) && !bitsum)) { + prod2A++; + } + + bita = (prod2B & 0x8000000000000000L) != 0; + bitb = (bc & 0x80000000L) != 0; + + prod2B += bc << 32; + prod2A += bc >>> 32; + + bitsum = (prod2B & 0x8000000000000000L) != 0; + + /* Carry */ + if ((bita && bitb) || ((bita || bitb) && !bitsum)) { + prod2A++; + } + + /* Multiply input by pio4bits[1] */ + c = PI_O_4_BITS[1] >>> 32; + d = PI_O_4_BITS[1] & 0xffffffffL; + ac = a * c; + bc = b * c; + ad = a * d; + + /* Collect terms */ + ac += (bc + ad) >>> 32; + + bita = (prod2B & 0x8000000000000000L) != 0; + bitb = (ac & 0x8000000000000000L) != 0; + prod2B += ac; + bitsum = (prod2B & 0x8000000000000000L) != 0; + /* Carry */ + if ((bita && bitb) || ((bita || bitb) && !bitsum)) { + prod2A++; + } + + /* Multiply inputB by pio4bits[0] */ + a = prodB >>> 32; + b = prodB & 0xffffffffL; + c = PI_O_4_BITS[0] >>> 32; + d = PI_O_4_BITS[0] & 0xffffffffL; + ac = a * c; + bc = b * c; + ad = a * d; + + /* Collect terms */ + ac += (bc + ad) >>> 32; + + bita = (prod2B & 0x8000000000000000L) != 0; + bitb = (ac & 0x8000000000000000L) != 0; + prod2B += ac; + bitsum = (prod2B & 0x8000000000000000L) != 0; + /* Carry */ + if ((bita && bitb) || ((bita || bitb) && !bitsum)) { + prod2A++; + } + + /* Convert to double */ + double tmpA = (prod2A >>> 12) / TWO_POWER_52; // High order 52 bits + double tmpB = + (((prod2A & 0xfffL) << 40) + (prod2B >>> 24)) + / TWO_POWER_52 + / TWO_POWER_52; // Low bits + + double sumA = tmpA + tmpB; + double sumB = -(sumA - tmpA - tmpB); + + /* Multiply by PI/2 and return */ + result[0] = intPart; + result[1] = sumA * 2.0; + result[2] = sumB * 2.0; + } + + /** + * Sine function. + * + * @param x Argument. + * @return sin(x) + */ + public static double sin(double x) { + boolean negative = false; + int quadrant = 0; + double xa; + double xb = 0.0; + + /* Take absolute value of the input */ + xa = x; + if (x < 0) { + negative = true; + xa = -xa; + } + + /* Check for zero and negative zero */ + if (xa == 0.0) { + long bits = Double.doubleToRawLongBits(x); + if (bits < 0) { + return -0.0; + } + return 0.0; + } + + if (xa != xa || xa == Double.POSITIVE_INFINITY) { + return Double.NaN; + } + + /* Perform any argument reduction */ + if (xa > 3294198.0) { + // PI * (2**20) + // Argument too big for CodyWaite reduction. Must use + // PayneHanek. + double reduceResults[] = new double[3]; + reducePayneHanek(xa, reduceResults); + quadrant = ((int) reduceResults[0]) & 3; + xa = reduceResults[1]; + xb = reduceResults[2]; + } else if (xa > 1.5707963267948966) { + final CodyWaite cw = new CodyWaite(xa); + quadrant = cw.getK() & 3; + xa = cw.getRemA(); + xb = cw.getRemB(); + } + + if (negative) { + quadrant ^= 2; // Flip bit 1 + } + + switch (quadrant) { + case 0: + return sinQ(xa, xb); + case 1: + return cosQ(xa, xb); + case 2: + return -sinQ(xa, xb); + case 3: + return -cosQ(xa, xb); + default: + return Double.NaN; + } + } + + /** + * Cosine function. + * + * @param x Argument. + * @return cos(x) + */ + public static double cos(double x) { + int quadrant = 0; + + /* Take absolute value of the input */ + double xa = x; + if (x < 0) { + xa = -xa; + } + + if (xa != xa || xa == Double.POSITIVE_INFINITY) { + return Double.NaN; + } + + /* Perform any argument reduction */ + double xb = 0; + if (xa > 3294198.0) { + // PI * (2**20) + // Argument too big for CodyWaite reduction. Must use + // PayneHanek. + double reduceResults[] = new double[3]; + reducePayneHanek(xa, reduceResults); + quadrant = ((int) reduceResults[0]) & 3; + xa = reduceResults[1]; + xb = reduceResults[2]; + } else if (xa > 1.5707963267948966) { + final CodyWaite cw = new CodyWaite(xa); + quadrant = cw.getK() & 3; + xa = cw.getRemA(); + xb = cw.getRemB(); + } + + // if (negative) + // quadrant = (quadrant + 2) % 4; + + switch (quadrant) { + case 0: + return cosQ(xa, xb); + case 1: + return -sinQ(xa, xb); + case 2: + return -cosQ(xa, xb); + case 3: + return sinQ(xa, xb); + default: + return Double.NaN; + } + } + + /** + * Tangent function. + * + * @param x Argument. + * @return tan(x) + */ + public static double tan(double x) { + boolean negative = false; + int quadrant = 0; + + /* Take absolute value of the input */ + double xa = x; + if (x < 0) { + negative = true; + xa = -xa; + } + + /* Check for zero and negative zero */ + if (xa == 0.0) { + long bits = Double.doubleToRawLongBits(x); + if (bits < 0) { + return -0.0; + } + return 0.0; + } + + if (xa != xa || xa == Double.POSITIVE_INFINITY) { + return Double.NaN; + } + + /* Perform any argument reduction */ + double xb = 0; + if (xa > 3294198.0) { + // PI * (2**20) + // Argument too big for CodyWaite reduction. Must use + // PayneHanek. + double reduceResults[] = new double[3]; + reducePayneHanek(xa, reduceResults); + quadrant = ((int) reduceResults[0]) & 3; + xa = reduceResults[1]; + xb = reduceResults[2]; + } else if (xa > 1.5707963267948966) { + final CodyWaite cw = new CodyWaite(xa); + quadrant = cw.getK() & 3; + xa = cw.getRemA(); + xb = cw.getRemB(); + } + + if (xa > 1.5) { + // Accuracy suffers between 1.5 and PI/2 + final double pi2a = 1.5707963267948966; + final double pi2b = 6.123233995736766E-17; + + final double a = pi2a - xa; + double b = -(a - pi2a + xa); + b += pi2b - xb; + + xa = a + b; + xb = -(xa - a - b); + quadrant ^= 1; + negative ^= true; + } + + double result; + if ((quadrant & 1) == 0) { + result = tanQ(xa, xb, false); + } else { + result = -tanQ(xa, xb, true); + } + + if (negative) { + result = -result; + } + + return result; + } + + /** + * Arctangent function + * + * @param x a number + * @return atan(x) + */ + public static double atan(double x) { + return atan(x, 0.0, false); + } + + /** + * Internal helper function to compute arctangent. + * + * @param xa number from which arctangent is requested + * @param xb extra bits for x (may be 0.0) + * @param leftPlane if true, result angle must be put in the left half plane + * @return atan(xa + xb) (or angle shifted by {@code PI} if leftPlane is true) + */ + private static double atan(double xa, double xb, boolean leftPlane) { + if (xa == 0.0) { // Matches +/- 0.0; return correct sign + return leftPlane ? copySign(Math.PI, xa) : xa; + } + + final boolean negate; + if (xa < 0) { + // negative + xa = -xa; + xb = -xb; + negate = true; + } else { + negate = false; + } + + if (xa > 1.633123935319537E16) { // Very large input + return (negate ^ leftPlane) ? (-Math.PI * F_1_2) : (Math.PI * F_1_2); + } + + /* Estimate the closest tabulated arctan value, compute eps = xa-tangentTable */ + final int idx; + if (xa < 1) { + idx = (int) (((-1.7168146928204136 * xa * xa + 8.0) * xa) + 0.5); + } else { + final double oneOverXa = 1 / xa; + idx = + (int) + (-((-1.7168146928204136 * oneOverXa * oneOverXa + 8.0) * oneOverXa) + + 13.07); + } + + final double ttA = TANGENT_TABLE_A[idx]; + final double ttB = TANGENT_TABLE_B[idx]; + + double epsA = xa - ttA; + double epsB = -(epsA - xa + ttA); + epsB += xb - ttB; + + double temp = epsA + epsB; + epsB = -(temp - epsA - epsB); + epsA = temp; + + /* Compute eps = eps / (1.0 + xa*tangent) */ + temp = xa * HEX_40000000; + double ya = xa + temp - temp; + double yb = xb + xa - ya; + xa = ya; + xb += yb; + + // if (idx > 8 || idx == 0) + if (idx == 0) { + /* If the slope of the arctan is gentle enough (< 0.45), this approximation will suffice */ + // double denom = 1.0 / (1.0 + xa*tangentTableA[idx] + xb*tangentTableA[idx] + + // xa*tangentTableB[idx] + xb*tangentTableB[idx]); + final double denom = 1d / (1d + (xa + xb) * (ttA + ttB)); + // double denom = 1.0 / (1.0 + xa*tangentTableA[idx]); + ya = epsA * denom; + yb = epsB * denom; + } else { + double temp2 = xa * ttA; + double za = 1d + temp2; + double zb = -(za - 1d - temp2); + temp2 = xb * ttA + xa * ttB; + temp = za + temp2; + zb += -(temp - za - temp2); + za = temp; + + zb += xb * ttB; + ya = epsA / za; + + temp = ya * HEX_40000000; + final double yaa = (ya + temp) - temp; + final double yab = ya - yaa; + + temp = za * HEX_40000000; + final double zaa = (za + temp) - temp; + final double zab = za - zaa; + + /* Correct for rounding in division */ + yb = (epsA - yaa * zaa - yaa * zab - yab * zaa - yab * zab) / za; + + yb += -epsA * zb / za / za; + yb += epsB / za; + } + + epsA = ya; + epsB = yb; + + /* Evaluate polynomial */ + final double epsA2 = epsA * epsA; + + /* + yb = -0.09001346640161823; + yb = yb * epsA2 + 0.11110718400605211; + yb = yb * epsA2 + -0.1428571349122913; + yb = yb * epsA2 + 0.19999999999273194; + yb = yb * epsA2 + -0.33333333333333093; + yb = yb * epsA2 * epsA; + */ + + yb = 0.07490822288864472; + yb = yb * epsA2 - 0.09088450866185192; + yb = yb * epsA2 + 0.11111095942313305; + yb = yb * epsA2 - 0.1428571423679182; + yb = yb * epsA2 + 0.19999999999923582; + yb = yb * epsA2 - 0.33333333333333287; + yb = yb * epsA2 * epsA; + + ya = epsA; + + temp = ya + yb; + yb = -(temp - ya - yb); + ya = temp; + + /* Add in effect of epsB. atan'(x) = 1/(1+x^2) */ + yb += epsB / (1d + epsA * epsA); + + final double eighths = EIGHTHS[idx]; + + // result = yb + eighths[idx] + ya; + double za = eighths + ya; + double zb = -(za - eighths - ya); + temp = za + yb; + zb += -(temp - za - yb); + za = temp; + + double result = za + zb; + + if (leftPlane) { + // Result is in the left plane + final double resultb = -(result - za - zb); + final double pia = 1.5707963267948966 * 2; + final double pib = 6.123233995736766E-17 * 2; + + za = pia - result; + zb = -(za - pia + result); + zb += pib - resultb; + + result = za + zb; + } + + if (negate ^ leftPlane) { + result = -result; + } + + return result; + } + + /** + * Two arguments arctangent function + * + * @param y ordinate + * @param x abscissa + * @return phase angle of point (x,y) between {@code -PI} and {@code PI} + */ + public static double atan2(double y, double x) { + if (x != x || y != y) { + return Double.NaN; + } + + if (y == 0) { + final double result = x * y; + final double invx = 1d / x; + final double invy = 1d / y; + + if (invx == 0) { // X is infinite + if (x > 0) { + return y; // return +/- 0.0 + } else { + return copySign(Math.PI, y); + } + } + + if (x < 0 || invx < 0) { + if (y < 0 || invy < 0) { + return -Math.PI; + } else { + return Math.PI; + } + } else { + return result; + } + } + + // y cannot now be zero + + if (y == Double.POSITIVE_INFINITY) { + if (x == Double.POSITIVE_INFINITY) { + return Math.PI * F_1_4; + } + + if (x == Double.NEGATIVE_INFINITY) { + return Math.PI * F_3_4; + } + + return Math.PI * F_1_2; + } + + if (y == Double.NEGATIVE_INFINITY) { + if (x == Double.POSITIVE_INFINITY) { + return -Math.PI * F_1_4; + } + + if (x == Double.NEGATIVE_INFINITY) { + return -Math.PI * F_3_4; + } + + return -Math.PI * F_1_2; + } + + if (x == Double.POSITIVE_INFINITY) { + if (y > 0 || 1 / y > 0) { + return 0d; + } + + if (y < 0 || 1 / y < 0) { + return -0d; + } + } + + if (x == Double.NEGATIVE_INFINITY) { + if (y > 0.0 || 1 / y > 0.0) { + return Math.PI; + } + + if (y < 0 || 1 / y < 0) { + return -Math.PI; + } + } + + // Neither y nor x can be infinite or NAN here + + if (x == 0) { + if (y > 0 || 1 / y > 0) { + return Math.PI * F_1_2; + } + + if (y < 0 || 1 / y < 0) { + return -Math.PI * F_1_2; + } + } + + // Compute ratio r = y/x + final double r = y / x; + if (Double.isInfinite(r)) { // bypass calculations that can create NaN + return atan(r, 0, x < 0); + } + + double ra = doubleHighPart(r); + double rb = r - ra; + + // Split x + final double xa = doubleHighPart(x); + final double xb = x - xa; + + rb += (y - ra * xa - ra * xb - rb * xa - rb * xb) / x; + + final double temp = ra + rb; + rb = -(temp - ra - rb); + ra = temp; + + if (ra == 0) { // Fix up the sign so atan works correctly + ra = copySign(0d, y); + } + + // Call atan + final double result = atan(ra, rb, x < 0); + + return result; + } + + /** + * Compute the arc sine of a number. + * + * @param x number on which evaluation is done + * @return arc sine of x + */ + public static double asin(double x) { + if (x != x) { + return Double.NaN; + } + + if (x > 1.0 || x < -1.0) { + return Double.NaN; + } + + if (x == 1.0) { + return Math.PI / 2.0; + } + + if (x == -1.0) { + return -Math.PI / 2.0; + } + + if (x == 0.0) { // Matches +/- 0.0; return correct sign + return x; + } + + /* Compute asin(x) = atan(x/sqrt(1-x*x)) */ + + /* Split x */ + double temp = x * HEX_40000000; + final double xa = x + temp - temp; + final double xb = x - xa; + + /* Square it */ + double ya = xa * xa; + double yb = xa * xb * 2.0 + xb * xb; + + /* Subtract from 1 */ + ya = -ya; + yb = -yb; + + double za = 1.0 + ya; + double zb = -(za - 1.0 - ya); + + temp = za + yb; + zb += -(temp - za - yb); + za = temp; + + /* Square root */ + double y; + y = sqrt(za); + temp = y * HEX_40000000; + ya = y + temp - temp; + yb = y - ya; + + /* Extend precision of sqrt */ + yb += (za - ya * ya - 2 * ya * yb - yb * yb) / (2.0 * y); + + /* Contribution of zb to sqrt */ + double dx = zb / (2.0 * y); + + // Compute ratio r = x/y + double r = x / y; + temp = r * HEX_40000000; + double ra = r + temp - temp; + double rb = r - ra; + + rb += (x - ra * ya - ra * yb - rb * ya - rb * yb) / y; // Correct for rounding in division + rb += -x * dx / y / y; // Add in effect additional bits of sqrt. + + temp = ra + rb; + rb = -(temp - ra - rb); + ra = temp; + + return atan(ra, rb, false); + } + + /** + * Compute the arc cosine of a number. + * + * @param x number on which evaluation is done + * @return arc cosine of x + */ + public static double acos(double x) { + if (x != x) { + return Double.NaN; + } + + if (x > 1.0 || x < -1.0) { + return Double.NaN; + } + + if (x == -1.0) { + return Math.PI; + } + + if (x == 1.0) { + return 0.0; + } + + if (x == 0) { + return Math.PI / 2.0; + } + + /* Compute acos(x) = atan(sqrt(1-x*x)/x) */ + + /* Split x */ + double temp = x * HEX_40000000; + final double xa = x + temp - temp; + final double xb = x - xa; + + /* Square it */ + double ya = xa * xa; + double yb = xa * xb * 2.0 + xb * xb; + + /* Subtract from 1 */ + ya = -ya; + yb = -yb; + + double za = 1.0 + ya; + double zb = -(za - 1.0 - ya); + + temp = za + yb; + zb += -(temp - za - yb); + za = temp; + + /* Square root */ + double y = sqrt(za); + temp = y * HEX_40000000; + ya = y + temp - temp; + yb = y - ya; + + /* Extend precision of sqrt */ + yb += (za - ya * ya - 2 * ya * yb - yb * yb) / (2.0 * y); + + /* Contribution of zb to sqrt */ + yb += zb / (2.0 * y); + y = ya + yb; + yb = -(y - ya - yb); + + // Compute ratio r = y/x + double r = y / x; + + // Did r overflow? + if (Double.isInfinite(r)) { // x is effectively zero + return Math.PI / 2; // so return the appropriate value + } + + double ra = doubleHighPart(r); + double rb = r - ra; + + rb += (y - ra * xa - ra * xb - rb * xa - rb * xb) / x; // Correct for rounding in division + rb += yb / x; // Add in effect additional bits of sqrt. + + temp = ra + rb; + rb = -(temp - ra - rb); + ra = temp; + + return atan(ra, rb, x < 0); + } + + /** + * Compute the cubic root of a number. + * + * @param x number on which evaluation is done + * @return cubic root of x + */ + public static double cbrt(double x) { + /* Convert input double to bits */ + long inbits = Double.doubleToRawLongBits(x); + int exponent = (int) ((inbits >> 52) & 0x7ff) - 1023; + boolean subnormal = false; + + if (exponent == -1023) { + if (x == 0) { + return x; + } + + /* Subnormal, so normalize */ + subnormal = true; + x *= 1.8014398509481984E16; // 2^54 + inbits = Double.doubleToRawLongBits(x); + exponent = (int) ((inbits >> 52) & 0x7ff) - 1023; + } + + if (exponent == 1024) { + // Nan or infinity. Don't care which. + return x; + } + + /* Divide the exponent by 3 */ + int exp3 = exponent / 3; + + /* p2 will be the nearest power of 2 to x with its exponent divided by 3 */ + double p2 = + Double.longBitsToDouble( + (inbits & 0x8000000000000000L) | (long) (((exp3 + 1023) & 0x7ff)) << 52); + + /* This will be a number between 1 and 2 */ + final double mant = + Double.longBitsToDouble((inbits & 0x000fffffffffffffL) | 0x3ff0000000000000L); + + /* Estimate the cube root of mant by polynomial */ + double est = -0.010714690733195933; + est = est * mant + 0.0875862700108075; + est = est * mant + -0.3058015757857271; + est = est * mant + 0.7249995199969751; + est = est * mant + 0.5039018405998233; + + est *= CBRTTWO[exponent % 3 + 2]; + + // est should now be good to about 15 bits of precision. Do 2 rounds of + // Newton's method to get closer, this should get us full double precision + // Scale down x for the purpose of doing newtons method. This avoids over/under flows. + final double xs = x / (p2 * p2 * p2); + est += (xs - est * est * est) / (3 * est * est); + est += (xs - est * est * est) / (3 * est * est); + + // Do one round of Newton's method in extended precision to get the last bit right. + double temp = est * HEX_40000000; + double ya = est + temp - temp; + double yb = est - ya; + + double za = ya * ya; + double zb = ya * yb * 2.0 + yb * yb; + temp = za * HEX_40000000; + double temp2 = za + temp - temp; + zb += za - temp2; + za = temp2; + + zb = za * yb + ya * zb + zb * yb; + za *= ya; + + double na = xs - za; + double nb = -(na - xs + za); + nb -= zb; + + est += (na + nb) / (3 * est * est); + + /* Scale by a power of two, so this is exact. */ + est *= p2; + + if (subnormal) { + est *= 3.814697265625E-6; // 2^-18 + } + + return est; + } + + /** + * Convert degrees to radians, with error of less than 0.5 ULP + * + * @param x angle in degrees + * @return x converted into radians + */ + public static double toRadians(double x) { + if (Double.isInfinite(x) || x == 0.0) { // Matches +/- 0.0; return correct sign + return x; + } + + // These are PI/180 split into high and low order bits + final double facta = 0.01745329052209854; + final double factb = 1.997844754509471E-9; + + double xa = doubleHighPart(x); + double xb = x - xa; + + double result = xb * factb + xb * facta + xa * factb + xa * facta; + if (result == 0) { + result *= x; // ensure correct sign if calculation underflows + } + return result; + } + + /** + * Convert radians to degrees, with error of less than 0.5 ULP + * + * @param x angle in radians + * @return x converted into degrees + */ + public static double toDegrees(double x) { + if (Double.isInfinite(x) || x == 0.0) { // Matches +/- 0.0; return correct sign + return x; + } + + // These are 180/PI split into high and low order bits + final double facta = 57.2957763671875; + final double factb = 3.145894820876798E-6; + + double xa = doubleHighPart(x); + double xb = x - xa; + + return xb * factb + xb * facta + xa * factb + xa * facta; + } + + /** + * Absolute value. + * + * @param x number from which absolute value is requested + * @return abs(x) + */ + public static int abs(final int x) { + final int i = x >>> 31; + return (x ^ (~i + 1)) + i; + } + + /** + * Absolute value. + * + * @param x number from which absolute value is requested + * @return abs(x) + */ + public static long abs(final long x) { + final long l = x >>> 63; + // l is one if x negative zero else + // ~l+1 is zero if x is positive, -1 if x is negative + // x^(~l+1) is x is x is positive, ~x if x is negative + // add around + return (x ^ (~l + 1)) + l; + } + + /** + * Absolute value. + * + * @param x number from which absolute value is requested + * @return abs(x) + */ + public static float abs(final float x) { + return Float.intBitsToFloat(MASK_NON_SIGN_INT & Float.floatToRawIntBits(x)); + } + + /** + * Absolute value. + * + * @param x number from which absolute value is requested + * @return abs(x) + */ + public static double abs(double x) { + return Double.longBitsToDouble(MASK_NON_SIGN_LONG & Double.doubleToRawLongBits(x)); + } + + /** + * Compute least significant bit (Unit in Last Position) for a number. + * + * @param x number from which ulp is requested + * @return ulp(x) + */ + public static double ulp(double x) { + if (Double.isInfinite(x)) { + return Double.POSITIVE_INFINITY; + } + return abs(x - Double.longBitsToDouble(Double.doubleToRawLongBits(x) ^ 1)); + } + + /** + * Compute least significant bit (Unit in Last Position) for a number. + * + * @param x number from which ulp is requested + * @return ulp(x) + */ + public static float ulp(float x) { + if (Float.isInfinite(x)) { + return Float.POSITIVE_INFINITY; + } + return abs(x - Float.intBitsToFloat(Float.floatToIntBits(x) ^ 1)); + } + + /** + * Multiply a double number by a power of 2. + * + * @param d number to multiply + * @param n power of 2 + * @return d × 2<sup>n</sup> + */ + public static double scalb(final double d, final int n) { + + // first simple and fast handling when 2^n can be represented using normal numbers + if ((n > -1023) && (n < 1024)) { + return d * Double.longBitsToDouble(((long) (n + 1023)) << 52); + } + + // handle special cases + if (Double.isNaN(d) || Double.isInfinite(d) || (d == 0)) { + return d; + } + if (n < -2098) { + return (d > 0) ? 0.0 : -0.0; + } + if (n > 2097) { + return (d > 0) ? Double.POSITIVE_INFINITY : Double.NEGATIVE_INFINITY; + } + + // decompose d + final long bits = Double.doubleToRawLongBits(d); + final long sign = bits & 0x8000000000000000L; + int exponent = ((int) (bits >>> 52)) & 0x7ff; + long mantissa = bits & 0x000fffffffffffffL; + + // compute scaled exponent + int scaledExponent = exponent + n; + + if (n < 0) { + // we are really in the case n <= -1023 + if (scaledExponent > 0) { + // both the input and the result are normal numbers, we only adjust the exponent + return Double.longBitsToDouble(sign | (((long) scaledExponent) << 52) | mantissa); + } else if (scaledExponent > -53) { + // the input is a normal number and the result is a subnormal number + + // recover the hidden mantissa bit + mantissa |= 1L << 52; + + // scales down complete mantissa, hence losing least significant bits + final long mostSignificantLostBit = mantissa & (1L << (-scaledExponent)); + mantissa >>>= 1 - scaledExponent; + if (mostSignificantLostBit != 0) { + // we need to add 1 bit to round up the result + mantissa++; + } + return Double.longBitsToDouble(sign | mantissa); + + } else { + // no need to compute the mantissa, the number scales down to 0 + return (sign == 0L) ? 0.0 : -0.0; + } + } else { + // we are really in the case n >= 1024 + if (exponent == 0) { + + // the input number is subnormal, normalize it + while ((mantissa >>> 52) != 1) { + mantissa <<= 1; + --scaledExponent; + } + ++scaledExponent; + mantissa &= 0x000fffffffffffffL; + + if (scaledExponent < 2047) { + return Double.longBitsToDouble( + sign | (((long) scaledExponent) << 52) | mantissa); + } else { + return (sign == 0L) ? Double.POSITIVE_INFINITY : Double.NEGATIVE_INFINITY; + } + + } else if (scaledExponent < 2047) { + return Double.longBitsToDouble(sign | (((long) scaledExponent) << 52) | mantissa); + } else { + return (sign == 0L) ? Double.POSITIVE_INFINITY : Double.NEGATIVE_INFINITY; + } + } + } + + /** + * Multiply a float number by a power of 2. + * + * @param f number to multiply + * @param n power of 2 + * @return f × 2<sup>n</sup> + */ + public static float scalb(final float f, final int n) { + + // first simple and fast handling when 2^n can be represented using normal numbers + if ((n > -127) && (n < 128)) { + return f * Float.intBitsToFloat((n + 127) << 23); + } + + // handle special cases + if (Float.isNaN(f) || Float.isInfinite(f) || (f == 0f)) { + return f; + } + if (n < -277) { + return (f > 0) ? 0.0f : -0.0f; + } + if (n > 276) { + return (f > 0) ? Float.POSITIVE_INFINITY : Float.NEGATIVE_INFINITY; + } + + // decompose f + final int bits = Float.floatToIntBits(f); + final int sign = bits & 0x80000000; + int exponent = (bits >>> 23) & 0xff; + int mantissa = bits & 0x007fffff; + + // compute scaled exponent + int scaledExponent = exponent + n; + + if (n < 0) { + // we are really in the case n <= -127 + if (scaledExponent > 0) { + // both the input and the result are normal numbers, we only adjust the exponent + return Float.intBitsToFloat(sign | (scaledExponent << 23) | mantissa); + } else if (scaledExponent > -24) { + // the input is a normal number and the result is a subnormal number + + // recover the hidden mantissa bit + mantissa |= 1 << 23; + + // scales down complete mantissa, hence losing least significant bits + final int mostSignificantLostBit = mantissa & (1 << (-scaledExponent)); + mantissa >>>= 1 - scaledExponent; + if (mostSignificantLostBit != 0) { + // we need to add 1 bit to round up the result + mantissa++; + } + return Float.intBitsToFloat(sign | mantissa); + + } else { + // no need to compute the mantissa, the number scales down to 0 + return (sign == 0) ? 0.0f : -0.0f; + } + } else { + // we are really in the case n >= 128 + if (exponent == 0) { + + // the input number is subnormal, normalize it + while ((mantissa >>> 23) != 1) { + mantissa <<= 1; + --scaledExponent; + } + ++scaledExponent; + mantissa &= 0x007fffff; + + if (scaledExponent < 255) { + return Float.intBitsToFloat(sign | (scaledExponent << 23) | mantissa); + } else { + return (sign == 0) ? Float.POSITIVE_INFINITY : Float.NEGATIVE_INFINITY; + } + + } else if (scaledExponent < 255) { + return Float.intBitsToFloat(sign | (scaledExponent << 23) | mantissa); + } else { + return (sign == 0) ? Float.POSITIVE_INFINITY : Float.NEGATIVE_INFINITY; + } + } + } + + /** + * Get the next machine representable number after a number, moving in the direction of another + * number. + * + * <p>The ordering is as follows (increasing): + * + * <ul> + * <li>-INFINITY + * <li>-MAX_VALUE + * <li>-MIN_VALUE + * <li>-0.0 + * <li>+0.0 + * <li>+MIN_VALUE + * <li>+MAX_VALUE + * <li>+INFINITY + * <li> + * <p>If arguments compare equal, then the second argument is returned. + * <p>If {@code direction} is greater than {@code d}, the smallest machine representable + * number strictly greater than {@code d} is returned; if less, then the largest + * representable number strictly less than {@code d} is returned. + * <p>If {@code d} is infinite and direction does not bring it back to finite numbers, it + * is returned unchanged. + * + * @param d base number + * @param direction (the only important thing is whether {@code direction} is greater or smaller + * than {@code d}) + * @return the next machine representable number in the specified direction + */ + public static double nextAfter(double d, double direction) { + + // handling of some important special cases + if (Double.isNaN(d) || Double.isNaN(direction)) { + return Double.NaN; + } else if (d == direction) { + return direction; + } else if (Double.isInfinite(d)) { + return (d < 0) ? -Double.MAX_VALUE : Double.MAX_VALUE; + } else if (d == 0) { + return (direction < 0) ? -Double.MIN_VALUE : Double.MIN_VALUE; + } + // special cases MAX_VALUE to infinity and MIN_VALUE to 0 + // are handled just as normal numbers + // can use raw bits since already dealt with infinity and NaN + final long bits = Double.doubleToRawLongBits(d); + final long sign = bits & 0x8000000000000000L; + if ((direction < d) ^ (sign == 0L)) { + return Double.longBitsToDouble(sign | ((bits & 0x7fffffffffffffffL) + 1)); + } else { + return Double.longBitsToDouble(sign | ((bits & 0x7fffffffffffffffL) - 1)); + } + } + + /** + * Get the next machine representable number after a number, moving in the direction of another + * number. + * + * <p>The ordering is as follows (increasing): + * + * <ul> + * <li>-INFINITY + * <li>-MAX_VALUE + * <li>-MIN_VALUE + * <li>-0.0 + * <li>+0.0 + * <li>+MIN_VALUE + * <li>+MAX_VALUE + * <li>+INFINITY + * <li> + * <p>If arguments compare equal, then the second argument is returned. + * <p>If {@code direction} is greater than {@code f}, the smallest machine representable + * number strictly greater than {@code f} is returned; if less, then the largest + * representable number strictly less than {@code f} is returned. + * <p>If {@code f} is infinite and direction does not bring it back to finite numbers, it + * is returned unchanged. + * + * @param f base number + * @param direction (the only important thing is whether {@code direction} is greater or smaller + * than {@code f}) + * @return the next machine representable number in the specified direction + */ + public static float nextAfter(final float f, final double direction) { + + // handling of some important special cases + if (Double.isNaN(f) || Double.isNaN(direction)) { + return Float.NaN; + } else if (f == direction) { + return (float) direction; + } else if (Float.isInfinite(f)) { + return (f < 0f) ? -Float.MAX_VALUE : Float.MAX_VALUE; + } else if (f == 0f) { + return (direction < 0) ? -Float.MIN_VALUE : Float.MIN_VALUE; + } + // special cases MAX_VALUE to infinity and MIN_VALUE to 0 + // are handled just as normal numbers + + final int bits = Float.floatToIntBits(f); + final int sign = bits & 0x80000000; + if ((direction < f) ^ (sign == 0)) { + return Float.intBitsToFloat(sign | ((bits & 0x7fffffff) + 1)); + } else { + return Float.intBitsToFloat(sign | ((bits & 0x7fffffff) - 1)); + } + } + + /** + * Get the largest whole number smaller than x. + * + * @param x number from which floor is requested + * @return a double number f such that f is an integer f <= x < f + 1.0 + */ + public static double floor(double x) { + long y; + + if (x != x) { // NaN + return x; + } + + if (x >= TWO_POWER_52 || x <= -TWO_POWER_52) { + return x; + } + + y = (long) x; + if (x < 0 && y != x) { + y--; + } + + if (y == 0) { + return x * y; + } + + return y; + } + + /** + * Get the smallest whole number larger than x. + * + * @param x number from which ceil is requested + * @return a double number c such that c is an integer c - 1.0 < x <= c + */ + public static double ceil(double x) { + double y; + + if (x != x) { // NaN + return x; + } + + y = floor(x); + if (y == x) { + return y; + } + + y += 1.0; + + if (y == 0) { + return x * y; + } + + return y; + } + + /** + * Get the whole number that is the nearest to x, or the even one if x is exactly half way + * between two integers. + * + * @param x number from which nearest whole number is requested + * @return a double number r such that r is an integer r - 0.5 <= x <= r + 0.5 + */ + public static double rint(double x) { + double y = floor(x); + double d = x - y; + + if (d > 0.5) { + if (y == -1.0) { + return -0.0; // Preserve sign of operand + } + return y + 1.0; + } + if (d < 0.5) { + return y; + } + + /* half way, round to even */ + long z = (long) y; + return (z & 1) == 0 ? y : y + 1.0; + } + + /** + * Get the closest long to x. + * + * @param x number from which closest long is requested + * @return closest long to x + */ + public static long round(double x) { + return (long) floor(x + 0.5); + } + + /** + * Get the closest int to x. + * + * @param x number from which closest int is requested + * @return closest int to x + */ + public static int round(final float x) { + return (int) floor(x + 0.5f); + } + + /** + * Compute the minimum of two values + * + * @param a first value + * @param b second value + * @return a if a is lesser or equal to b, b otherwise + */ + public static int min(final int a, final int b) { + return (a <= b) ? a : b; + } + + /** + * Compute the minimum of two values + * + * @param a first value + * @param b second value + * @return a if a is lesser or equal to b, b otherwise + */ + public static long min(final long a, final long b) { + return (a <= b) ? a : b; + } + + /** + * Compute the minimum of two values + * + * @param a first value + * @param b second value + * @return a if a is lesser or equal to b, b otherwise + */ + public static float min(final float a, final float b) { + if (a > b) { + return b; + } + if (a < b) { + return a; + } + /* if either arg is NaN, return NaN */ + if (a != b) { + return Float.NaN; + } + /* min(+0.0,-0.0) == -0.0 */ + /* 0x80000000 == Float.floatToRawIntBits(-0.0d) */ + int bits = Float.floatToRawIntBits(a); + if (bits == 0x80000000) { + return a; + } + return b; + } + + /** + * Compute the minimum of two values + * + * @param a first value + * @param b second value + * @return a if a is lesser or equal to b, b otherwise + */ + public static double min(final double a, final double b) { + if (a > b) { + return b; + } + if (a < b) { + return a; + } + /* if either arg is NaN, return NaN */ + if (a != b) { + return Double.NaN; + } + /* min(+0.0,-0.0) == -0.0 */ + /* 0x8000000000000000L == Double.doubleToRawLongBits(-0.0d) */ + long bits = Double.doubleToRawLongBits(a); + if (bits == 0x8000000000000000L) { + return a; + } + return b; + } + + /** + * Compute the maximum of two values + * + * @param a first value + * @param b second value + * @return b if a is lesser or equal to b, a otherwise + */ + public static int max(final int a, final int b) { + return (a <= b) ? b : a; + } + + /** + * Compute the maximum of two values + * + * @param a first value + * @param b second value + * @return b if a is lesser or equal to b, a otherwise + */ + public static long max(final long a, final long b) { + return (a <= b) ? b : a; + } + + /** + * Compute the maximum of two values + * + * @param a first value + * @param b second value + * @return b if a is lesser or equal to b, a otherwise + */ + public static float max(final float a, final float b) { + if (a > b) { + return a; + } + if (a < b) { + return b; + } + /* if either arg is NaN, return NaN */ + if (a != b) { + return Float.NaN; + } + /* min(+0.0,-0.0) == -0.0 */ + /* 0x80000000 == Float.floatToRawIntBits(-0.0d) */ + int bits = Float.floatToRawIntBits(a); + if (bits == 0x80000000) { + return b; + } + return a; + } + + /** + * Compute the maximum of two values + * + * @param a first value + * @param b second value + * @return b if a is lesser or equal to b, a otherwise + */ + public static double max(final double a, final double b) { + if (a > b) { + return a; + } + if (a < b) { + return b; + } + /* if either arg is NaN, return NaN */ + if (a != b) { + return Double.NaN; + } + /* min(+0.0,-0.0) == -0.0 */ + /* 0x8000000000000000L == Double.doubleToRawLongBits(-0.0d) */ + long bits = Double.doubleToRawLongBits(a); + if (bits == 0x8000000000000000L) { + return b; + } + return a; + } + + /** + * Returns the hypotenuse of a triangle with sides {@code x} and {@code y} - + * sqrt(<i>x</i><sup>2</sup> +<i>y</i><sup>2</sup>)<br> + * avoiding intermediate overflow or underflow. + * + * <ul> + * <li>If either argument is infinite, then the result is positive infinity. + * <li>else, if either argument is NaN then the result is NaN. + * </ul> + * + * @param x a value + * @param y a value + * @return sqrt(<i>x</i><sup>2</sup> +<i>y</i><sup>2</sup>) + */ + public static double hypot(final double x, final double y) { + if (Double.isInfinite(x) || Double.isInfinite(y)) { + return Double.POSITIVE_INFINITY; + } else if (Double.isNaN(x) || Double.isNaN(y)) { + return Double.NaN; + } else { + + final int expX = getExponent(x); + final int expY = getExponent(y); + if (expX > expY + 27) { + // y is neglectible with respect to x + return abs(x); + } else if (expY > expX + 27) { + // x is neglectible with respect to y + return abs(y); + } else { + + // find an intermediate scale to avoid both overflow and underflow + final int middleExp = (expX + expY) / 2; + + // scale parameters without losing precision + final double scaledX = scalb(x, -middleExp); + final double scaledY = scalb(y, -middleExp); + + // compute scaled hypotenuse + final double scaledH = sqrt(scaledX * scaledX + scaledY * scaledY); + + // remove scaling + return scalb(scaledH, middleExp); + } + } + } + + /** + * Computes the remainder as prescribed by the IEEE 754 standard. The remainder value is + * mathematically equal to {@code x - y*n} where {@code n} is the mathematical integer closest + * to the exact mathematical value of the quotient {@code x/y}. If two mathematical integers are + * equally close to {@code x/y} then {@code n} is the integer that is even. + * + * <p> + * + * <ul> + * <li>If either operand is NaN, the result is NaN. + * <li>If the result is not NaN, the sign of the result equals the sign of the dividend. + * <li>If the dividend is an infinity, or the divisor is a zero, or both, the result is NaN. + * <li>If the dividend is finite and the divisor is an infinity, the result equals the + * dividend. + * <li>If the dividend is a zero and the divisor is finite, the result equals the dividend. + * </ul> + * + * <p><b>Note:</b> this implementation currently delegates to {@link StrictMath#IEEEremainder} + * + * @param dividend the number to be divided + * @param divisor the number by which to divide + * @return the remainder, rounded + */ + public static double IEEEremainder(double dividend, double divisor) { + return StrictMath.IEEEremainder(dividend, divisor); // TODO provide our own implementation + } + + /** + * Convert a long to interger, detecting overflows + * + * @param n number to convert to int + * @return integer with same valie as n if no overflows occur + * @exception MathArithmeticException if n cannot fit into an int + * @since 3.4 + */ + public static int toIntExact(final long n) throws MathArithmeticException { + if (n < Integer.MIN_VALUE || n > Integer.MAX_VALUE) { + throw new MathArithmeticException(LocalizedFormats.OVERFLOW); + } + return (int) n; + } + + /** + * Increment a number, detecting overflows. + * + * @param n number to increment + * @return n+1 if no overflows occur + * @exception MathArithmeticException if an overflow occurs + * @since 3.4 + */ + public static int incrementExact(final int n) throws MathArithmeticException { + + if (n == Integer.MAX_VALUE) { + throw new MathArithmeticException(LocalizedFormats.OVERFLOW_IN_ADDITION, n, 1); + } + + return n + 1; + } + + /** + * Increment a number, detecting overflows. + * + * @param n number to increment + * @return n+1 if no overflows occur + * @exception MathArithmeticException if an overflow occurs + * @since 3.4 + */ + public static long incrementExact(final long n) throws MathArithmeticException { + + if (n == Long.MAX_VALUE) { + throw new MathArithmeticException(LocalizedFormats.OVERFLOW_IN_ADDITION, n, 1); + } + + return n + 1; + } + + /** + * Decrement a number, detecting overflows. + * + * @param n number to decrement + * @return n-1 if no overflows occur + * @exception MathArithmeticException if an overflow occurs + * @since 3.4 + */ + public static int decrementExact(final int n) throws MathArithmeticException { + + if (n == Integer.MIN_VALUE) { + throw new MathArithmeticException(LocalizedFormats.OVERFLOW_IN_SUBTRACTION, n, 1); + } + + return n - 1; + } + + /** + * Decrement a number, detecting overflows. + * + * @param n number to decrement + * @return n-1 if no overflows occur + * @exception MathArithmeticException if an overflow occurs + * @since 3.4 + */ + public static long decrementExact(final long n) throws MathArithmeticException { + + if (n == Long.MIN_VALUE) { + throw new MathArithmeticException(LocalizedFormats.OVERFLOW_IN_SUBTRACTION, n, 1); + } + + return n - 1; + } + + /** + * Add two numbers, detecting overflows. + * + * @param a first number to add + * @param b second number to add + * @return a+b if no overflows occur + * @exception MathArithmeticException if an overflow occurs + * @since 3.4 + */ + public static int addExact(final int a, final int b) throws MathArithmeticException { + + // compute sum + final int sum = a + b; + + // check for overflow + if ((a ^ b) >= 0 && (sum ^ b) < 0) { + throw new MathArithmeticException(LocalizedFormats.OVERFLOW_IN_ADDITION, a, b); + } + + return sum; + } + + /** + * Add two numbers, detecting overflows. + * + * @param a first number to add + * @param b second number to add + * @return a+b if no overflows occur + * @exception MathArithmeticException if an overflow occurs + * @since 3.4 + */ + public static long addExact(final long a, final long b) throws MathArithmeticException { + + // compute sum + final long sum = a + b; + + // check for overflow + if ((a ^ b) >= 0 && (sum ^ b) < 0) { + throw new MathArithmeticException(LocalizedFormats.OVERFLOW_IN_ADDITION, a, b); + } + + return sum; + } + + /** + * Subtract two numbers, detecting overflows. + * + * @param a first number + * @param b second number to subtract from a + * @return a-b if no overflows occur + * @exception MathArithmeticException if an overflow occurs + * @since 3.4 + */ + public static int subtractExact(final int a, final int b) { + + // compute subtraction + final int sub = a - b; + + // check for overflow + if ((a ^ b) < 0 && (sub ^ b) >= 0) { + throw new MathArithmeticException(LocalizedFormats.OVERFLOW_IN_SUBTRACTION, a, b); + } + + return sub; + } + + /** + * Subtract two numbers, detecting overflows. + * + * @param a first number + * @param b second number to subtract from a + * @return a-b if no overflows occur + * @exception MathArithmeticException if an overflow occurs + * @since 3.4 + */ + public static long subtractExact(final long a, final long b) { + + // compute subtraction + final long sub = a - b; + + // check for overflow + if ((a ^ b) < 0 && (sub ^ b) >= 0) { + throw new MathArithmeticException(LocalizedFormats.OVERFLOW_IN_SUBTRACTION, a, b); + } + + return sub; + } + + /** + * Multiply two numbers, detecting overflows. + * + * @param a first number to multiply + * @param b second number to multiply + * @return a*b if no overflows occur + * @exception MathArithmeticException if an overflow occurs + * @since 3.4 + */ + public static int multiplyExact(final int a, final int b) { + if (((b > 0) && (a > Integer.MAX_VALUE / b || a < Integer.MIN_VALUE / b)) + || ((b < -1) && (a > Integer.MIN_VALUE / b || a < Integer.MAX_VALUE / b)) + || ((b == -1) && (a == Integer.MIN_VALUE))) { + throw new MathArithmeticException(LocalizedFormats.OVERFLOW_IN_MULTIPLICATION, a, b); + } + return a * b; + } + + /** + * Multiply two numbers, detecting overflows. + * + * @param a first number to multiply + * @param b second number to multiply + * @return a*b if no overflows occur + * @exception MathArithmeticException if an overflow occurs + * @since 3.4 + */ + public static long multiplyExact(final long a, final long b) { + if (((b > 0l) && (a > Long.MAX_VALUE / b || a < Long.MIN_VALUE / b)) + || ((b < -1l) && (a > Long.MIN_VALUE / b || a < Long.MAX_VALUE / b)) + || ((b == -1l) && (a == Long.MIN_VALUE))) { + throw new MathArithmeticException(LocalizedFormats.OVERFLOW_IN_MULTIPLICATION, a, b); + } + return a * b; + } + + /** + * Finds q such that a = q b + r with 0 <= r < b if b > 0 and b < r <= 0 if b < 0. + * + * <p>This methods returns the same value as integer division when a and b are same signs, but + * returns a different value when they are opposite (i.e. q is negative). + * + * @param a dividend + * @param b divisor + * @return q such that a = q b + r with 0 <= r < b if b > 0 and b < r <= 0 if b < 0 + * @exception MathArithmeticException if b == 0 + * @see #floorMod(int, int) + * @since 3.4 + */ + public static int floorDiv(final int a, final int b) throws MathArithmeticException { + + if (b == 0) { + throw new MathArithmeticException(LocalizedFormats.ZERO_DENOMINATOR); + } + + final int m = a % b; + if ((a ^ b) >= 0 || m == 0) { + // a an b have same sign, or division is exact + return a / b; + } else { + // a and b have opposite signs and division is not exact + return (a / b) - 1; + } + } + + /** + * Finds q such that a = q b + r with 0 <= r < b if b > 0 and b < r <= 0 if b < 0. + * + * <p>This methods returns the same value as integer division when a and b are same signs, but + * returns a different value when they are opposite (i.e. q is negative). + * + * @param a dividend + * @param b divisor + * @return q such that a = q b + r with 0 <= r < b if b > 0 and b < r <= 0 if b < 0 + * @exception MathArithmeticException if b == 0 + * @see #floorMod(long, long) + * @since 3.4 + */ + public static long floorDiv(final long a, final long b) throws MathArithmeticException { + + if (b == 0l) { + throw new MathArithmeticException(LocalizedFormats.ZERO_DENOMINATOR); + } + + final long m = a % b; + if ((a ^ b) >= 0l || m == 0l) { + // a an b have same sign, or division is exact + return a / b; + } else { + // a and b have opposite signs and division is not exact + return (a / b) - 1l; + } + } + + /** + * Finds r such that a = q b + r with 0 <= r < b if b > 0 and b < r <= 0 if b < 0. + * + * <p>This methods returns the same value as integer modulo when a and b are same signs, but + * returns a different value when they are opposite (i.e. q is negative). + * + * @param a dividend + * @param b divisor + * @return r such that a = q b + r with 0 <= r < b if b > 0 and b < r <= 0 if b < 0 + * @exception MathArithmeticException if b == 0 + * @see #floorDiv(int, int) + * @since 3.4 + */ + public static int floorMod(final int a, final int b) throws MathArithmeticException { + + if (b == 0) { + throw new MathArithmeticException(LocalizedFormats.ZERO_DENOMINATOR); + } + + final int m = a % b; + if ((a ^ b) >= 0 || m == 0) { + // a an b have same sign, or division is exact + return m; + } else { + // a and b have opposite signs and division is not exact + return b + m; + } + } + + /** + * Finds r such that a = q b + r with 0 <= r < b if b > 0 and b < r <= 0 if b < 0. + * + * <p>This methods returns the same value as integer modulo when a and b are same signs, but + * returns a different value when they are opposite (i.e. q is negative). + * + * @param a dividend + * @param b divisor + * @return r such that a = q b + r with 0 <= r < b if b > 0 and b < r <= 0 if b < 0 + * @exception MathArithmeticException if b == 0 + * @see #floorDiv(long, long) + * @since 3.4 + */ + public static long floorMod(final long a, final long b) { + + if (b == 0l) { + throw new MathArithmeticException(LocalizedFormats.ZERO_DENOMINATOR); + } + + final long m = a % b; + if ((a ^ b) >= 0l || m == 0l) { + // a an b have same sign, or division is exact + return m; + } else { + // a and b have opposite signs and division is not exact + return b + m; + } + } + + /** + * Returns the first argument with the sign of the second argument. A NaN {@code sign} argument + * is treated as positive. + * + * @param magnitude the value to return + * @param sign the sign for the returned value + * @return the magnitude with the same sign as the {@code sign} argument + */ + public static double copySign(double magnitude, double sign) { + // The highest order bit is going to be zero if the + // highest order bit of m and s is the same and one otherwise. + // So (m^s) will be positive if both m and s have the same sign + // and negative otherwise. + final long m = Double.doubleToRawLongBits(magnitude); // don't care about NaN + final long s = Double.doubleToRawLongBits(sign); + if ((m ^ s) >= 0) { + return magnitude; + } + return -magnitude; // flip sign + } + + /** + * Returns the first argument with the sign of the second argument. A NaN {@code sign} argument + * is treated as positive. + * + * @param magnitude the value to return + * @param sign the sign for the returned value + * @return the magnitude with the same sign as the {@code sign} argument + */ + public static float copySign(float magnitude, float sign) { + // The highest order bit is going to be zero if the + // highest order bit of m and s is the same and one otherwise. + // So (m^s) will be positive if both m and s have the same sign + // and negative otherwise. + final int m = Float.floatToRawIntBits(magnitude); + final int s = Float.floatToRawIntBits(sign); + if ((m ^ s) >= 0) { + return magnitude; + } + return -magnitude; // flip sign + } + + /** + * Return the exponent of a double number, removing the bias. + * + * <p>For double numbers of the form 2<sup>x</sup>, the unbiased exponent is exactly x. + * + * @param d number from which exponent is requested + * @return exponent for d in IEEE754 representation, without bias + */ + public static int getExponent(final double d) { + // NaN and Infinite will return 1024 anywho so can use raw bits + return (int) ((Double.doubleToRawLongBits(d) >>> 52) & 0x7ff) - 1023; + } + + /** + * Return the exponent of a float number, removing the bias. + * + * <p>For float numbers of the form 2<sup>x</sup>, the unbiased exponent is exactly x. + * + * @param f number from which exponent is requested + * @return exponent for d in IEEE754 representation, without bias + */ + public static int getExponent(final float f) { + // NaN and Infinite will return the same exponent anywho so can use raw bits + return ((Float.floatToRawIntBits(f) >>> 23) & 0xff) - 127; + } + + /** + * Print out contents of arrays, and check the length. + * + * <p>used to generate the preset arrays originally. + * + * @param a unused + */ + public static void main(String[] a) { + PrintStream out = System.out; + FastMathCalc.printarray( + out, "EXP_INT_TABLE_A", EXP_INT_TABLE_LEN, ExpIntTable.EXP_INT_TABLE_A); + FastMathCalc.printarray( + out, "EXP_INT_TABLE_B", EXP_INT_TABLE_LEN, ExpIntTable.EXP_INT_TABLE_B); + FastMathCalc.printarray( + out, "EXP_FRAC_TABLE_A", EXP_FRAC_TABLE_LEN, ExpFracTable.EXP_FRAC_TABLE_A); + FastMathCalc.printarray( + out, "EXP_FRAC_TABLE_B", EXP_FRAC_TABLE_LEN, ExpFracTable.EXP_FRAC_TABLE_B); + FastMathCalc.printarray(out, "LN_MANT", LN_MANT_LEN, lnMant.LN_MANT); + FastMathCalc.printarray(out, "SINE_TABLE_A", SINE_TABLE_LEN, SINE_TABLE_A); + FastMathCalc.printarray(out, "SINE_TABLE_B", SINE_TABLE_LEN, SINE_TABLE_B); + FastMathCalc.printarray(out, "COSINE_TABLE_A", SINE_TABLE_LEN, COSINE_TABLE_A); + FastMathCalc.printarray(out, "COSINE_TABLE_B", SINE_TABLE_LEN, COSINE_TABLE_B); + FastMathCalc.printarray(out, "TANGENT_TABLE_A", SINE_TABLE_LEN, TANGENT_TABLE_A); + FastMathCalc.printarray(out, "TANGENT_TABLE_B", SINE_TABLE_LEN, TANGENT_TABLE_B); + } + + /** Enclose large data table in nested static class so it's only loaded on first access. */ + private static class ExpIntTable { + /** + * Exponential evaluated at integer values, exp(x) = expIntTableA[x + + * EXP_INT_TABLE_MAX_INDEX] + expIntTableB[x+EXP_INT_TABLE_MAX_INDEX]. + */ + private static final double[] EXP_INT_TABLE_A; + + /** + * Exponential evaluated at integer values, exp(x) = expIntTableA[x + + * EXP_INT_TABLE_MAX_INDEX] + expIntTableB[x+EXP_INT_TABLE_MAX_INDEX] + */ + private static final double[] EXP_INT_TABLE_B; + + static { + if (RECOMPUTE_TABLES_AT_RUNTIME) { + EXP_INT_TABLE_A = new double[FastMath.EXP_INT_TABLE_LEN]; + EXP_INT_TABLE_B = new double[FastMath.EXP_INT_TABLE_LEN]; + + final double tmp[] = new double[2]; + final double recip[] = new double[2]; + + // Populate expIntTable + for (int i = 0; i < FastMath.EXP_INT_TABLE_MAX_INDEX; i++) { + FastMathCalc.expint(i, tmp); + EXP_INT_TABLE_A[i + FastMath.EXP_INT_TABLE_MAX_INDEX] = tmp[0]; + EXP_INT_TABLE_B[i + FastMath.EXP_INT_TABLE_MAX_INDEX] = tmp[1]; + + if (i != 0) { + // Negative integer powers + FastMathCalc.splitReciprocal(tmp, recip); + EXP_INT_TABLE_A[FastMath.EXP_INT_TABLE_MAX_INDEX - i] = recip[0]; + EXP_INT_TABLE_B[FastMath.EXP_INT_TABLE_MAX_INDEX - i] = recip[1]; + } + } + } else { + EXP_INT_TABLE_A = FastMathLiteralArrays.loadExpIntA(); + EXP_INT_TABLE_B = FastMathLiteralArrays.loadExpIntB(); + } + } + } + + /** Enclose large data table in nested static class so it's only loaded on first access. */ + private static class ExpFracTable { + /** + * Exponential over the range of 0 - 1 in increments of 2^-10 exp(x/1024) = expFracTableA[x] + * + expFracTableB[x]. 1024 = 2^10 + */ + private static final double[] EXP_FRAC_TABLE_A; + + /** + * Exponential over the range of 0 - 1 in increments of 2^-10 exp(x/1024) = expFracTableA[x] + * + expFracTableB[x]. + */ + private static final double[] EXP_FRAC_TABLE_B; + + static { + if (RECOMPUTE_TABLES_AT_RUNTIME) { + EXP_FRAC_TABLE_A = new double[FastMath.EXP_FRAC_TABLE_LEN]; + EXP_FRAC_TABLE_B = new double[FastMath.EXP_FRAC_TABLE_LEN]; + + final double tmp[] = new double[2]; + + // Populate expFracTable + final double factor = 1d / (EXP_FRAC_TABLE_LEN - 1); + for (int i = 0; i < EXP_FRAC_TABLE_A.length; i++) { + FastMathCalc.slowexp(i * factor, tmp); + EXP_FRAC_TABLE_A[i] = tmp[0]; + EXP_FRAC_TABLE_B[i] = tmp[1]; + } + } else { + EXP_FRAC_TABLE_A = FastMathLiteralArrays.loadExpFracA(); + EXP_FRAC_TABLE_B = FastMathLiteralArrays.loadExpFracB(); + } + } + } + + /** Enclose large data table in nested static class so it's only loaded on first access. */ + private static class lnMant { + /** Extended precision logarithm table over the range 1 - 2 in increments of 2^-10. */ + private static final double[][] LN_MANT; + + static { + if (RECOMPUTE_TABLES_AT_RUNTIME) { + LN_MANT = new double[FastMath.LN_MANT_LEN][]; + + // Populate lnMant table + for (int i = 0; i < LN_MANT.length; i++) { + final double d = + Double.longBitsToDouble((((long) i) << 42) | 0x3ff0000000000000L); + LN_MANT[i] = FastMathCalc.slowLog(d); + } + } else { + LN_MANT = FastMathLiteralArrays.loadLnMant(); + } + } + } + + /** Enclose the Cody/Waite reduction (used in "sin", "cos" and "tan"). */ + private static class CodyWaite { + /** k */ + private final int finalK; + + /** remA */ + private final double finalRemA; + + /** remB */ + private final double finalRemB; + + /** + * @param xa Argument. + */ + CodyWaite(double xa) { + // Estimate k. + // k = (int)(xa / 1.5707963267948966); + int k = (int) (xa * 0.6366197723675814); + + // Compute remainder. + double remA; + double remB; + while (true) { + double a = -k * 1.570796251296997; + remA = xa + a; + remB = -(remA - xa - a); + + a = -k * 7.549789948768648E-8; + double b = remA; + remA = a + b; + remB += -(remA - b - a); + + a = -k * 6.123233995736766E-17; + b = remA; + remA = a + b; + remB += -(remA - b - a); + + if (remA > 0) { + break; + } + + // Remainder is negative, so decrement k and try again. + // This should only happen if the input is very close + // to an even multiple of pi/2. + --k; + } + + this.finalK = k; + this.finalRemA = remA; + this.finalRemB = remB; + } + + /** + * @return k + */ + int getK() { + return finalK; + } + + /** + * @return remA + */ + double getRemA() { + return finalRemA; + } + + /** + * @return remB + */ + double getRemB() { + return finalRemB; + } + } +} diff --git a/src/main/java/org/apache/commons/math3/util/FastMathCalc.java b/src/main/java/org/apache/commons/math3/util/FastMathCalc.java new file mode 100644 index 0000000..cf0f27c --- /dev/null +++ b/src/main/java/org/apache/commons/math3/util/FastMathCalc.java @@ -0,0 +1,678 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math3.util; + +import org.apache.commons.math3.exception.DimensionMismatchException; + +import java.io.PrintStream; + +/** + * Class used to compute the classical functions tables. + * + * @since 3.0 + */ +class FastMathCalc { + + /** + * 0x40000000 - used to split a double into two parts, both with the low order bits cleared. + * Equivalent to 2^30. + */ + private static final long HEX_40000000 = 0x40000000L; // 1073741824L + + /** Factorial table, for Taylor series expansions. 0!, 1!, 2!, ... 19! */ + private static final double FACT[] = + new double[] { + +1.0d, // 0 + +1.0d, // 1 + +2.0d, // 2 + +6.0d, // 3 + +24.0d, // 4 + +120.0d, // 5 + +720.0d, // 6 + +5040.0d, // 7 + +40320.0d, // 8 + +362880.0d, // 9 + +3628800.0d, // 10 + +39916800.0d, // 11 + +479001600.0d, // 12 + +6227020800.0d, // 13 + +87178291200.0d, // 14 + +1307674368000.0d, // 15 + +20922789888000.0d, // 16 + +355687428096000.0d, // 17 + +6402373705728000.0d, // 18 + +121645100408832000.0d, // 19 + }; + + /** Coefficients for slowLog. */ + private static final double LN_SPLIT_COEF[][] = { + {2.0, 0.0}, + {0.6666666269302368, 3.9736429850260626E-8}, + {0.3999999761581421, 2.3841857910019882E-8}, + {0.2857142686843872, 1.7029898543501842E-8}, + {0.2222222089767456, 1.3245471311735498E-8}, + {0.1818181574344635, 2.4384203044354907E-8}, + {0.1538461446762085, 9.140260083262505E-9}, + {0.13333332538604736, 9.220590270857665E-9}, + {0.11764700710773468, 1.2393345855018391E-8}, + {0.10526403784751892, 8.251545029714408E-9}, + {0.0952233225107193, 1.2675934823758863E-8}, + {0.08713622391223907, 1.1430250008909141E-8}, + {0.07842259109020233, 2.404307984052299E-9}, + {0.08371849358081818, 1.176342548272881E-8}, + {0.030589580535888672, 1.2958646899018938E-9}, + {0.14982303977012634, 1.225743062930824E-8}, + }; + + /** Table start declaration. */ + private static final String TABLE_START_DECL = " {"; + + /** Table end declaration. */ + private static final String TABLE_END_DECL = " };"; + + /** Private Constructor. */ + private FastMathCalc() {} + + /** + * Build the sine and cosine tables. + * + * @param SINE_TABLE_A table of the most significant part of the sines + * @param SINE_TABLE_B table of the least significant part of the sines + * @param COSINE_TABLE_A table of the most significant part of the cosines + * @param COSINE_TABLE_B table of the most significant part of the cosines + * @param SINE_TABLE_LEN length of the tables + * @param TANGENT_TABLE_A table of the most significant part of the tangents + * @param TANGENT_TABLE_B table of the most significant part of the tangents + */ + @SuppressWarnings("unused") + private static void buildSinCosTables( + double[] SINE_TABLE_A, + double[] SINE_TABLE_B, + double[] COSINE_TABLE_A, + double[] COSINE_TABLE_B, + int SINE_TABLE_LEN, + double[] TANGENT_TABLE_A, + double[] TANGENT_TABLE_B) { + final double result[] = new double[2]; + + /* Use taylor series for 0 <= x <= 6/8 */ + for (int i = 0; i < 7; i++) { + double x = i / 8.0; + + slowSin(x, result); + SINE_TABLE_A[i] = result[0]; + SINE_TABLE_B[i] = result[1]; + + slowCos(x, result); + COSINE_TABLE_A[i] = result[0]; + COSINE_TABLE_B[i] = result[1]; + } + + /* Use angle addition formula to complete table to 13/8, just beyond pi/2 */ + for (int i = 7; i < SINE_TABLE_LEN; i++) { + double xs[] = new double[2]; + double ys[] = new double[2]; + double as[] = new double[2]; + double bs[] = new double[2]; + double temps[] = new double[2]; + + if ((i & 1) == 0) { + // Even, use double angle + xs[0] = SINE_TABLE_A[i / 2]; + xs[1] = SINE_TABLE_B[i / 2]; + ys[0] = COSINE_TABLE_A[i / 2]; + ys[1] = COSINE_TABLE_B[i / 2]; + + /* compute sine */ + splitMult(xs, ys, result); + SINE_TABLE_A[i] = result[0] * 2.0; + SINE_TABLE_B[i] = result[1] * 2.0; + + /* Compute cosine */ + splitMult(ys, ys, as); + splitMult(xs, xs, temps); + temps[0] = -temps[0]; + temps[1] = -temps[1]; + splitAdd(as, temps, result); + COSINE_TABLE_A[i] = result[0]; + COSINE_TABLE_B[i] = result[1]; + } else { + xs[0] = SINE_TABLE_A[i / 2]; + xs[1] = SINE_TABLE_B[i / 2]; + ys[0] = COSINE_TABLE_A[i / 2]; + ys[1] = COSINE_TABLE_B[i / 2]; + as[0] = SINE_TABLE_A[i / 2 + 1]; + as[1] = SINE_TABLE_B[i / 2 + 1]; + bs[0] = COSINE_TABLE_A[i / 2 + 1]; + bs[1] = COSINE_TABLE_B[i / 2 + 1]; + + /* compute sine */ + splitMult(xs, bs, temps); + splitMult(ys, as, result); + splitAdd(result, temps, result); + SINE_TABLE_A[i] = result[0]; + SINE_TABLE_B[i] = result[1]; + + /* Compute cosine */ + splitMult(ys, bs, result); + splitMult(xs, as, temps); + temps[0] = -temps[0]; + temps[1] = -temps[1]; + splitAdd(result, temps, result); + COSINE_TABLE_A[i] = result[0]; + COSINE_TABLE_B[i] = result[1]; + } + } + + /* Compute tangent = sine/cosine */ + for (int i = 0; i < SINE_TABLE_LEN; i++) { + double xs[] = new double[2]; + double ys[] = new double[2]; + double as[] = new double[2]; + + as[0] = COSINE_TABLE_A[i]; + as[1] = COSINE_TABLE_B[i]; + + splitReciprocal(as, ys); + + xs[0] = SINE_TABLE_A[i]; + xs[1] = SINE_TABLE_B[i]; + + splitMult(xs, ys, as); + + TANGENT_TABLE_A[i] = as[0]; + TANGENT_TABLE_B[i] = as[1]; + } + } + + /** + * For x between 0 and pi/4 compute cosine using Talor series cos(x) = 1 - x^2/2! + x^4/4! ... + * + * @param x number from which cosine is requested + * @param result placeholder where to put the result in extended precision (may be null) + * @return cos(x) + */ + static double slowCos(final double x, final double result[]) { + + final double xs[] = new double[2]; + final double ys[] = new double[2]; + final double facts[] = new double[2]; + final double as[] = new double[2]; + split(x, xs); + ys[0] = ys[1] = 0.0; + + for (int i = FACT.length - 1; i >= 0; i--) { + splitMult(xs, ys, as); + ys[0] = as[0]; + ys[1] = as[1]; + + if ((i & 1) != 0) { // skip odd entries + continue; + } + + split(FACT[i], as); + splitReciprocal(as, facts); + + if ((i & 2) != 0) { // alternate terms are negative + facts[0] = -facts[0]; + facts[1] = -facts[1]; + } + + splitAdd(ys, facts, as); + ys[0] = as[0]; + ys[1] = as[1]; + } + + if (result != null) { + result[0] = ys[0]; + result[1] = ys[1]; + } + + return ys[0] + ys[1]; + } + + /** + * For x between 0 and pi/4 compute sine using Taylor expansion: sin(x) = x - x^3/3! + x^5/5! - + * x^7/7! ... + * + * @param x number from which sine is requested + * @param result placeholder where to put the result in extended precision (may be null) + * @return sin(x) + */ + static double slowSin(final double x, final double result[]) { + final double xs[] = new double[2]; + final double ys[] = new double[2]; + final double facts[] = new double[2]; + final double as[] = new double[2]; + split(x, xs); + ys[0] = ys[1] = 0.0; + + for (int i = FACT.length - 1; i >= 0; i--) { + splitMult(xs, ys, as); + ys[0] = as[0]; + ys[1] = as[1]; + + if ((i & 1) == 0) { // Ignore even numbers + continue; + } + + split(FACT[i], as); + splitReciprocal(as, facts); + + if ((i & 2) != 0) { // alternate terms are negative + facts[0] = -facts[0]; + facts[1] = -facts[1]; + } + + splitAdd(ys, facts, as); + ys[0] = as[0]; + ys[1] = as[1]; + } + + if (result != null) { + result[0] = ys[0]; + result[1] = ys[1]; + } + + return ys[0] + ys[1]; + } + + /** + * For x between 0 and 1, returns exp(x), uses extended precision + * + * @param x argument of exponential + * @param result placeholder where to place exp(x) split in two terms for extra precision (i.e. + * exp(x) = result[0] + result[1] + * @return exp(x) + */ + static double slowexp(final double x, final double result[]) { + final double xs[] = new double[2]; + final double ys[] = new double[2]; + final double facts[] = new double[2]; + final double as[] = new double[2]; + split(x, xs); + ys[0] = ys[1] = 0.0; + + for (int i = FACT.length - 1; i >= 0; i--) { + splitMult(xs, ys, as); + ys[0] = as[0]; + ys[1] = as[1]; + + split(FACT[i], as); + splitReciprocal(as, facts); + + splitAdd(ys, facts, as); + ys[0] = as[0]; + ys[1] = as[1]; + } + + if (result != null) { + result[0] = ys[0]; + result[1] = ys[1]; + } + + return ys[0] + ys[1]; + } + + /** + * Compute split[0], split[1] such that their sum is equal to d, and split[0] has its 30 least + * significant bits as zero. + * + * @param d number to split + * @param split placeholder where to place the result + */ + private static void split(final double d, final double split[]) { + if (d < 8e298 && d > -8e298) { + final double a = d * HEX_40000000; + split[0] = (d + a) - a; + split[1] = d - split[0]; + } else { + final double a = d * 9.31322574615478515625E-10; + split[0] = (d + a - d) * HEX_40000000; + split[1] = d - split[0]; + } + } + + /** + * Recompute a split. + * + * @param a input/out array containing the split, changed on output + */ + private static void resplit(final double a[]) { + final double c = a[0] + a[1]; + final double d = -(c - a[0] - a[1]); + + if (c < 8e298 && c > -8e298) { // MAGIC NUMBER + double z = c * HEX_40000000; + a[0] = (c + z) - z; + a[1] = c - a[0] + d; + } else { + double z = c * 9.31322574615478515625E-10; + a[0] = (c + z - c) * HEX_40000000; + a[1] = c - a[0] + d; + } + } + + /** + * Multiply two numbers in split form. + * + * @param a first term of multiplication + * @param b second term of multiplication + * @param ans placeholder where to put the result + */ + private static void splitMult(double a[], double b[], double ans[]) { + ans[0] = a[0] * b[0]; + ans[1] = a[0] * b[1] + a[1] * b[0] + a[1] * b[1]; + + /* Resplit */ + resplit(ans); + } + + /** + * Add two numbers in split form. + * + * @param a first term of addition + * @param b second term of addition + * @param ans placeholder where to put the result + */ + private static void splitAdd(final double a[], final double b[], final double ans[]) { + ans[0] = a[0] + b[0]; + ans[1] = a[1] + b[1]; + + resplit(ans); + } + + /** + * Compute the reciprocal of in. Use the following algorithm. in = c + d. want to find x + y + * such that x+y = 1/(c+d) and x is much larger than y and x has several zero bits on the right. + * + * <p>Set b = 1/(2^22), a = 1 - b. Thus (a+b) = 1. Use following identity to compute (a+b)/(c+d) + * + * <p>(a+b)/(c+d) = a/c + (bc - ad) / (c^2 + cd) set x = a/c and y = (bc - ad) / (c^2 + cd) This + * will be close to the right answer, but there will be some rounding in the calculation of X. + * So by carefully computing 1 - (c+d)(x+y) we can compute an error and add that back in. This + * is done carefully so that terms of similar size are subtracted first. + * + * @param in initial number, in split form + * @param result placeholder where to put the result + */ + static void splitReciprocal(final double in[], final double result[]) { + final double b = 1.0 / 4194304.0; + final double a = 1.0 - b; + + if (in[0] == 0.0) { + in[0] = in[1]; + in[1] = 0.0; + } + + result[0] = a / in[0]; + result[1] = (b * in[0] - a * in[1]) / (in[0] * in[0] + in[0] * in[1]); + + if (result[1] != result[1]) { // can happen if result[1] is NAN + result[1] = 0.0; + } + + /* Resplit */ + resplit(result); + + for (int i = 0; i < 2; i++) { + /* this may be overkill, probably once is enough */ + double err = + 1.0 + - result[0] * in[0] + - result[0] * in[1] + - result[1] * in[0] + - result[1] * in[1]; + /*err = 1.0 - err; */ + err *= result[0] + result[1]; + /*printf("err = %16e\n", err); */ + result[1] += err; + } + } + + /** + * Compute (a[0] + a[1]) * (b[0] + b[1]) in extended precision. + * + * @param a first term of the multiplication + * @param b second term of the multiplication + * @param result placeholder where to put the result + */ + private static void quadMult(final double a[], final double b[], final double result[]) { + final double xs[] = new double[2]; + final double ys[] = new double[2]; + final double zs[] = new double[2]; + + /* a[0] * b[0] */ + split(a[0], xs); + split(b[0], ys); + splitMult(xs, ys, zs); + + result[0] = zs[0]; + result[1] = zs[1]; + + /* a[0] * b[1] */ + split(b[1], ys); + splitMult(xs, ys, zs); + + double tmp = result[0] + zs[0]; + result[1] -= tmp - result[0] - zs[0]; + result[0] = tmp; + tmp = result[0] + zs[1]; + result[1] -= tmp - result[0] - zs[1]; + result[0] = tmp; + + /* a[1] * b[0] */ + split(a[1], xs); + split(b[0], ys); + splitMult(xs, ys, zs); + + tmp = result[0] + zs[0]; + result[1] -= tmp - result[0] - zs[0]; + result[0] = tmp; + tmp = result[0] + zs[1]; + result[1] -= tmp - result[0] - zs[1]; + result[0] = tmp; + + /* a[1] * b[0] */ + split(a[1], xs); + split(b[1], ys); + splitMult(xs, ys, zs); + + tmp = result[0] + zs[0]; + result[1] -= tmp - result[0] - zs[0]; + result[0] = tmp; + tmp = result[0] + zs[1]; + result[1] -= tmp - result[0] - zs[1]; + result[0] = tmp; + } + + /** + * Compute exp(p) for a integer p in extended precision. + * + * @param p integer whose exponential is requested + * @param result placeholder where to put the result in extended precision + * @return exp(p) in standard precision (equal to result[0] + result[1]) + */ + static double expint(int p, final double result[]) { + // double x = M_E; + final double xs[] = new double[2]; + final double as[] = new double[2]; + final double ys[] = new double[2]; + // split(x, xs); + // xs[1] = (double)(2.7182818284590452353602874713526625L - xs[0]); + // xs[0] = 2.71827697753906250000; + // xs[1] = 4.85091998273542816811e-06; + // xs[0] = Double.longBitsToDouble(0x4005bf0800000000L); + // xs[1] = Double.longBitsToDouble(0x3ed458a2bb4a9b00L); + + /* E */ + xs[0] = 2.718281828459045; + xs[1] = 1.4456468917292502E-16; + + split(1.0, ys); + + while (p > 0) { + if ((p & 1) != 0) { + quadMult(ys, xs, as); + ys[0] = as[0]; + ys[1] = as[1]; + } + + quadMult(xs, xs, as); + xs[0] = as[0]; + xs[1] = as[1]; + + p >>= 1; + } + + if (result != null) { + result[0] = ys[0]; + result[1] = ys[1]; + + resplit(result); + } + + return ys[0] + ys[1]; + } + + /** + * xi in the range of [1, 2]. 3 5 7 x+1 / x x x \ ln ----- = 2 * | x + ---- + ---- + ---- + ... + * | 1-x \ 3 5 7 / + * + * <p>So, compute a Remez approximation of the following function + * + * <p>ln ((sqrt(x)+1)/(1-sqrt(x))) / x + * + * <p>This will be an even function with only positive coefficents. x is in the range [0 - 1/3]. + * + * <p>Transform xi for input to the above function by setting x = (xi-1)/(xi+1). Input to the + * polynomial is x^2, then the result is multiplied by x. + * + * @param xi number from which log is requested + * @return log(xi) + */ + static double[] slowLog(double xi) { + double x[] = new double[2]; + double x2[] = new double[2]; + double y[] = new double[2]; + double a[] = new double[2]; + + split(xi, x); + + /* Set X = (x-1)/(x+1) */ + x[0] += 1.0; + resplit(x); + splitReciprocal(x, a); + x[0] -= 2.0; + resplit(x); + splitMult(x, a, y); + x[0] = y[0]; + x[1] = y[1]; + + /* Square X -> X2*/ + splitMult(x, x, x2); + + // x[0] -= 1.0; + // resplit(x); + + y[0] = LN_SPLIT_COEF[LN_SPLIT_COEF.length - 1][0]; + y[1] = LN_SPLIT_COEF[LN_SPLIT_COEF.length - 1][1]; + + for (int i = LN_SPLIT_COEF.length - 2; i >= 0; i--) { + splitMult(y, x2, a); + y[0] = a[0]; + y[1] = a[1]; + splitAdd(y, LN_SPLIT_COEF[i], a); + y[0] = a[0]; + y[1] = a[1]; + } + + splitMult(y, x, a); + y[0] = a[0]; + y[1] = a[1]; + + return y; + } + + /** + * Print an array. + * + * @param out text output stream where output should be printed + * @param name array name + * @param expectedLen expected length of the array + * @param array2d array data + */ + static void printarray(PrintStream out, String name, int expectedLen, double[][] array2d) { + out.println(name); + checkLen(expectedLen, array2d.length); + out.println(TABLE_START_DECL + " "); + int i = 0; + for (double[] array : array2d) { // "double array[]" causes PMD parsing error + out.print(" {"); + for (double d : array) { // assume inner array has very few entries + out.printf("%-25.25s", format(d)); // multiple entries per line + } + out.println("}, // " + i++); + } + out.println(TABLE_END_DECL); + } + + /** + * Print an array. + * + * @param out text output stream where output should be printed + * @param name array name + * @param expectedLen expected length of the array + * @param array array data + */ + static void printarray(PrintStream out, String name, int expectedLen, double[] array) { + out.println(name + "="); + checkLen(expectedLen, array.length); + out.println(TABLE_START_DECL); + for (double d : array) { + out.printf(" %s%n", format(d)); // one entry per line + } + out.println(TABLE_END_DECL); + } + + /** + * Format a double. + * + * @param d double number to format + * @return formatted number + */ + static String format(double d) { + if (d != d) { + return "Double.NaN,"; + } else { + return ((d >= 0) ? "+" : "") + Double.toString(d) + "d,"; + } + } + + /** + * Check two lengths are equal. + * + * @param expectedLen expected length + * @param actual actual length + * @exception DimensionMismatchException if the two lengths are not equal + */ + private static void checkLen(int expectedLen, int actual) throws DimensionMismatchException { + if (expectedLen != actual) { + throw new DimensionMismatchException(actual, expectedLen); + } + } +} diff --git a/src/main/java/org/apache/commons/math3/util/FastMathLiteralArrays.java b/src/main/java/org/apache/commons/math3/util/FastMathLiteralArrays.java new file mode 100644 index 0000000..1092b32 --- /dev/null +++ b/src/main/java/org/apache/commons/math3/util/FastMathLiteralArrays.java @@ -0,0 +1,8228 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.math3.util; + +/** Utility class for loading tabulated data used by {@link FastMath}. */ +class FastMathLiteralArrays { + /** + * Exponential evaluated at integer values, exp(x) = expIntTableA[x + EXP_INT_TABLE_MAX_INDEX] + + * expIntTableB[x+EXP_INT_TABLE_MAX_INDEX]. + */ + private static final double[] EXP_INT_A = + new double[] { + +0.0d, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + +1.2167807682331913E-308d, + +3.3075532478807267E-308d, + +8.990862214387203E-308d, + +2.4439696075216986E-307d, + +6.64339758024534E-307d, + +1.8058628951432254E-306d, + +4.908843759498681E-306d, + +1.334362017065677E-305d, + +3.627172425759641E-305d, + +9.85967600992008E-305d, + +2.680137967689915E-304d, + +7.285370725133842E-304d, + +1.9803689272433392E-303d, + +5.3832011494782624E-303d, + +1.463305638201413E-302d, + +3.9776772027043775E-302d, + +1.0812448255518705E-301d, + +2.9391280956327795E-301d, + +7.989378677301346E-301d, + +2.1717383041010577E-300d, + +5.903396499766243E-300d, + +1.604709595901607E-299d, + +4.3620527352131126E-299d, + +1.1857289715706991E-298d, + +3.2231452986239366E-298d, + +8.761416875971053E-298d, + +2.381600167287677E-297d, + +6.473860152384321E-297d, + +1.7597776278732318E-296d, + +4.7835721669653157E-296d, + +1.3003096668152053E-295d, + +3.5346080979652066E-295d, + +9.608060944124859E-295d, + +2.6117415961302846E-294d, + +7.099449830809996E-294d, + +1.9298305829106006E-293d, + +5.245823134132673E-293d, + +1.4259627797225802E-292d, + +3.8761686729764145E-292d, + +1.0536518897078156E-291d, + +2.864122672853628E-291d, + +7.785491934690374E-291d, + +2.116316283183901E-290d, + +5.7527436249968E-290d, + +1.5637579898345352E-289d, + +4.250734424415339E-289d, + +1.1554696041977512E-288d, + +3.1408919441362495E-288d, + +8.537829238438662E-288d, + +2.320822576772103E-287d, + +6.308649765138419E-287d, + +1.7148689119310826E-286d, + +4.66149719271323E-286d, + +1.267126226441217E-285d, + +3.444406231880653E-285d, + +9.362866914115166E-285d, + +2.5450911557068313E-284d, + +6.918275021321188E-284d, + +1.880582039589629E-283d, + +5.111952261540649E-283d, + +1.3895726688907995E-282d, + +3.7772500667438066E-282d, + +1.026763015362553E-281d, + +2.791031173360063E-281d, + +7.586808748646825E-281d, + +2.0623086887184633E-280d, + +5.605936171588964E-280d, + +1.5238514098804918E-279d, + +4.1422578754033235E-279d, + +1.1259823210174452E-278d, + +3.060737220976933E-278d, + +8.319947089683576E-278d, + +2.2615958035357106E-277d, + +6.147655179898435E-277d, + +1.6711060014400145E-276d, + +4.542536646012133E-276d, + +1.2347896500246374E-275d, + +3.3565057475434694E-275d, + +9.123929070778758E-275d, + +2.4801413921885483E-274d, + +6.741722283079056E-274d, + +1.8325902719086093E-273d, + +4.981496462621207E-273d, + +1.3541112064618357E-272d, + +3.68085620656127E-272d, + +1.0005602916630382E-271d, + +2.719805132368625E-271d, + +7.393196131284108E-271d, + +2.0096791226867E-270d, + +5.462874707256208E-270d, + +1.4849631831943512E-269d, + +4.036548930895323E-269d, + +1.0972476870931676E-268d, + +2.9826282194717127E-268d, + +8.107624153838987E-268d, + +2.2038806519542315E-267d, + +5.990769236615968E-267d, + +1.628459873440512E-266d, + +4.4266130556431266E-266d, + +1.203278237867575E-265d, + +3.270849446965521E-265d, + +8.891090288030614E-265d, + +2.4168487931443637E-264d, + +6.569676185250389E-264d, + +1.7858231429575898E-263d, + +4.85437090269903E-263d, + +1.3195548295785448E-262d, + +3.5869215528816054E-262d, + +9.750264097807267E-262d, + +2.650396454019762E-261d, + +7.204525142098426E-261d, + +1.958392846081373E-260d, + +5.32346341339996E-260d, + +1.4470673509275515E-259d, + +3.9335373658569176E-259d, + +1.0692462289051038E-258d, + +2.9065128598079075E-258d, + +7.900720862969045E-258d, + +2.147638465376883E-257d, + +5.8378869339035456E-257d, + +1.5869022483809747E-256d, + +4.3136475849391444E-256d, + +1.1725710340687719E-255d, + +3.1873780814410126E-255d, + +8.66419234315257E-255d, + +2.35517168886351E-254d, + +6.402020300783889E-254d, + +1.740249660600677E-253d, + +4.7304887145310405E-253d, + +1.2858802448614707E-252d, + +3.495384792953975E-252d, + +9.501439740542955E-252d, + +2.582759362004277E-251d, + +7.020668578160457E-251d, + +1.908415302517694E-250d, + +5.1876107490791666E-250d, + +1.4101386971763257E-249d, + +3.8331545111676784E-249d, + +1.0419594359065132E-248d, + +2.8323395451363237E-248d, + +7.699097067385825E-248d, + +2.0928317096428755E-247d, + +5.688906371296133E-247d, + +1.5464049837965422E-246d, + +4.2035646586788297E-246d, + +1.1426473877336358E-245d, + +3.106037603716254E-245d, + +8.443084996839363E-245d, + +2.2950686306677644E-244d, + +6.238642390386363E-244d, + +1.695838923802857E-243d, + +4.6097680405580995E-243d, + +1.2530649392922358E-242d, + +3.4061835424180075E-242d, + +9.25896798127602E-242d, + +2.5168480541429286E-241d, + +6.841502859109196E-241d, + +1.8597132378953187E-240d, + +5.055224959032211E-240d, + +1.374152583940637E-239d, + +3.735333866258403E-239d, + +1.0153690688015855E-238d, + +2.7600590782738726E-238d, + +7.502618487550056E-238d, + +2.0394233446495043E-237d, + +5.543727690168612E-237d, + +1.5069412868172555E-236d, + +4.0962906236847E-236d, + +1.1134873918971586E-235d, + +3.026772467749944E-235d, + +8.227620163729258E-235d, + +2.2364990583200056E-234d, + +6.079434951446575E-234d, + +1.6525617499662284E-233d, + +4.4921289690525345E-233d, + +1.2210872189854344E-232d, + +3.3192593301633E-232d, + +9.02268127425393E-232d, + +2.4526190464373087E-231d, + +6.666909874218774E-231d, + +1.8122539547625083E-230d, + +4.926216840507529E-230d, + +1.3390847149416908E-229d, + +3.6400093808551196E-229d, + +9.894571625944288E-229d, + +2.689623698321582E-228d, + +7.31115423069187E-228d, + +1.9873779569310022E-227d, + +5.402252865260326E-227d, + +1.4684846983789053E-226d, + +3.991755413823315E-226d, + +1.0850715739509136E-225d, + +2.9495302004590423E-225d, + +8.017654713159388E-225d, + +2.179424521221378E-224d, + +5.924290380648597E-224d, + +1.6103890140790331E-223d, + +4.377491272857675E-223d, + +1.1899254154663847E-222d, + +3.2345523990372546E-222d, + +8.792425221770645E-222d, + +2.3900289095512176E-221d, + +6.496772856703278E-221d, + +1.7660059778220905E-220d, + +4.800501435803201E-220d, + +1.3049116216750674E-219d, + +3.5471180281159325E-219d, + +9.642065709892252E-219d, + +2.6209850274990846E-218d, + +7.124574366530717E-218d, + +1.9366601417010147E-217d, + +5.264388476949737E-217d, + +1.431009021985696E-216d, + +3.889885799962507E-216d, + +1.057380684430436E-215d, + +2.8742587656021775E-215d, + +7.813044552050569E-215d, + +2.1238058974550874E-214d, + +5.773102661099307E-214d, + +1.5692921723471877E-213d, + +4.2657777816050375E-213d, + +1.1595585743839232E-212d, + +3.1520070828798975E-212d, + +8.568043768122183E-212d, + +2.329035966595791E-211d, + +6.33097561889469E-211d, + +1.720937714565362E-210d, + +4.677993239821998E-210d, + +1.2716105485691878E-209d, + +3.456595573934475E-209d, + +9.396000024637834E-209d, + +2.55409795397022E-208d, + +6.942757623821567E-208d, + +1.887237361505784E-207d, + +5.13004286606108E-207d, + +1.3944901709366118E-206d, + +3.7906173667738715E-206d, + +1.0303966192973381E-205d, + +2.8009086220877197E-205d, + +7.613657850210907E-205d, + +2.0696069842597556E-204d, + +5.6257755605305175E-204d, + +1.5292444435954893E-203d, + +4.156916476922876E-203d, + +1.12996721591364E-202d, + +3.071569248856111E-202d, + +8.349390727162016E-202d, + +2.2695999828608633E-201d, + +6.1694117899971836E-201d, + +1.677020107827128E-200d, + +4.558612479525779E-200d, + +1.2391595516612638E-199d, + +3.3683846288580648E-199d, + +9.156218120779494E-199d, + +2.4889182184335247E-198d, + +6.765580431441772E-198d, + +1.839075686473352E-197d, + +4.999126524757713E-197d, + +1.3589033107846643E-196d, + +3.6938826366068014E-196d, + +1.0041012794280992E-195d, + +2.7294301888986675E-195d, + +7.419361045185406E-195d, + +2.016791373353671E-194d, + +5.482208065983983E-194d, + +1.490218341008089E-193d, + +4.050833763855709E-193d, + +1.101130773265179E-192d, + +2.993183789477209E-192d, + +8.136316299122392E-192d, + +2.2116799789922265E-191d, + +6.011969568315371E-191d, + +1.6342228966392253E-190d, + +4.4422779589171113E-190d, + +1.2075364784547675E-189d, + +3.282424571107068E-189d, + +8.92255448602772E-189d, + +2.425402115319395E-188d, + +6.592926904915355E-188d, + +1.79214305133496E-187d, + +4.871550528055661E-187d, + +1.3242245776666673E-186d, + +3.599615946028287E-186d, + +9.78476998200719E-186d, + +2.659776075359514E-185d, + +7.230020851688713E-185d, + +1.9653234116333892E-184d, + +5.34230278107224E-184d, + +1.4521887058451231E-183d, + +3.947457923821984E-183d, + +1.0730302255093144E-182d, + +2.9167986204137332E-182d, + +7.928680793406766E-182d, + +2.1552386987482013E-181d, + +5.858546779607288E-181d, + +1.5925182066949723E-180d, + +4.328913614497258E-180d, + +1.1767205227552116E-179d, + +3.198658219194836E-179d, + +8.694853785564504E-179d, + +2.363506255864984E-178d, + +6.42467573615509E-178d, + +1.746408207555959E-177d, + +4.747229597770176E-177d, + +1.2904307529671472E-176d, + +3.507754341050756E-176d, + +9.535066345267336E-176d, + +2.591899541396432E-175d, + +7.045512786902009E-175d, + +1.9151693415969248E-174d, + +5.205969622575851E-174d, + +1.4151292367806538E-173d, + +3.846720258072078E-173d, + +1.045647032279984E-172d, + +2.8423629805010285E-172d, + +7.726344058192276E-172d, + +2.1002377128928765E-171d, + +5.709039546124285E-171d, + +1.5518778128928824E-170d, + +4.218440703602533E-170d, + +1.1466910691560932E-169d, + +3.1170298734336303E-169d, + +8.472965161251656E-169d, + +2.303190374523956E-168d, + +6.260720440258473E-168d, + +1.701840523821621E-167d, + +4.62608152166211E-167d, + +1.2574995962791943E-166d, + +3.418237608335161E-166d, + +9.29173407843235E-166d, + +2.5257552661512635E-165d, + +6.865714679174435E-165d, + +1.866294830116931E-164d, + +5.073114566291778E-164d, + +1.3790154522394582E-163d, + +3.7485528226129495E-163d, + +1.0189624503698769E-162d, + +2.7698267293941856E-162d, + +7.529170882336924E-162d, + +2.0466404088178596E-161d, + +5.56334611651382E-161d, + +1.512274346576166E-160d, + +4.110787043867721E-160d, + +1.1174279267498045E-159d, + +3.0374839443564585E-159d, + +8.25673801176584E-159d, + +2.244414150254963E-158d, + +6.1009492034592176E-158d, + +1.6584100275603453E-157d, + +4.50802633729044E-157d, + +1.2254085656601853E-156d, + +3.3310057014599044E-156d, + +9.054612259832416E-156d, + +2.4612985502035675E-155d, + +6.690503835950083E-155d, + +1.8186679660152888E-154d, + +4.9436516047443576E-154d, + +1.3438240331106108E-153d, + +3.652892398145774E-153d, + +9.92958982547828E-153d, + +2.6991427376823027E-152d, + +7.3370297995122135E-152d, + +1.994411660450821E-151d, + +5.421372463189529E-151d, + +1.4736818914204564E-150d, + +4.005882964287806E-150d, + +1.088911919926534E-149d, + +2.9599693109692324E-149d, + +8.046030012041041E-149d, + +2.18713790898745E-148d, + +5.945256705384597E-148d, + +1.6160884846515524E-147d, + +4.392983574030969E-147d, + +1.1941366764543551E-146d, + +3.2460001983475855E-146d, + +8.8235440586675E-146d, + +2.3984878190403553E-145d, + +6.519765758635405E-145d, + +1.772256261139753E-144d, + +4.817491674217065E-144d, + +1.3095299991573769E-143d, + +3.559671483107555E-143d, + +9.676190774054103E-143d, + +2.630261301303634E-142d, + +7.149792225695347E-142d, + +1.943514969662872E-141d, + +5.283020542151163E-141d, + +1.4360739330834996E-140d, + +3.9036541111764032E-140d, + +1.0611230602364477E-139d, + +2.8844319473099593E-139d, + +7.84069876400596E-139d, + +2.1313228444765414E-138d, + +5.793536445518422E-138d, + +1.5748463788034308E-137d, + +4.2808762411845363E-137d, + +1.1636629220608724E-136d, + +3.163163464591171E-136d, + +8.598369704466743E-136d, + +2.337279322276433E-135d, + +6.353384093665193E-135d, + +1.7270287031459572E-134d, + +4.694550492773212E-134d, + +1.2761111606368036E-133d, + +3.4688299108856403E-133d, + +9.429257929713919E-133d, + +2.5631381141873417E-132d, + +6.967331001069377E-132d, + +1.8939170679975288E-131d, + +5.148199748336684E-131d, + +1.3994258162094293E-130d, + +3.804034213613942E-130d, + +1.0340436948077763E-129d, + +2.8108219632627907E-129d, + +7.640606938467665E-129d, + +2.0769322678328357E-128d, + +5.645687086879944E-128d, + +1.5346568127351796E-127d, + +4.171630237420918E-127d, + +1.1339665711932977E-126d, + +3.0824406750909563E-126d, + +8.37894218404787E-126d, + +2.2776327994966818E-125d, + +6.191247522703296E-125d, + +1.6829556040859853E-124d, + +4.5747479502862494E-124d, + +1.2435453481209945E-123d, + +3.3803067202247166E-123d, + +9.188625696750548E-123d, + +2.4977273040076145E-122d, + +6.789527378582775E-122d, + +1.845584943222965E-121d, + +5.016820182185716E-121d, + +1.3637129731022491E-120d, + +3.706956710275979E-120d, + +1.0076552294433743E-119d, + +2.739090595934893E-119d, + +7.445620503219039E-119d, + +2.023929422267303E-118d, + +5.501611507503037E-118d, + +1.4954928881576769E-117d, + +4.0651709187617596E-117d, + +1.1050280679513555E-116d, + +3.003777734030334E-116d, + +8.165114384910189E-116d, + +2.219508285637377E-115d, + +6.033249389304709E-115d, + +1.6400070480930697E-114d, + +4.458001565878111E-114d, + +1.2118105325725891E-113d, + +3.2940421731384895E-113d, + +8.954135150208654E-113d, + +2.433986351722258E-112d, + +6.616260705434716E-112d, + +1.7984863104885375E-111d, + +4.888792154132158E-111d, + +1.3289115531074511E-110d, + +3.612356038181234E-110d, + +9.819402293160495E-110d, + +2.6691899766673256E-109d, + +7.255611264437603E-109d, + +1.9722796756250217E-108d, + +5.361211684173837E-108d, + +1.4573285967670963E-107d, + +3.961429477016909E-107d, + +1.0768281419102595E-106d, + +2.9271223293841774E-106d, + +7.956744351476403E-106d, + +2.1628672925745152E-105d, + +5.879282834821692E-105d, + +1.5981547034872092E-104d, + +4.344234755347641E-104d, + +1.1808855501885005E-103d, + +3.2099795870407646E-103d, + +8.725629524586503E-103d, + +2.3718718327094683E-102d, + +6.44741641521183E-102d, + +1.7525895549820557E-101d, + +4.7640323331013947E-101d, + +1.2949980563724296E-100d, + +3.5201699899499525E-100d, + +9.56881327374431E-100d, + +2.6010732940533088E-99d, + +7.070450309820548E-99d, + +1.9219478787856753E-98d, + +5.2243955659975294E-98d, + +1.4201378353978042E-97d, + +3.8603349913851996E-97d, + +1.0493479260117497E-96d, + +2.8524232604238555E-96d, + +7.753690709912764E-96d, + +2.1076716069929933E-95d, + +5.72924572981599E-95d, + +1.5573703263204683E-94d, + +4.233371554108682E-94d, + +1.1507496472539512E-93d, + +3.1280620563875923E-93d, + +8.5029538631631E-93d, + +2.3113425190436427E-92d, + +6.28287989314225E-92d, + +1.7078641226055994E-91d, + +4.6424556110307644E-91d, + +1.261950308999819E-90d, + +3.430336362898836E-90d, + +9.324622137237299E-90d, + +2.5346947846365435E-89d, + +6.890014851450124E-89d, + +1.8729003560057785E-88d, + +5.091070300111434E-88d, + +1.3838964592430477E-87d, + +3.761820584522275E-87d, + +1.0225689628581036E-86d, + +2.7796303536272215E-86d, + +7.555818934379333E-86d, + +2.053884626293416E-85d, + +5.583037134407759E-85d, + +1.5176268538776042E-84d, + +4.125337057189083E-84d, + +1.121383042095528E-83d, + +3.0482348236054953E-83d, + +8.285962249116636E-83d, + +2.2523580600947705E-82d, + +6.122543452787843E-82d, + +1.664279766968299E-81d, + +4.523982262003404E-81d, + +1.2297456769063303E-80d, + +3.342795345742034E-80d, + +9.086660081726823E-80d, + +2.4700104681773258E-79d, + +6.714184569587689E-79d, + +1.8251046352720517E-78d, + +4.961148056969105E-78d, + +1.3485799924445315E-77d, + +3.665820371396835E-77d, + +9.964732578705785E-77d, + +2.708695208461993E-76d, + +7.362996533913695E-76d, + +2.0014700145557332E-75d, + +5.440559532453721E-75d, + +1.4788974793889734E-74d, + +4.020060558571273E-74d, + +1.092765612182012E-73d, + +2.970445258959489E-73d, + +8.074507236705857E-73d, + +2.1948784599535102E-72d, + +5.966298125808066E-72d, + +1.6218081151910012E-71d, + +4.408531734441582E-71d, + +1.198363039426718E-70d, + +3.257488853378793E-70d, + +8.854771398921902E-70d, + +2.406976727302894E-69d, + +6.542840888268955E-69d, + +1.778528517418201E-68d, + +4.834541417183388E-68d, + +1.3141647465063647E-67d, + +3.572270133517001E-67d, + +9.710435805122717E-67d, + +2.63957027915428E-66d, + +7.175096392165733E-66d, + +1.9503931430716318E-65d, + +5.3017188565638215E-65d, + +1.4411566290936352E-64d, + +3.9174693825966044E-64d, + +1.0648786018364265E-63d, + +2.8946401383311E-63d, + +7.868447965383903E-63d, + +2.1388659707647114E-62d, + +5.814040618670345E-62d, + +1.5804200403673568E-61d, + +4.296027044486766E-61d, + +1.1677812418806031E-60d, + +3.174358801839755E-60d, + +8.62880163941313E-60d, + +2.345551464945955E-59d, + +6.3758692300917355E-59d, + +1.733140900346534E-58d, + +4.711165925070571E-58d, + +1.2806275683797178E-57d, + +3.481106736845E-57d, + +9.462629520363307E-57d, + +2.5722094667974783E-56d, + +6.9919903587080315E-56d, + +1.9006201022568844E-55d, + +5.166420404109835E-55d, + +1.4043786616805493E-54d, + +3.8174968984748894E-54d, + +1.03770335512154E-53d, + +2.820769858672565E-53d, + +7.667647949477605E-53d, + +2.0842827711783212E-52d, + +5.6656680900216754E-52d, + +1.5400881501571645E-51d, + +4.1863938339341257E-51d, + +1.1379799629071911E-50d, + +3.093350150840571E-50d, + +8.408597060399334E-50d, + +2.2856938448387544E-49d, + +6.2131591878042886E-49d, + +1.688911928929718E-48d, + +4.5909386437919143E-48d, + +1.2479464696643861E-47d, + +3.3922703599272275E-47d, + +9.221146830884422E-47d, + +2.5065676066043174E-46d, + +6.8135571305481364E-46d, + +1.8521166948363666E-45d, + +5.0345752964740226E-45d, + +1.368539456379101E-44d, + +3.720075801577098E-44d, + +1.0112214979786464E-43d, + +2.7487849807248755E-43d, + +7.47197247068667E-43d, + +2.0310928323153876E-42d, + +5.521082422279256E-42d, + +1.5007857288519654E-41d, + +4.0795586181406803E-41d, + +1.108938997126179E-40d, + +3.0144088843073416E-40d, + +8.194012195477669E-40d, + +2.2273635587196807E-39d, + +6.054601485195952E-39d, + +1.6458113136245473E-38d, + +4.473779311490168E-38d, + +1.2160992719555806E-37d, + +3.3057007442449645E-37d, + +8.985825281444118E-37d, + +2.442600707513088E-36d, + +6.639677673630215E-36d, + +1.8048513285848406E-35d, + +4.906094420881007E-35d, + +1.3336148713971936E-34d, + +3.625141007634431E-34d, + +9.854154449263851E-34d, + +2.6786368134431636E-33d, + +7.28128971953363E-33d, + +1.9792597720953414E-32d, + +5.380185921962174E-32d, + +1.4624861244004054E-31d, + +3.975449484028966E-31d, + +1.080639291795678E-30d, + +2.9374821418009058E-30d, + +7.984904044796711E-30d, + +2.1705221445447534E-29d, + +5.900089995748943E-29d, + +1.6038109389511792E-28d, + +4.359610133382778E-28d, + +1.185064946717304E-27d, + +3.221340469489223E-27d, + +8.756510122348782E-27d, + +2.380266370880709E-26d, + +6.47023467943241E-26d, + +1.75879225876483E-25d, + +4.780892502168074E-25d, + +1.2995814853898995E-24d, + +3.5326287852455166E-24d, + +9.602680736954162E-24d, + +2.6102792042257208E-23d, + +7.095474414148981E-23d, + +1.9287497671359936E-22d, + +5.242885191553114E-22d, + +1.4251641388208515E-21d, + +3.873997809109103E-21d, + +1.0530616658562386E-20d, + +2.862518609581133E-20d, + +7.78113163345177E-20d, + +2.1151310700892382E-19d, + +5.74952254077566E-19d, + +1.5628822871880503E-18d, + +4.24835413113866E-18d, + +1.1548223864099742E-17d, + +3.139132557537509E-17d, + +8.533046968331264E-17d, + +2.3195229636950566E-16d, + +6.305116324200775E-16d, + +1.71390848833098E-15d, + +4.6588861918718874E-15d, + +1.2664165777252073E-14d, + +3.442477422913037E-14d, + +9.357622912219837E-14d, + +2.5436656904062604E-13d, + +6.914399608426436E-13d, + +1.879528650772233E-12d, + +5.1090893668503945E-12d, + +1.3887944613766301E-11d, + +3.775134371775124E-11d, + +1.0261880234452292E-10d, + +2.789468100949932E-10d, + +7.582560135332983E-10d, + +2.061153470123145E-9d, + +5.602796449011294E-9d, + +1.5229979055675358E-8d, + +4.139937459513021E-8d, + +1.1253517584464134E-7d, + +3.059023470086686E-7d, + +8.315287232107949E-7d, + +2.260329438286135E-6d, + +6.1442124206223525E-6d, + +1.670170240686275E-5d, + +4.539993096841499E-5d, + +1.2340981629677117E-4d, + +3.35462624207139E-4d, + +9.118819143623114E-4d, + +0.0024787522852420807d, + +0.006737947463989258d, + +0.018315639346837997d, + +0.049787066876888275d, + +0.1353352963924408d, + +0.3678794503211975d, + +1.0d, + +2.7182817459106445d, + +7.389056205749512d, + +20.08553695678711d, + +54.59815216064453d, + +148.41314697265625d, + +403.42877197265625d, + +1096.633056640625d, + +2980.9580078125d, + +8103.083984375d, + +22026.46484375d, + +59874.140625d, + +162754.78125d, + +442413.375d, + +1202604.25d, + +3269017.5d, + +8886110.0d, + +2.4154952E7d, + +6.5659968E7d, + +1.78482304E8d, + +4.85165184E8d, + +1.318815744E9d, + +3.584912896E9d, + +9.74480384E9d, + +2.6489122816E10d, + +7.200489472E10d, + +1.95729620992E11d, + +5.32048248832E11d, + +1.446257098752E12d, + +3.9313342464E12d, + +1.0686474223616E13d, + +2.904884772864E13d, + +7.8962956959744E13d, + +2.14643574308864E14d, + +5.83461777702912E14d, + +1.586013579247616E15d, + +4.31123180027904E15d, + +1.1719142537166848E16d, + +3.1855931348221952E16d, + +8.6593395455164416E16d, + +2.35385270340419584E17d, + +6.3984347447610573E17d, + +1.73927483790327808E18d, + +4.7278395262972723E18d, + +1.285159987981792E19d, + +3.493427277593156E19d, + +9.496119530068797E19d, + +2.581312717296228E20d, + +7.016736290557636E20d, + +1.907346499785443E21d, + +5.1847060206155E21d, + +1.4093490364499379E22d, + +3.831007739580998E22d, + +1.0413759887481643E23d, + +2.8307533984544136E23d, + +7.694785471490595E23d, + +2.0916595931561093E24d, + +5.685720022003016E24d, + +1.545539007875769E25d, + +4.201209991636407E25d, + +1.142007304008196E26d, + +3.104297782658242E26d, + +8.43835682327257E26d, + +2.2937832658080656E27d, + +6.23514943204966E27d, + +1.694889206675675E28d, + +4.607187019879158E28d, + +1.2523630909973607E29d, + +3.4042761729010895E29d, + +9.253781621373885E29d, + +2.5154385492401904E30d, + +6.837671137556327E30d, + +1.8586717056324128E31d, + +5.05239404378821E31d, + +1.3733830589835937E32d, + +3.733241849647479E32d, + +1.014800418749161E33d, + +2.758513549969986E33d, + +7.498416981578345E33d, + +2.0382811492597872E34d, + +5.540622484676759E34d, + +1.5060972626944096E35d, + +4.0939972479624634E35d, + +1.1128638067747114E36d, + +3.0250770246136387E36d, + +8.223012393018281E36d, + +2.2352467822017166E37d, + +6.076029840339376E37d, + +1.6516361647240826E38d, + +4.4896127778163155E38d, + +1.2204032949639917E39d, + +3.3174000012927697E39d, + +9.017628107716908E39d, + +2.451245443147225E40d, + +6.663175904917432E40d, + +1.8112388823726723E41d, + +4.923458004084836E41d, + +1.3383347029375378E42d, + +3.637970747803715E42d, + +9.889030935681123E42d, + +2.6881169167589747E43d, + +7.307059786371152E43d, + +1.986264756071962E44d, + +5.399227989109673E44d, + +1.467662348860426E45d, + +3.989519470441919E45d, + +1.0844638420493122E46d, + +2.9478781225754055E46d, + +8.013164089994031E46d, + +2.1782039447564253E47d, + +5.920972420778763E47d, + +1.609486943324346E48d, + +4.3750396394525074E48d, + +1.1892591576149107E49d, + +3.2327411123173475E49d, + +8.787501601904039E49d, + +2.3886908001521312E50d, + +6.493134033643613E50d, + +1.7650169203544438E51d, + +4.7978130078372714E51d, + +1.3041809768060802E52d, + +3.5451314095271004E52d, + +9.636666808527841E52d, + +2.6195174357581655E53d, + +7.120586694432509E53d, + +1.9355758655647052E54d, + +5.2614409704305464E54d, + +1.4302079642723736E55d, + +3.8877083524279136E55d, + +1.0567886837680406E56d, + +2.872649515690124E56d, + +7.808670894670738E56d, + +2.1226166967029073E57d, + +5.769871153180574E57d, + +1.568413405104933E58d, + +4.263390023436419E58d, + +1.1589095247718807E59d, + +3.150242850860434E59d, + +8.563247933339596E59d, + +2.3277319969498524E60d, + +6.327431953939798E60d, + +1.719974302355042E61d, + +4.675374788964851E61d, + +1.2708985520400816E62d, + +3.454660807101683E62d, + +9.390740355567705E62d, + +2.5526681615684215E63d, + +6.938871462941557E63d, + +1.8861808782043154E64d, + +5.1271712215233855E64d, + +1.3937096689052236E65d, + +3.7884955399150257E65d, + +1.0298199046367501E66d, + +2.799340708992666E66d, + +7.609396391563323E66d, + +2.0684484008569103E67d, + +5.622626080395226E67d, + +1.528388084444653E68d, + +4.1545899609113734E68d, + +1.1293346659459732E69d, + +3.069849599753188E69d, + +8.344717266683004E69d, + +2.268329019570017E70d, + +6.165958325782564E70d, + +1.676081191364984E71d, + +4.556060380835955E71d, + +1.2384658100355657E72d, + +3.3664990715562672E72d, + +9.15109220707761E72d, + +2.4875248571153216E73d, + +6.761793219649385E73d, + +1.8380461271305958E74d, + +4.996327312938759E74d, + +1.3581426848077408E75d, + +3.691814001080034E75d, + +1.0035391101975138E76d, + +2.7279024753382288E76d, + +7.415207287657125E76d, + +2.0156621983963848E77d, + +5.479138512760614E77d, + +1.4893842728520671E78d, + +4.048565732162643E78d, + +1.1005142643914475E79d, + +2.991508131437659E79d, + +8.131762373533769E79d, + +2.210442148596269E80d, + +6.008604166110734E80d, + +1.633308028614055E81d, + +4.439791652732591E81d, + +1.206860599814453E82d, + +3.280586734644871E82d, + +8.917559854082513E82d, + +2.4240442814945802E83d, + +6.589235682116406E83d, + +1.7911398904871E84d, + +4.86882298924053E84d, + +1.3234832005748183E85d, + +3.597600556519039E85d, + +9.77929222446451E85d, + +2.658286976862848E86d, + +7.225974166887662E86d, + +1.9642232209552433E87d, + +5.3393125705958075E87d, + +1.4513757076459615E88d, + +3.945247871835613E88d, + +1.0724295693252266E89d, + +2.915165904253785E89d, + +7.924242330665303E89d, + +2.1540322390343345E90d, + +5.855267177907345E90d, + +1.5916266807316476E91d, + +4.326489915443873E91d, + +1.1760619079592718E92d, + +3.1968677404735245E92d, + +8.689987517871135E92d, + +2.3621834216830225E93d, + +6.421080550439423E93d, + +1.7454306955949023E94d, + +4.744571892885607E94d, + +1.2897084285532175E95d, + +3.505791114318544E95d, + +9.529727908157224E95d, + +2.5904487437231458E96d, + +7.041568925985714E96d, + +1.9140971884979424E97d, + +5.203055142575272E97d, + +1.4143368931719686E98d, + +3.8445667684706366E98d, + +1.0450615121235744E99d, + +2.8407720200442806E99d, + +7.722018663521402E99d, + +2.0990624115923312E100d, + +5.705842978547001E100d, + +1.5510089388648915E101d, + +4.216079296087462E101d, + +1.1460491592124923E102d, + +3.1152847602082673E102d, + +8.468222063292654E102d, + +2.3019011105282883E103d, + +6.257216813084462E103d, + +1.7008878437355237E104d, + +4.62349260394851E104d, + +1.2567956334920216E105d, + +3.416324322370112E105d, + +9.286532888251822E105d, + +2.5243410574836706E106d, + +6.861870970598542E106d, + +1.8652499723625443E107d, + +5.070274654122399E107d, + +1.3782437251846782E108d, + +3.746454626411946E108d, + +1.0183920005400422E109d, + +2.768276122845335E109d, + +7.524954624697075E109d, + +2.0454950851007314E110d, + +5.56023190218245E110d, + +1.511427628805191E111d, + +4.1084862677372065E111d, + +1.1168024085164686E112d, + +3.0357834799588566E112d, + +8.252116273466952E112d, + +2.2431576057283144E113d, + +6.097534318207731E113d, + +1.65748157925005E114d, + +4.5055022172222453E114d, + +1.2247224482958058E115d, + +3.329140840363789E115d, + +9.049543313665034E115d, + +2.4599209935197392E116d, + +6.686758417135634E116d, + +1.817649308779104E117d, + +4.940883275207154E117d, + +1.3430713954289087E118d, + +3.6508464654683645E118d, + +9.924030156169606E118d, + +2.697631034485758E119d, + +7.332921137166064E119d, + +1.9932945470297703E120d, + +5.418336099279846E120d, + +1.472856595860236E121d, + +4.0036393271908754E121d, + +1.0883019300873278E122d, + +2.9583112936666607E122d, + +8.041523923017192E122d, + +2.1859129781586158E123d, + +5.941927186144745E123d, + +1.6151834292371802E124d, + +4.390523815859274E124d, + +1.1934680816813702E125d, + +3.2441826014060764E125d, + +8.81860282490643E125d, + +2.3971445233885962E126d, + +6.516115189736396E126d, + +1.7712635751001657E127d, + +4.814793918384117E127d, + +1.3087966177291396E128d, + +3.557678449715009E128d, + +9.670771210463886E128d, + +2.628788218289742E129d, + +7.145787619369324E129d, + +1.9424264981694277E130d, + +5.280062387569078E130d, + +1.4352697002457768E131d, + +3.901467289560222E131d, + +1.0605288965077546E132d, + +2.882816299252225E132d, + +7.836307815186044E132d, + +2.1301292155181736E133d, + +5.790291758828013E133d, + +1.573964437869041E134d, + +4.278478878300888E134d, + +1.1630112062985817E135d, + +3.1613917467297413E135d, + +8.593554223894477E135d, + +2.335970335559215E136d, + +6.349826172787151E136d, + +1.7260616357651607E137d, + +4.691921416188566E137d, + +1.2753966504932798E138d, + +3.466887271843006E138d, + +9.423976538577447E138d, + +2.561702766944378E139d, + +6.963429563637273E139d, + +1.892856346657855E140d, + +5.1453167686439515E140d, + +1.3986421289359558E141d, + +3.8019036618832785E141d, + +1.033464507572145E142d, + +2.809247950589945E142d, + +7.636326960498012E142d, + +2.075769060297565E143d, + +5.64252553828769E143d, + +1.5337974510118784E144d, + +4.169293918423203E144d, + +1.1333315586787883E145d, + +3.080714152600695E145d, + +8.374250298636991E145d, + +2.276357074042286E146d, + +6.187780443461367E146d, + +1.6820131331794073E147d, + +4.572185635487065E147d, + +1.2428488853188662E148d, + +3.378413594504258E148d, + +9.183480622172801E148d, + +2.4963286658278886E149d, + +6.785725312893433E149d, + +1.8445514681108982E150d, + +5.014010481958507E150d, + +1.3629491735708616E151d, + +3.7048805655699485E151d, + +1.0070909418550386E152d, + +2.7375567044077912E152d, + +7.441451374243517E152d, + +2.022795961737854E153d, + +5.4985298195094216E153d, + +1.494655405262451E154d, + +4.062894701808608E154d, + +1.1044092571980793E155d, + +3.002095574584687E155d, + +8.160542326793782E155d, + +2.218265110516721E156d, + +6.02987028472758E156d, + +1.6390888071605646E157d, + +4.455504920700703E157d, + +1.2111317421229415E158d, + +3.2921976772303727E158d, + +8.94912101169977E158d, + +2.432623425087251E159d, + +6.612555731556604E159d, + +1.7974788874847574E160d, + +4.8860545948985793E160d, + +1.328167263606087E161d, + +3.610333312791256E161d, + +9.813901863427107E161d, + +2.667695552814763E162d, + +7.251548346906463E162d, + +1.9711751621240536E163d, + +5.3582093498119173E163d, + +1.4565123573071036E164d, + +3.959211091077107E164d, + +1.0762251933089556E165d, + +2.9254832789181E165d, + +7.952287052787358E165d, + +2.161656025361765E166d, + +5.8759898326913254E166d, + +1.597259768214821E167d, + +4.3418021646459346E167d, + +1.1802241249113175E168d, + +3.2081817253680657E168d, + +8.720743087611513E168d, + +2.3705435424427623E169d, + +6.443805025317327E169d, + +1.7516078165936552E170d, + +4.7613641572445654E170d, + +1.2942728582966776E171d, + +3.518198614137319E171d, + +9.563454814394247E171d, + +2.5996166206245285E172d, + +7.066491077377918E172d, + +1.920871394985668E173d, + +5.221469250951617E173d, + +1.4193426880442385E174d, + +3.8581732071331E174d, + +1.0487601931965087E175d, + +2.850825930161946E175d, + +7.749348772180658E175d, + +2.1064911705560668E176d, + +5.726036941135634E176d, + +1.5564982816556894E177d, + +4.231000988846797E177d, + +1.1501053030837989E178d, + +3.1263099916916113E178d, + +8.498192212235393E178d, + +2.3100480183046895E179d, + +6.279361500971995E179d, + +1.7069074829463731E180d, + +4.63985600437427E180d, + +1.2612435745231905E181d, + +3.4284156709489884E181d, + +9.319400030019162E181d, + +2.5332752658571312E182d, + +6.88615578404537E182d, + +1.8718514371423056E183d, + +5.088219872370737E183d, + +1.3831214731781958E184d, + +3.759713966511158E184d, + +1.021996184153141E185d, + +2.778073442169904E185d, + +7.55158797540476E185d, + +2.0527342305586606E186d, + +5.579910641313343E186d, + +1.5167767828844167E187d, + +4.123026721295484E187d, + +1.1207549425651513E188d, + +3.0465278560980536E188d, + +8.281321669236493E188d, + +2.251096660331649E189d, + +6.119114404399683E189d, + +1.6633478556884994E190d, + +4.521448560089285E190d, + +1.2290570545894685E191d, + +3.340923580982338E191d, + +9.081571104550255E191d, + +2.468626868232408E192d, + +6.710424255583952E192d, + +1.8240823171621646E193d, + +4.958369974640573E193d, + +1.3478247120462365E194d, + +3.6637673548790206E194d, + +9.959152908532152E194d, + +2.707178052117959E195d, + +7.358873642076596E195d, + +2.0003490682463053E196d, + +5.4375131636754E196d, + +1.4780692924846082E197d, + +4.01780853635105E197d, + +1.0921536132159379E198d, + +2.968781250496917E198d, + +8.069984512111955E198d, + +2.193649279840519E199d, + +5.962956589227457E199d, + +1.620899738203635E200d, + +4.406062052965071E200d, + +1.1976919074588434E201d, + +3.2556641859513496E201d, + +8.849812639395597E201d, + +2.40562867677584E202d, + +6.539175932653188E202d, + +1.7775323307944624E203d, + +4.831833881898182E203d, + +1.3134287685114547E204d, + +3.5702693195009266E204d, + +9.704997606668411E204d, + +2.63809219778715E205d, + +7.171077244202293E205d, + +1.949300880034352E206d, + +5.298749302736127E206d, + +1.4403494631058154E207d, + +3.91527572177694E207d, + +1.0642823992403076E208d, + +2.8930193727937684E208d, + +7.8640411896421955E208d, + +2.1376680994038112E209d, + +5.8107841809216616E209d, + +1.5795351101531684E210d, + +4.293620869258453E210d, + +1.1671272667059652E211d, + +3.172580666390786E211d, + +8.623968972387222E211d, + +2.3442378838418366E212d, + +6.372298757235201E212d, + +1.7321703934464356E213d, + +4.708527306855985E213d, + +1.279910496643312E214d, + +3.479157135998568E214d, + +9.45732984079136E214d, + +2.5707689593428096E215d, + +6.988074107282322E215d, + +1.8995553996578656E216d, + +5.1635269305465607E216d, + +1.4035923083915864E217d, + +3.815359096108819E217d, + +1.0371220592190472E218d, + +2.819190456167585E218d, + +7.663353127378024E218d, + +2.083115484919861E219d, + +5.662495731848751E219d, + +1.5392257142577226E220d, + +4.184049381430498E220d, + +1.1373425785132867E221d, + +3.091617462831603E221d, + +8.403887374207366E221d, + +2.2844135610697528E222d, + +6.209679892802781E222d, + +1.6879660933816274E223d, + +4.588367423411997E223d, + +1.2472476068464461E224d, + +3.3903703993793316E224d, + +9.215982463319503E224d, + +2.5051637206758385E225d, + +6.809741127603255E225d, + +1.8510795864289367E226d, + +5.031755776868959E226d, + +1.3677729802316034E227d, + +3.7179924024793253E227d, + +1.0106552237522032E228d, + +2.7472456017809066E228d, + +7.467788172398272E228d, + +2.029955237703202E229d, + +5.517990469846618E229d, + +1.4999452522236406E230d, + +4.0772734783595525E230d, + +1.1083180046837618E231d, + +3.012720614547867E231d, + +8.18942426109357E231d, + +2.2261161215322043E232d, + +6.051211457626543E232d, + +1.6448897917725177E233d, + +4.471273900208441E233d, + +1.2154183152078517E234d, + +3.3038494682728794E234d, + +8.98079409878202E234d, + +2.4412328161430576E235d, + +6.63595840453991E235d, + +1.8038406914061554E236d, + +4.90334700062756E236d, + +1.3328680266667662E237d, + +3.623110695743118E237d, + +9.848636053777669E237d, + +2.677136737066629E238d, + +7.277212447141125E238d, + +1.978151484427976E239d, + +5.377173488599035E239d, + +1.4616672175682191E240d, + +3.973222981713661E240d, + +1.0800340064859439E241d, + +2.935837009891444E241d, + +7.980432566722885E241d, + +2.169306470354036E242d, + +5.896786161387733E242d, + +1.6029126916635028E243d, + +4.357168123448786E243d, + +1.1844011798406507E244d, + +3.2195361624179725E244d, + +8.751606149833694E244d, + +2.3789334438756013E245d, + +6.466611224443739E245d, + +1.7578073785142153E246d, + +4.7782149589194885E246d, + +1.2988535295611824E247d, + +3.5306502960727705E247d, + +9.597302512507479E247d, + +2.608817438130718E248d, + +7.091500562953208E248d, + +1.9276698418065647E249d, + +5.239949786641934E249d, + +1.42436589329759E250d, + +3.8718282216768776E250d, + +1.0524719896550007E251d, + +2.860915548426704E251d, + +7.77677492833005E251d, + +2.113946677051906E252d, + +5.7463023795153145E252d, + +1.56200679236425E253d, + +4.2459748085663055E253d, + +1.1541756557557508E254d, + +3.137374584307575E254d, + +8.528268445871411E254d, + +2.3182239583484444E255d, + +6.301585387776819E255d, + +1.7129486892266285E256d, + +4.6562769567905925E256d, + +1.26570724146049E257d, + +3.4405490416979487E257d, + +9.352382323649647E257d, + +2.54224113415832E258d, + +6.910528108396216E258d, + +1.8784760208391767E259d, + +5.106228040084293E259d, + +1.3880166914480165E260d, + +3.7730204737910044E260d, + +1.0256131352582533E261d, + +2.787906051540986E261d, + +7.578313650939932E261d, + +2.0599991793068063E262d, + +5.5996586041611455E262d, + +1.522145133131402E263d, + +4.137618951061827E263d, + +1.1247213964487372E264d, + +3.0573102223682595E264d, + +8.310629417537063E264d, + +2.2590636576955473E265d, + +6.1407711078356886E265d, + +1.6692346202615142E266d, + +4.5374504961394207E266d, + +1.2334070098307164E267d, + +3.3527476928456816E267d, + +9.113713162029408E267d, + +2.4773638527240193E268d, + +6.734172833429278E268d, + +1.8305382378470305E269d, + +4.9759187284770303E269d, + +1.352594940263854E270d, + +3.6767339705169146E270d, + +9.994400500679653E270d, + +2.716759624268743E271d, + +7.384918458508588E271d, + +2.007428933605617E272d, + +5.456757565532369E272d, + +1.4833003969415539E273d, + +4.0320284712983994E273d, + +1.096019026243815E274d, + +2.979288529962515E274d, + +8.098545495417704E274d, + +2.201412886580694E275d, + +5.984060832462728E275d, + +1.6266362950862408E276d, + +4.4216561713555547E276d, + +1.2019307065458128E277d, + +3.2671863888979078E277d, + +8.881133159512924E277d, + +2.4141423627760256E278d, + +6.562319473965767E278d, + +1.7838233889223407E279d, + +4.848934634563382E279d, + +1.3180771991576186E280d, + +3.5829049382293792E280d, + +9.739345931419228E280d, + +2.6474285478041252E281d, + +7.196457718729758E281d, + +1.956199868121249E282d, + +5.31750271790054E282d, + +1.4454470027638629E283d, + +3.929132560365955E283d, + +1.0680488848057261E284d, + +2.9032581477488686E284d, + +7.89187408872514E284d, + +2.1452336456259667E285d, + +5.831349876080173E285d, + +1.5851251724785243E286d, + +4.308816643345461E286d, + +1.1712579802975851E287d, + +3.1838092090922606E287d, + +8.654490685278886E287d, + +2.3525345191912968E288d, + +6.39485115791896E288d, + +1.7383009254496851E289d, + +4.725191397657393E289d, + +1.2844402232816276E290d, + +3.491470347090126E290d, + +9.490800658395667E290d, + +2.579867270991543E291d, + +7.012806239173502E291d, + +1.906278351789277E292d, + +5.181801397059486E292d, + +1.408559707497606E293d, + +3.8288623079292884E293d, + +1.0407926842436056E294d, + +2.829168201470791E294d, + +7.690475570840264E294d, + +2.0904882610105383E295d, + +5.68253547942899E295d, + +1.544673396032028E296d, + +4.1988574190754736E296d, + +1.1413677466646359E297d, + +3.102559332875688E297d, + +8.433630296371073E297d, + +2.292498520423419E298d, + +6.23165710486722E298d, + +1.6939399242810123E299d, + +4.604606371472047E299d, + +1.2516618713553432E300d, + +3.402369329874797E300d, + +9.248598815279678E300d, + +2.51402968559859E301d, + +6.833842035076675E301d, + +1.8576309291617257E302d, + +5.049564425991982E302d, + +1.3726137091534984E303d, + +3.7311513682845094E303d, + +1.0142320772726397E304d, + +2.7569686255975333E304d, + +7.494218049456063E304d, + +2.037139607241041E305d, + +5.5375196488302575E305d, + +1.5052539519895093E306d, + +4.091704288360009E306d, + +1.1122405335641184E307d, + +3.023383151402969E307d, + +8.218407798110846E307d, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + }; + + /** + * Exponential evaluated at integer values, exp(x) = expIntTableA[x + EXP_INT_TABLE_MAX_INDEX] + + * expIntTableB[x+EXP_INT_TABLE_MAX_INDEX] + */ + private static final double[] EXP_INT_B = + new double[] { + +0.0d, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + -1.76097684E-316d, + -2.44242319E-315d, + -9.879317845E-315d, + -1.3811462167E-314d, + +2.1775261204E-314d, + -1.4379095864E-313d, + +1.4219324087E-313d, + +1.00605438061E-312d, + -1.287101187097E-312d, + +5.33839690397E-312d, + -9.35130825405E-313d, + -4.15218681073E-311d, + +4.546040329134E-311d, + -1.57333572310673E-310d, + +1.05387548454467E-309d, + +2.095732474644446E-309d, + -2.62524392470767E-310d, + +5.86440876259637E-309d, + -2.401816502004675E-309d, + -2.2711230715729753E-308d, + +2.0670460065057715E-307d, + +3.436860020483706E-308d, + +2.0862243734177337E-306d, + -4.637025318037353E-306d, + +9.222671009756424E-306d, + +6.704597874020559E-305d, + +4.351284159444109E-305d, + +4.232889602759328E-304d, + +1.2840977763293412E-303d, + -2.6993478083348727E-303d, + -1.053265874779237E-303d, + +1.207746682843556E-303d, + +5.21281096513035E-303d, + +1.6515377082609677E-301d, + +3.3951607353932444E-301d, + +5.609418227003629E-301d, + +4.238775357914848E-300d, + -9.441842771290538E-300d, + -2.1745347282493023E-299d, + -6.203839803215248E-299d, + -5.617718879466363E-299d, + +5.2869976233132615E-298d, + -1.4300075619643524E-298d, + +4.3198234936686506E-297d, + -2.6448316331572387E-297d, + +4.315655444002347E-296d, + -7.253671992213344E-296d, + -1.1288398461391523E-295d, + -4.83901764243093E-296d, + +1.7407497662694827E-295d, + +1.1969717029666017E-294d, + -7.752519943329177E-294d, + -4.019569741253664E-293d, + -2.4467928392518484E-293d, + -1.0269233640424235E-292d, + -3.2330960700986594E-292d, + -1.440995270758115E-291d, + -3.726946038150935E-291d, + -1.3424576100819801E-291d, + -3.128894928199484E-290d, + -5.989337506920005E-290d, + -9.438168176533759E-290d, + -1.9220613500411237E-289d, + +2.1186736024949195E-289d, + +6.3015208029537436E-288d, + -8.168129112703755E-288d, + -1.6040513288090055E-287d, + -1.0809972724404233E-287d, + -3.080380385962424E-286d, + +2.6399157174374624E-286d, + +1.3317127674213423E-285d, + -3.5821668044872306E-285d, + +1.978536584535392E-284d, + +1.3399392455370071E-284d, + -2.870168560029448E-284d, + +3.5311184272663063E-283d, + -7.204247881190918E-283d, + +3.2425604548983798E-282d, + +3.913063150326019E-282d, + -2.260957518848075E-281d, + +3.807242187736102E-281d, + -5.095591405025083E-281d, + +2.3400625068490396E-280d, + -1.1564717694090882E-280d, + -3.517594695450786E-279d, + +6.666544384808297E-279d, + -9.204784113858607E-279d, + +4.8677119923665573E-278d, + +7.942176091555472E-278d, + -2.5113270522478854E-277d, + +5.332900939354667E-277d, + -3.491241408725929E-276d, + -2.1141094074221325E-276d, + +1.722049095222509E-275d, + +4.0430160253378594E-275d, + +1.9888195459082551E-274d, + +3.230089643550739E-275d, + +5.077824728028163E-274d, + -3.526547961682877E-274d, + -6.4376298274983765E-273d, + -2.5338279333399964E-272d, + -3.614847626733713E-272d, + +2.510812179067931E-272d, + +3.953806005373127E-272d, + +7.112596406315374E-272d, + -2.850217520533226E-270d, + -8.571477929711754E-270d, + +1.2902019831221148E-269d, + -6.978783784755863E-270d, + +9.89845486618531E-269d, + -3.538563171970534E-268d, + +3.537475449241181E-268d, + +3.6924578046381256E-267d, + +1.3555502536444713E-266d, + -1.1279742372661484E-266d, + +5.475072932318336E-266d, + -1.1679889049814275E-265d, + -8.946297908979776E-266d, + +1.0565816011650582E-264d, + -3.2161237736296753E-265d, + -6.022045553485609E-264d, + -2.0332050860436034E-263d, + -1.0488538406930105E-262d, + +1.6793752843984384E-262d, + +3.2558720916543104E-263d, + -1.9546569053899882E-262d, + +5.082190670014963E-262d, + -1.0188117475357564E-260d, + +3.7920054509691455E-261d, + -8.330969967504819E-260d, + -1.1623181434592597E-259d, + +9.09665088462258E-259d, + -1.56400149127482E-259d, + -7.796557225750673E-258d, + +6.751460509863465E-258d, + +7.243157658226935E-258d, + +1.2574668958946027E-256d, + +2.2678858131411216E-256d, + +5.1079306249351287E-256d, + -5.672261759108003E-257d, + +3.476539491009769E-256d, + -1.3481093992496937E-254d, + -3.314051560952014E-254d, + +7.408112967339146E-255d, + -7.164884605413269E-254d, + -6.456588023278983E-253d, + -1.4881197370811587E-252d, + +1.7534012237555307E-252d, + -1.3070101381473173E-251d, + +6.081420141954215E-251d, + +6.591143677421159E-251d, + +2.6917461073773043E-250d, + +3.683043641790553E-251d, + +1.2195076420741757E-249d, + -8.220283439582378E-249d, + +1.637852737426943E-248d, + -8.332543237340988E-249d, + +2.9581193516975647E-248d, + -1.7790661150204172E-247d, + -1.7809679916043692E-247d, + +8.378574405736031E-247d, + -2.883847036065813E-246d, + +1.3223776943337897E-245d, + +3.098547586845664E-245d, + -1.1036542789147287E-244d, + -5.7187703271582225E-244d, + -1.8058492822440396E-244d, + +4.4373726292703545E-243d, + -3.4631935816990754E-243d, + -1.82770041073856E-243d, + +3.845535085273936E-242d, + +8.446532344375812E-242d, + +2.7751016140238277E-242d, + +1.3158882241538003E-241d, + -3.579433051074272E-240d, + -6.151751570213211E-240d, + -2.990535475079021E-239d, + +2.3396028616528764E-239d, + +7.233790684263346E-239d, + +1.0847913100494912E-238d, + +7.103148400942551E-238d, + +3.463600299750966E-237d, + -4.873121855093712E-237d, + +1.3407295326570417E-236d, + +9.390271617387205E-237d, + -2.4767709454727603E-235d, + +3.205923535388443E-235d, + -1.0074984709952582E-234d, + +2.4747880175747574E-234d, + -5.146939682310558E-234d, + -2.827581009333298E-233d, + -3.0307641004671077E-233d, + +5.92044714050651E-233d, + -2.0582596893119236E-232d, + -6.58066591313112E-232d, + -4.869955151949929E-231d, + -5.763495903609913E-231d, + -2.3580462372762525E-230d, + +1.8559980428862584E-230d, + +2.854978560542175E-229d, + +5.637945686485334E-229d, + +2.1454644909004582E-228d, + -1.1918070206953359E-228d, + -5.021851606912854E-228d, + +3.861525553653117E-227d, + +6.533561982617909E-227d, + -3.015709444206057E-226d, + -5.042005018212734E-227d, + +1.5959614205422845E-225d, + +2.0402105689098835E-224d, + +5.164902728917601E-224d, + +9.981031744879876E-224d, + +4.0281104210095145E-223d, + +1.1158160971176672E-222d, + +2.0736172194624895E-222d, + +4.983162653734032E-222d, + +2.1753390051977871E-221d, + +3.969413618002761E-221d, + +1.3961255018698695E-220d, + +2.1290855095314206E-220d, + +1.1927747883417406E-219d, + +3.7264401117998796E-219d, + +9.318532410862293E-219d, + +2.3414841777613345E-218d, + +4.3791842770430786E-218d, + +1.7173159016511951E-217d, + +3.5037536832675478E-217d, + +1.4300098613455884E-216d, + +2.4189403362149483E-216d, + +9.306541421999056E-216d, + +3.442100456607687E-215d, + +5.94407068841904E-215d, + +2.0483260435783403E-214d, + +3.8410992889527954E-214d, + +1.2038281262953917E-213d, + +3.865007795216205E-213d, + +9.754659138599756E-213d, + +2.7653605770745684E-212d, + +5.359568079675375E-212d, + +2.61726605666378E-211d, + +5.054202073556894E-211d, + +8.707092668016246E-211d, + +1.4080573899148006E-210d, + +1.288124387778789E-209d, + +1.8639901642011898E-209d, + +6.076014540574561E-209d, + +1.798489141298457E-208d, + +2.1525406805994896E-208d, + +1.1864056832305874E-207d, + +2.1077440662171152E-207d, + +1.3784853708457332E-206d, + +1.6965806532093783E-206d, + +7.241626420445137E-206d, + +2.575584299085016E-205d, + +6.151951078101721E-205d, + +2.40652042118887E-204d, + +4.022633486003565E-204d, + +5.8840879519086286E-204d, + +3.2820308007277566E-203d, + +4.31880454864738E-203d, + +2.427240455243201E-202d, + +7.326955749884755E-202d, + +1.4310184489676175E-201d, + +4.464279133463661E-201d, + +4.895131474682867E-201d, + +4.48614966943544E-200d, + +8.924048768324976E-200d, + +2.5035535029701945E-199d, + +6.627829836338812E-199d, + +2.6066826304502746E-198d, + +8.042275310036546E-198d, + +2.115062964308555E-197d, + +4.413745413236018E-197d, + +1.644449394585716E-196d, + +3.138217752973845E-196d, + +7.48533983136081E-196d, + +2.613626422028823E-195d, + +3.6741841454219095E-195d, + +5.906102862953403E-195d, + +4.4940857547850743E-194d, + +5.840064709376958E-194d, + +3.087661273836024E-193d, + +4.995552216100365E-193d, + +1.991444798915497E-192d, + +7.097454751809522E-192d, + +2.0510193986749737E-191d, + +5.759440286608551E-191d, + +1.7013941257113314E-190d, + +2.1383323934483528E-190d, + +8.280292810015406E-190d, + +3.138655772049104E-189d, + +7.961506427685701E-189d, + +2.0579001228504997E-188d, + +7.530840351477639E-188d, + +1.4582863136475673E-187d, + +3.149267215638608E-187d, + +5.443114553057336E-187d, + +3.4672966834277804E-186d, + +7.374944406615125E-186d, + +2.7318417252599104E-185d, + +7.913674211949961E-185d, + +2.5217716516462005E-184d, + +4.0866585874353075E-184d, + +1.2087698972768686E-183d, + +3.7072473866919033E-183d, + +1.1333588840402273E-182d, + +1.61949812578045E-182d, + +6.567779607147072E-182d, + +2.422974840736314E-181d, + +2.551170809294396E-181d, + +1.0905890688083124E-180d, + +3.221279639653057E-180d, + +7.068244813489027E-180d, + +1.3752309224575428E-179d, + +7.20154303462761E-179d, + +1.5391707185581056E-178d, + +7.708777608683431E-178d, + +5.597398155472547E-178d, + +1.8487854656676722E-177d, + +1.0577249492414076E-176d, + +2.8926683313922764E-176d, + +4.090184282164232E-176d, + +1.6142943398013813E-175d, + +7.873864351702525E-175d, + +2.242630017261011E-174d, + +3.4637009373878283E-174d, + +1.5907089565090164E-173d, + +1.6985075903314236E-173d, + +1.1552273904608563E-172d, + +2.237894048535414E-172d, + +5.321990399912051E-172d, + +1.4106062639738257E-171d, + +2.9850404523368767E-171d, + +1.5683802588004895E-170d, + +4.880146806045633E-170d, + +1.1489352403441815E-169d, + +1.6401586605693734E-169d, + +8.29169700697816E-169d, + +1.0380723705441457E-168d, + +7.126414081261746E-168d, + +1.253325949455206E-167d, + +2.595079206183114E-167d, + +1.537490712803659E-166d, + +2.6338455225993276E-166d, + +7.994936425058567E-166d, + +1.5716634677516025E-165d, + +3.669404761339415E-165d, + +1.9941628263579332E-164d, + +4.5012079983352374E-164d, + +7.283163019991001E-164d, + +2.398038505188316E-163d, + +7.868666894503849E-163d, + +2.1478649410390003E-162d, + +8.306111510463843E-162d, + +1.5453160659068463E-161d, + -4.590496588813841E-162d, + +3.5449293983801232E-161d, + -1.0440854056870505E-160d, + -2.321064927632431E-160d, + +5.707867001443433E-160d, + -2.238614484037969E-159d, + +2.482282821883242E-159d, + -1.1508772192025259E-158d, + +1.9903990578876104E-158d, + -1.2116165315442256E-158d, + -2.9084557554502667E-157d, + -1.1211083853006645E-156d, + -1.309893394818129E-156d, + +4.2269712317468864E-156d, + -7.678973146281339E-156d, + +3.2021376921211934E-155d, + -7.08313012515209E-155d, + +1.944398214330544E-154d, + +1.1860061363751161E-153d, + +1.5234465914578058E-153d, + -2.9020908354550263E-153d, + +4.980100072851796E-153d, + +2.3101551448625578E-152d, + -1.1959241322537072E-151d, + -9.27398924154364E-153d, + +5.999390491704392E-152d, + +1.3373196561281372E-150d, + -1.0271780540759147E-150d, + +2.575620466387945E-150d, + -6.56250013356227E-149d, + -1.1961357917482867E-148d, + +5.5807813570926636E-148d, + +9.252840189663807E-148d, + -1.830335419852293E-147d, + +9.350990339947455E-147d, + -1.6072409939877762E-146d, + -2.5309995887229526E-146d, + -1.6014373376410622E-146d, + -3.303297758377758E-145d, + +1.5640419864850202E-145d, + +9.544642884951585E-145d, + -8.64864445321803E-144d, + +7.580392204597681E-144d, + +2.678334184447568E-143d, + -3.7269289985326055E-143d, + -2.851965258161176E-142d, + +7.243267286265823E-142d, + +4.4510805312036926E-141d, + +9.008499734799015E-141d, + +1.130435759928337E-140d, + -3.096539751496479E-140d, + -1.497405487919762E-139d, + +3.51519845948652E-139d, + -4.713790209541894E-139d, + +4.740753295616865E-138d, + +9.517570994930463E-138d, + -1.8842098029339485E-137d, + -3.825558165008403E-137d, + +1.1817638600528107E-136d, + -3.514601201473235E-136d, + -6.344612631552417E-136d, + -1.6754164785291923E-136d, + +4.445372986583078E-135d, + -3.89604237755475E-134d, + -1.0155552195374609E-134d, + +2.1858142063550155E-134d, + +3.497714990137842E-133d, + -7.635830383612894E-133d, + +1.2050744860079718E-132d, + -7.683019590615251E-133d, + -3.344806129021162E-131d, + -1.6737914131474577E-131d, + -4.30610076666344E-131d, + +5.184023388254773E-130d, + +2.6290763595212492E-129d, + +7.90041744728452E-130d, + -3.204473056113754E-129d, + -2.552517201762272E-128d, + +7.130134251490065E-128d, + -3.2244113258340395E-127d, + -1.064920993515727E-127d, + +2.7466520735457463E-126d, + +4.368312797746065E-126d, + +1.8802599072446818E-125d, + -4.257625799463564E-125d, + +5.491672256552995E-125d, + +3.7298611779671127E-124d, + +5.724180836308973E-124d, + +1.3861841053630075E-123d, + +4.2303826056297614E-123d, + +3.5335436928899096E-123d, + -2.522906629540626E-122d, + +1.0147808005267102E-121d, + +6.734406065735473E-122d, + -4.948973160958133E-121d, + +2.4256181927024344E-120d, + +4.9056283164780554E-120d, + +6.846440394397547E-120d, + +3.512747689569002E-119d, + -9.020907406701404E-119d, + +2.5718749916003624E-118d, + +4.3724191002977524E-119d, + +1.001455050575191E-117d, + -2.4442443105031435E-117d, + +2.38873950760028E-116d, + -4.831068747037129E-118d, + -5.148989321866988E-116d, + +1.7875271881514469E-115d, + -1.1821586412088555E-114d, + +4.43247726423679E-115d, + +4.634817120492781E-114d, + +1.671311907037975E-113d, + -4.595250028278979E-113d, + -5.905511605694905E-113d, + -1.3657642265608213E-112d, + +2.881416869529271E-112d, + +2.1253302469985373E-111d, + -5.301386276260592E-111d, + +1.4198782892306878E-112d, + -3.395494928605007E-110d, + +9.284633292147283E-110d, + -6.054133004896379E-110d, + -8.324100783330331E-109d, + -2.193190669794277E-108d, + +1.3613655394659198E-107d, + +6.463452607647978E-108d, + +1.0187183636134904E-106d, + +1.0705673935006142E-106d, + +2.509050608571019E-106d, + -1.5096182622106617E-105d, + +1.7794190449526737E-106d, + +1.2261246749706581E-104d, + +2.1377905661197194E-104d, + -2.2015877944429946E-104d, + +7.873970951802825E-104d, + -1.7999197335480384E-103d, + +1.0487383011058756E-105d, + -2.9988278531841556E-102d, + +4.7976477743232285E-102d, + +3.452316818502442E-102d, + +5.89953246760617E-101d, + -4.0785601577267006E-101d, + +2.7214076662438963E-100d, + +5.237807655758373E-100d, + +6.180972117932364E-99d, + -1.3019742873005683E-98d, + +4.501188264957416E-99d, + -2.4075054705261798E-98d, + +1.6503086546628772E-97d, + -6.878666975101243E-97d, + +1.196718116616528E-96d, + +2.476190162339265E-96d, + -7.1844969234484515E-96d, + +5.088386759261555E-95d, + +6.749368983223726E-95d, + +1.965737856765605E-94d, + -5.574080023496771E-94d, + +1.2493696959436675E-93d, + +8.533262777516794E-94d, + -7.225259028588793E-93d, + -7.340587186324432E-93d, + -3.482412195764625E-92d, + +3.4742610108480497E-91d, + -7.177274244758699E-91d, + +1.2736636153072213E-90d, + -5.730160886217076E-90d, + -1.545495535488274E-89d, + +1.1304179460367007E-89d, + +1.249260560756154E-88d, + -4.7439719382414206E-88d, + +7.164663249266942E-88d, + +1.7617425105337704E-87d, + +2.4175248449172035E-87d, + -1.043079666926483E-86d, + -2.8137609614326677E-86d, + -1.2091497144395591E-85d, + +3.7944631664558904E-85d, + -2.8144926807308225E-85d, + +3.9782728352520784E-85d, + +4.313978872469646E-84d, + +5.82190887044604E-84d, + +5.883385169571802E-83d, + +1.134857098306787E-82d, + +3.468049324128309E-82d, + +2.625423995658143E-82d, + -3.42827917465521E-81d, + +5.119461911618321E-81d, + -2.134387988350615E-80d, + -4.4703076268400615E-80d, + +4.806078883451016E-80d, + +2.3820250362443495E-79d, + -7.258551497833573E-79d, + -4.0297835558876335E-78d, + +2.1424166787650852E-78d, + -3.2117127164185917E-77d, + +4.8459153070935316E-77d, + -1.766924303914492E-76d, + -2.6921749814579492E-76d, + -4.1291070428848755E-76d, + +2.2086994756104319E-75d, + -7.814146377574201E-75d, + -1.9589778310104216E-74d, + +6.52658129486538E-74d, + +1.7804909509998055E-74d, + -4.1900132227036916E-73d, + +1.5705861683841123E-72d, + -1.904714978998808E-72d, + -7.81295459930537E-72d, + +2.818537910881676E-71d, + +5.840507984320445E-71d, + +1.7331720051707087E-70d, + +1.936946987935961E-70d, + -5.86517231340979E-71d, + -1.3277440528416646E-69d, + +1.9906256185827793E-69d, + +8.668714514280051E-69d, + +6.643105496829061E-69d, + -2.5436254170647032E-67d, + -4.8279217213630774E-67d, + -1.2640304072937576E-66d, + +3.51187258511716E-66d, + +1.4199501303738373E-65d, + -1.2351697477129173E-65d, + +7.0542365522414836E-65d, + +1.030593104122615E-64d, + -5.452692909894593E-65d, + -9.415506349675128E-64d, + -3.6206211446779087E-63d, + -1.6699188275658641E-62d, + +2.287280262665656E-62d, + +7.076135457313529E-62d, + +2.9019628518165404E-61d, + -3.1305705497720186E-61d, + +2.2978757040142953E-60d, + +1.2424439441817321E-60d, + +7.140343013236265E-60d, + +8.633726388939636E-60d, + +1.3483035574114863E-58d, + +1.653701058949654E-58d, + -8.939932297357388E-58d, + -1.395320103272191E-57d, + +6.440430933947252E-58d, + -1.681200826841738E-56d, + +3.9904382022898837E-56d, + -4.870518577546228E-56d, + -1.6990896855901115E-55d, + -6.751434891261518E-56d, + -1.669012123121194E-54d, + -4.079585475491198E-54d, + -1.3070436427679952E-53d, + -3.090028378908628E-53d, + +7.468160889798606E-53d, + +6.229095980733463E-53d, + +1.4794751934479566E-52d, + +1.7444373785853918E-51d, + -5.3681978363391484E-52d, + +2.71853394036182E-51d, + -1.3334367969274016E-50d, + -1.6958057665854177E-49d, + -1.452507231312146E-49d, + +3.3855429446520427E-49d, + +4.903687986212687E-49d, + +2.2185957416622524E-48d, + -9.924196700842429E-48d, + +4.285128462851149E-47d, + +3.076063086193525E-48d, + +4.102052341676543E-46d, + +1.1745772638457318E-45d, + -5.309047216809048E-47d, + +2.72972449891179E-45d, + -1.1748423022293739E-44d, + +6.626052626622228E-44d, + +3.0227439688367925E-44d, + -4.740494808228372E-43d, + +5.926057457356852E-43d, + +3.09768273342776E-42d, + -5.589493227475577E-42d, + -8.84908716783327E-42d, + +2.3684740712822874E-41d, + +1.4836491430755657E-40d, + +4.5878801324451396E-40d, + +1.0585156316103144E-39d, + +2.3805896467049493E-39d, + +1.0285082556185196E-38d, + +2.5187968110874885E-38d, + -1.4088399542613178E-38d, + -3.00901028043488E-38d, + +2.0089026801414973E-37d, + -1.3324111396289096E-36d, + +5.458481186294964E-36d, + -4.8402541351522003E-36d, + -1.3331969720555312E-35d, + -8.248332290732976E-35d, + -1.8349670703969982E-34d, + +6.403477383195494E-34d, + +3.7813691654412385E-34d, + +2.4621305031382827E-33d, + -5.634051826192439E-33d, + +3.817173955083142E-32d, + -6.038239639506472E-32d, + -2.130447095555397E-31d, + -6.824454861992054E-31d, + -1.3455801602048414E-30d, + -2.518642767561659E-30d, + +8.082792416221215E-30d, + +4.718103502869148E-29d, + -5.607991635038776E-29d, + -1.8042191582018579E-28d, + +6.989914264479507E-28d, + -2.9031739430339586E-28d, + +6.076820259849921E-27d, + -3.24981577480893E-27d, + -2.7648210023059463E-26d, + -9.785306155980342E-26d, + +1.241529292737115E-25d, + +3.0891604448087654E-25d, + +2.3451052074796954E-24d, + +6.574128018028633E-24d, + -1.3345148716925826E-23d, + +4.3594621428644293E-23d, + -5.678896695157704E-23d, + -4.676849004137386E-23d, + -2.281578975407609E-22d, + -3.144430608076357E-21d, + +5.662033727488754E-22d, + -4.30293375386492E-21d, + +4.985137671479376E-20d, + +1.657668502165438E-19d, + -3.3878706977811337E-19d, + -7.488022803661722E-19d, + +1.725039737424264E-18d, + -6.0275040161173166E-18d, + -8.081007442213538E-19d, + +2.9257892371894816E-17d, + +1.5231541295722552E-16d, + -1.1474026049124666E-17d, + +6.890372706231206E-16d, + +2.592721454922832E-15d, + -1.1253822296423454E-15d, + -2.650684279637763E-14d, + -4.107226967119929E-15d, + -3.130508064738312E-14d, + -6.729414275200856E-14d, + -1.6166170913368169E-12d, + -1.2059301405584488E-12d, + -1.2210091619211167E-11d, + +3.695372823623631E-12d, + +5.119220484478292E-11d, + -1.0857572226543142E-10d, + -4.6490379071586397E-10d, + -4.5810381714280557E-10d, + +1.4909756678328582E-9d, + -1.3155828104004438E-8d, + -9.149755188170102E-9d, + +0.0d, + +8.254840070411029E-8d, + -1.0681886149151956E-7d, + -3.359944163407147E-8d, + -2.1275002921718894E-6d, + +1.2129920353421116E-5d, + +2.1520078872608393E-5d, + +1.0178783359926372E-4d, + -2.077077172525637E-5d, + -5.67996159922899E-5d, + +9.510567165169581E-4d, + +0.0010901978184553272d, + +0.010169003920808009d, + +0.017008920503326107d, + +0.03416477677774927d, + -0.1275278893606981d, + +0.5205078726367633d, + +0.7535752982147762d, + +1.1373305111387886d, + -3.036812739155085d, + +11.409790277969124d, + -9.516785302789955d, + -49.86840843831867d, + -393.7510973999651d, + -686.1565277058598d, + +4617.385872524165d, + -11563.161235730215d, + -8230.201383316231d, + -34460.52482632287d, + +50744.04207438878d, + +357908.46214699093d, + +1936607.425231087d, + +3222936.695160983d, + +5477052.0646243105d, + -3.517545711859706E7d, + -1.2693418527187027E8d, + -2.5316384477288628E8d, + -1.6436423669122624E8d, + +4.0889180422033095E8d, + +4.968829330953611E9d, + -3.503399598592085E9d, + +1.905394922122271E10d, + +1.0361722296739479E11d, + -5.806792575852521E10d, + +2.3454138776381036E11d, + -1.718446464587963E12d, + -1.0946634815588584E12d, + +1.6889383928999305E13d, + -3.784600043778247E13d, + +7.270965670658928E13d, + -4.9202842786896806E14d, + +4.597700093952774E14d, + +2.6113557852262235E15d, + -4.544525556171388E15d, + -9.517971970450354E15d, + -2.0634857819227416E16d, + -9.7143113104549808E16d, + -2.2667083759873216E16d, + -7.2285665164439578E17d, + +4.1215410760803866E18d, + +8.5807488300972206E18d, + +1.530436781375042E19d, + -1.5453111533064765E19d, + -1.0633845571643594E20d, + -3.512380426745336E20d, + +3.7734658676841284E20d, + -3.855478664503271E21d, + +7.984485303520287E21d, + -1.2296934902142301E22d, + +1.042139023692827E22d, + +1.2167897656061312E23d, + +9.22064170155394E22d, + +3.965171513035854E23d, + -4.135121057126514E24d, + -7.944341754299148E24d, + +1.4715152230577016E25d, + -3.0635272288480756E25d, + -9.54468158713835E25d, + +1.5411775738825048E25d, + -8.274711842374368E26d, + -1.0028324930788433E27d, + +5.189062091114782E27d, + -2.8583500869462184E28d, + -5.198295198128238E28d, + +2.9758750368256437E29d, + +3.216046320616945E29d, + -1.7846700158234043E30d, + +3.847174961282827E30d, + +9.026991921214922E30d, + +4.1358029739592175E30d, + -6.461509354879894E29d, + +9.704297297526684E31d, + +2.9731739067444943E32d, + +9.97728609663656E32d, + +3.1149346370027763E33d, + +2.0051635097366476E34d, + +2.819272221032373E34d, + +1.6266731695798413E34d, + +1.998050894021586E35d, + -6.1633417615076335E35d, + +2.2505716077585116E36d, + +1.9299691540987203E36d, + +8.006569251375383E36d, + -3.785295042408568E37d, + -1.1870498357197593E38d, + +1.0010529668998112E38d, + +1.3240710866573994E38d, + +2.6888010385137123E39d, + +1.7400655988987023E39d, + -6.402740469853475E39d, + -3.93114092562274E40d, + +1.2363717201084252E41d, + -1.9219116633978794E41d, + -1.347867098583136E42d, + +7.87675118338788E41d, + +3.3932984011177642E41d, + -1.9872713979884691E43d, + +2.220208491349658E43d, + -3.466267817480825E43d, + +3.19462030745197E44d, + -9.841244788104406E44d, + -2.2676593395522725E45d, + -1.1349246400274207E46d, + -1.1700910284427406E46d, + -3.6754317105801715E46d, + +1.7647101734915075E47d, + +2.122358392979746E47d, + +3.156243682143956E47d, + +5.356668151937413E47d, + +2.7668218233914262E48d, + +3.5127708120698784E48d, + +1.7884841356632925E49d, + +1.716531820904728E50d, + -2.9114757102866277E50d, + +1.0657703081219677E51d, + -7.512169809356372E50d, + +1.764200470879736E51d, + -1.0088898215431471E52d, + -3.1085734725176E52d, + +4.3529009584292495E52d, + -2.467842129213774E53d, + -3.9317379627195146E53d, + -4.332335454045836E52d, + +7.979013724931926E54d, + -1.5038413653121357E55d, + +9.310799925566843E55d, + -2.2042966348036592E55d, + -4.518315366841937E55d, + -6.971366338144781E56d, + -2.0461505570781806E57d, + -8.823884392655312E57d, + -1.1264032993918548E58d, + -7.692065092509875E58d, + -1.8472516879728875E59d, + +8.72220314694275E58d, + +1.6525336989036362E59d, + -3.343201925128334E60d, + +5.493352163155986E60d, + -2.548073509300398E61d, + -9.566541624209933E61d, + +4.0891054447206644E61d, + -7.724182294653349E62d, + +1.0143022354947225E63d, + -4.952031310451961E63d, + -7.877410133454722E63d, + +4.505432606253564E64d, + -7.330635250808021E64d, + -1.642361029990822E65d, + +5.982180242124184E65d, + +7.120242132370469E65d, + +5.908356249789671E66d, + -2.8477710945673134E65d, + +6.65688196961235E66d, + -9.233295580238604E67d, + +3.2850043261803593E68d, + +7.041681569694413E68d, + -1.5652761725518397E69d, + +1.5377053215489084E68d, + +1.282130763903269E70d, + -2.380286345847567E70d, + -7.207022875977515E70d, + +2.7641662602473095E71d, + +7.685235201534525E71d, + +4.3239378585884645E70d, + -1.6840562544109314E72d, + -5.04128025464686E71d, + +5.4557485189210095E73d, + +7.160277784358221E73d, + +7.636179075087608E73d, + -8.18804507680012E74d, + +2.807397988979441E75d, + +2.165163304600171E75d, + -1.3208450062862734E76d, + -5.1939252391404724E76d, + -6.985952908805853E76d, + -1.6259920998287064E77d, + +6.098975200926637E77d, + -5.63383579957466E77d, + -1.5876819186852907E78d, + +2.1487475413123092E79d, + -3.987619123706934E79d, + +9.772655251656639E79d, + -1.638756156057952E79d, + -7.83892088580041E80d, + +1.274413296252691E81d, + +2.51946651720982E81d, + -2.516866097506943E81d, + +1.053956282234684E82d, + +1.8279051206232177E83d, + +1.2250764591564252E82d, + -4.0353723442917463E83d, + -1.4121324224340735E84d, + -5.45287716696021E84d, + -1.7514953095665195E85d, + -5.0706081370522526E85d, + -4.35799392139009E85d, + -3.982538093450217E86d, + -1.4591838284752642E87d, + +2.5313735821872488E87d, + -3.718501227185903E86d, + -1.3907979640327008E88d, + -5.79002114093961E86d, + -1.2500675565781447E89d, + +4.8182788286170926E89d, + -1.7198866036687559E90d, + -4.690417668647599E88d, + +1.3020631859056421E91d, + -1.3850458263351744E91d, + +4.87301010703588E91d, + -1.695546877943826E92d, + -1.6353756659909833E92d, + -1.5483926773679628E93d, + -1.8921091400297595E93d, + -6.183525570536406E93d, + -4.987913342551977E93d, + +1.0186485886120274E93d, + -1.5343120819745468E95d, + -5.262123923229857E95d, + +1.618327917706804E96d, + -4.135185828158998E96d, + -8.016793741945299E96d, + -3.0399439534134115E97d, + -1.2319346292749103E98d, + +7.536337311795176E97d, + -3.577715974851322E98d, + +2.0521614818695524E99d, + +1.2627736197958951E98d, + -5.206910481915062E99d, + +3.0974593993948837E100d, + -9.522726334561169E100d, + -1.1909272509710985E100d, + -5.056512677995137E101d, + +2.0902045062932175E102d, + +6.243669516810509E102d, + -1.7375090618655787E103d, + -2.5445477450140954E103d, + +3.619891246849381E103d, + +8.90737333900943E103d, + -2.7897360297480367E104d, + +1.3725786770437066E105d, + -8.316530604593264E105d, + -6.054541568735673E105d, + +7.523374196797555E105d, + +1.1475955030427985E107d, + +1.5260756679495707E107d, + +7.370294848920685E107d, + +1.3608995799112174E108d, + +1.0700758858011432E108d, + -4.989318918773146E108d, + -1.6629755787634093E108d, + +7.635999584053557E109d, + +1.892621828736983E109d, + -6.793094743406533E110d, + -8.160628910742724E110d, + -7.724219106106896E111d, + -1.6059226011778748E112d, + -1.5277127454062126E112d, + +3.911086668967361E112d, + +3.529920406834134E113d, + -4.3991443996021166E113d, + -1.2631909085915044E114d, + +3.8656278695544835E114d, + +1.71845288713123E115d, + +3.7660598745907915E115d, + -4.048086182363988E115d, + +2.3093822298965837E116d, + -9.684925795536813E116d, + -3.137992585221854E117d, + -5.637415935329794E117d, + -1.5536658521931418E118d, + -6.336314643222911E118d, + +8.550658957115427E118d, + -5.591880480212007E119d, + +2.4137404318673354E119d, + -2.631656656397244E120d, + -7.653117429165879E119d, + -4.073965591445897E121d, + +3.634781057940233E121d, + +4.537273754534966E121d, + -2.5138919966097735E122d, + -1.0292817180691822E123d, + -1.4265564976097062E122d, + +6.000235114895513E123d, + +4.186590347846346E124d, + -1.8950538406321535E124d, + +7.716762345695022E124d, + -4.443798187035849E125d, + -2.268994961992292E125d, + -2.8169291774231604E126d, + -2.749127978087685E126d, + -2.2929764629585683E126d, + -7.369842361872221E127d, + +2.81312841469177E128d, + +2.7856896414497757E128d, + -3.096733638475319E128d, + -5.4199510725063615E129d, + -7.315860999413894E129d, + +3.6424644535156437E130d, + -7.886250961456327E130d, + +5.289988151341401E130d, + +2.7758613753516344E131d, + -2.738246981762776E132d, + -2.2667181460478093E132d, + -3.614672661225457E131d, + +2.325337720526947E133d, + +4.16603235883392E133d, + -6.50348962894948E133d, + +3.851445905038431E134d, + -5.46060534001412E134d, + +5.4679180659102885E135d, + -3.037477806841494E135d, + -3.0417051809209134E136d, + -6.995964550587914E136d, + -3.6897084415718804E137d, + -6.938000231893302E137d, + +2.403806217004454E138d, + -3.4552363953199905E138d, + +7.3409917428393E138d, + -1.7445917446236717E139d, + -6.680679913078676E139d, + -8.193572619487537E139d, + +5.337290292186291E139d, + -3.951314467739045E140d, + -4.4662073456574476E141d, + +6.249381778908997E141d, + -2.928362616578011E142d, + -1.6661676835672304E143d, + -1.974465323891493E143d, + +1.3083870531380308E144d, + -2.382825271750576E144d, + -5.4826958838142734E144d, + +1.5340733916570804E145d, + -3.1327120557842516E145d, + +1.5790297768522832E146d, + +1.1518771984292262E146d, + -4.789917000227385E145d, + -8.689594184775204E146d, + +3.0680417869552433E146d, + +4.877860620031438E147d, + -3.4650891244084597E148d, + +1.8702183451052442E149d, + -3.5727227900139915E148d, + -1.3457821696677932E150d, + +3.3212950284273017E149d, + +7.316033240396569E150d, + -7.187723217018267E150d, + -8.537194547485455E150d, + -1.4561530066010593E152d, + -7.548155147049997E151d, + +1.0047353208353007E153d, + -1.2489460589853119E153d, + +4.426120229279107E153d, + -2.5466223330961086E154d, + +8.831699889789037E154d, + -2.0258084311749475E155d, + -5.525009099476396E155d, + -1.0235056525096769E156d, + -4.117971654572494E154d, + -4.7559175309753334E156d, + -1.4656240137098836E157d, + -7.675790582869644E157d, + -1.0126616322947826E158d, + +7.084865265284368E158d, + -9.374695893307895E158d, + +2.05597910889115E159d, + -7.368602086210704E159d, + -1.6167825196198978E160d, + +2.3832096207000712E160d, + +1.3166970112139726E161d, + -6.432337568761393E161d, + +2.9279594746502846E161d, + +4.8926595743317624E162d, + +1.2704793774453618E163d, + -1.1345910784680524E163d, + +7.75933511025868E163d, + -1.1441115218462356E163d, + +5.162248481759758E164d, + +6.362563919556132E164d, + -2.8362173224732088E165d, + -4.342161053332263E165d, + +4.388125271425036E166d, + -7.049068240916723E166d, + +3.8520227881415595E166d, + +2.9274120974020826E167d, + -7.500936767542933E167d, + -6.540181860667302E168d, + +4.664436780622191E168d, + -1.436111169285268E169d, + -1.0407581736224179E170d, + -2.7670181051374297E170d, + -6.788169932297778E170d, + +1.6997387217850427E171d, + -1.0965324942770584E171d, + +9.841563119484623E171d, + +3.175748919314254E172d, + +2.9621181706527444E172d, + -3.30101656090905E173d, + -3.791840683760427E173d, + -2.841347842666459E174d, + -7.836327226971707E174d, + +9.650358667643114E174d, + +5.9994277301267294E175d, + -6.0490084078440215E175d, + -2.8964095485948707E176d, + +9.916187343252014E175d, + +2.7535627955313556E176d, + +3.886891475472745E177d, + +3.1962472803616787E178d, + -5.50599549115449E178d, + +5.672812341879918E178d, + -3.295268490032475E179d, + +9.761163062156018E179d, + +3.107837179570674E180d, + +3.3894811576571423E179d, + -5.235397688850367E180d, + -5.004237248003625E181d, + -1.7544995191195304E182d, + +2.645622651144787E182d, + -3.459885432869825E182d, + -4.0361435606199565E183d, + -1.8382923511801317E183d, + -1.7332235571505177E184d, + +2.847653455671381E184d, + +1.7991060813894693E185d, + -2.0937429891059164E185d, + +5.744446753652847E185d, + -2.1349396267483754E184d, + -1.2542332720182776E186d, + +3.3730714236579374E186d, + -5.923734606208998E187d, + +2.24669039465627E188d, + -1.2588742703536392E188d, + +1.474522484905093E189d, + -2.4006971787803736E189d, + -3.52597540499141E189d, + +2.6676722922838097E190d, + +5.27579825970359E190d, + +2.1360492104281465E191d, + +1.9442210982008953E191d, + -1.4691239161932232E190d, + +3.8218180377739526E192d, + +1.9722862688653467E192d, + +3.047601928063002E193d, + +1.6747356805175311E193d, + +7.710512446969693E192d, + +1.7780021277684035E194d, + -1.4015110811648513E195d, + +4.0447634595724164E195d, + +9.023639664212642E195d, + +1.976868146639626E196d, + -9.084495133765657E196d, + -1.2023077889892748E196d, + +5.7455368446308694E197d, + -1.7766273910482863E198d, + +3.5590470673352285E198d, + +1.1304970373249033E199d, + +1.6496143246803731E199d, + -2.394588390685223E199d, + -1.4677321100833294E199d, + -1.1843870433971731E201d, + -1.8853982316037226E201d, + +2.8829871423339434E201d, + +5.369687677705385E200d, + +1.8356062677502141E202d, + -1.5544655377217875E203d, + +2.955364187248884E203d, + -2.7651059253677425E203d, + +9.903174064539538E203d, + -3.284204788892967E204d, + -1.5843229740595697E205d, + +5.333371443528904E204d, + +1.2781631468016048E205d, + +3.2188292385399854E205d, + -6.619064395428225E206d, + +1.291561142865928E207d, + +1.3142988156905172E207d, + -1.3841980097978606E208d, + +6.380177790989479E207d, + +1.0386032577072378E209d, + +2.7681631086098026E209d, + -9.053874899534375E209d, + +1.2424707839848734E210d, + +1.045546633850141E211d, + -1.2448938139338362E211d, + +7.221902646057552E211d, + +6.651345415954053E211d, + -5.8180712702152444E212d, + +5.275183961165903E212d, + +5.092753117288608E212d, + -2.437796532151255E213d, + +1.3480763914637323E214d, + +5.619995933180841E214d, + +2.547000388735681E214d, + +4.817319356453926E214d, + -7.897146442236022E215d, + -7.93844120619577E215d, + -4.9489938500591624E216d, + -2.862720607805682E216d, + -2.9275804461593914E217d, + -3.411186219855533E217d, + -2.0110092718356274E218d, + -8.472642266772353E218d, + -4.357990742470246E217d, + +4.793444363780116E219d, + +1.6544084224626834E220d, + -6.017988576347111E220d, + -3.580397221598409E220d, + -4.7208848667217906E221d, + -7.724899660259369E221d, + -2.4459728627968634E222d, + +3.667348665023154E221d, + +4.544122762558404E223d, + -4.0573420909530794E223d, + -3.2552002992257195E223d, + -6.488296536838142E224d, + +1.7544839352461719E224d, + -4.0873400635183405E225d, + -8.833499967268279E225d, + -1.0953484767704112E226d, + -8.56825295972308E226d, + -1.8097633115378247E227d, + -6.171564449018882E227d, + -4.351843341274115E227d, + +2.8032429752543687E228d, + -1.0065901934522996E229d, + +9.863720960170636E228d, + -9.481088691357648E229d, + -1.6843492713373762E229d, + -1.3282890219894906E230d, + +6.883577595238845E230d, + -1.153577281189635E231d, + -8.009548754642203E231d, + -4.722612904888278E232d, + -4.768909872963015E232d, + +3.2542391242036633E233d, + +6.513425781583774E233d, + -1.8889614379831606E233d, + -2.227647301474917E234d, + -4.7971208532986115E234d, + +6.693500938105557E234d, + -6.587776621471115E234d, + +3.0099905634916516E236d, + -4.6694407626686244E235d, + +2.965546585110978E236d, + +5.771457643937893E237d, + -9.029878114318277E237d, + +8.169926810324408E237d, + -1.779945804977441E239d, + +4.1218749988429474E239d, + +7.201319954099161E239d, + -1.530845432304069E240d, + -3.861762510530086E240d, + -2.4090696463777446E241d, + -1.8196842273916379E241d, + -1.7959243076374794E242d, + -3.7257346819782323E242d, + +3.413310324247329E242d, + -2.0406580894051073E243d, + -1.5335923091350053E243d, + -1.056727406551016E244d, + -4.6753408714233723E244d, + -2.0697130057384643E245d, + -1.0356006160554071E245d, + +1.1339195187304043E246d, + +1.792783182582235E246d, + +9.599214853681978E245d, + +1.5367645598839362E247d, + +2.934570385464815E247d, + -1.6411525886171892E248d, + +2.2638862982382794E248d, + -1.2268014119628852E249d, + +4.737693450915584E247d, + +6.3818993714899675E249d, + +1.2639113706171572E250d, + -4.011320021817099E249d, + -5.2744376732859406E250d, + -3.732266217624991E251d, + +1.7591819833844019E252d, + -3.292458622014749E252d, + -9.161340309319204E252d, + -1.728610646009749E253d, + +1.1698424008604891E254d, + -1.8494343291160577E254d, + +2.0568656302182574E254d, + +1.0537591246531136E255d, + +1.803052068234866E254d, + -1.053036399720808E256d, + +2.1836166619192508E256d, + +1.0368403169781264E257d, + -2.0648015610276362E257d, + +8.426174035728768E257d, + -1.3577357192972777E258d, + +2.1313950901331177E258d, + +8.919141843592823E258d, + -1.1800039972549816E259d, + -1.1878772398311421E260d, + -1.538273497873993E260d, + -4.51305093266001E260d, + +1.1241179396053055E261d, + +6.154786508667658E261d, + -1.0626125049032536E262d, + -1.8908603201210102E262d, + -4.571195152299358E262d, + +1.526100002923062E263d, + -9.457084582570225E263d, + -1.5460500618825853E264d, + -5.598276199126451E264d, + -1.2074097381167957E265d, + -3.015972957475025E265d, + +1.4345106852061226E265d, + +8.28479585346867E265d, + -3.118741081244705E266d, + -1.2054747399765794E266d, + +3.4454766202661184E267d, + +1.1279135096919439E268d, + +1.2066382528772518E268d, + +1.1984128162292276E269d, + +3.685169705587367E268d, + +6.570047690198998E269d, + +1.8836492887460383E270d, + +7.4364594917181125E270d, + +1.2773080633674971E271d, + +1.8928981707279692E271d, + +4.039437286589528E271d, + +1.785277385538302E272d, + -6.017681359527226E272d, + +1.9716943051755635E273d, + -8.772048092842086E271d, + +1.5645672698520312E274d, + -3.7979660725865874E274d, + +5.324902289537048E274d, + -1.8806716685063293E274d, + +9.320900373401115E275d, + +1.4615985810260016E275d, + +8.321226457219046E276d, + -4.608112855795952E276d, + -3.476352191116455E277d, + +5.266381689434054E277d, + -9.622106063561645E277d, + +4.1719443712336026E278d, + +4.222411269063919E279d, + -6.714376022102489E279d, + -1.0732735585199074E280d, + -2.5866883048437488E280d, + -1.1306860837934988E281d, + +3.690690354793168E281d, + -5.5299180508885456E281d, + +2.7006726968568243E282d, + +4.135457669031131E282d, + +2.8401159516008676E283d, + +5.127265762024798E283d, + -3.4893601256685762E283d, + -1.145160459652136E283d, + +2.1742808735341656E284d, + +4.656972469326391E285d, + +7.672307991205681E285d, + +1.5781599575584034E286d, + +4.218682431618625E286d, + -2.4602260687026867E287d, + +2.7211316452521414E287d, + -1.8740018211089393E288d, + +2.6367639658206183E288d, + -3.102678910525039E288d, + +1.1992295328636466E289d, + +6.8190133180135345E289d, + +5.783203879030497E289d, + +5.171047077293295E290d, + +1.8396930096213817E290d, + +1.4977047507315718E290d, + +1.0672499803427623E292d, + +3.3310942289102464E291d, + -7.962256961838823E292d, + +1.7396889119023863E293d, + +3.8072183820435085E293d, + +2.2772059538865722E294d, + -2.0549866377878678E294d, + -1.2277120342804144E295d, + -3.609949022969024E295d, + +1.1479863663699871E296d, + -1.5314373779304356E296d, + -2.2537635160762597E296d, + -6.1370690793508674E296d, + -4.996854125490041E297d, + -6.883499809714189E297d, + -2.595456638706416E298d, + -1.1892631528580186E299d, + -1.4672600326020399E299d, + -3.200068509818696E299d, + -7.126913872617518E298d, + -3.3655587417265094E300d, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + Double.NaN, + }; + + /** + * Exponential over the range of 0 - 1 in increments of 2^-10 exp(x/1024) = expFracTableA[x] + + * expFracTableB[x]. 1024 = 2^10 + */ + private static final double[] EXP_FRAC_A = + new double[] { + +1.0d, + +1.0009770393371582d, + +1.0019550323486328d, + +1.0029339790344238d, + +1.0039138793945312d, + +1.004894733428955d, + +1.0058765411376953d, + +1.006859302520752d, + +1.007843017578125d, + +1.0088276863098145d, + +1.0098135471343994d, + +1.0108001232147217d, + +1.0117876529693604d, + +1.0127761363983154d, + +1.013765811920166d, + +1.014756202697754d, + +1.0157477855682373d, + +1.016740083694458d, + +1.0177335739135742d, + +1.0187277793884277d, + +1.0197231769561768d, + +1.0207195281982422d, + +1.021716833114624d, + +1.0227150917053223d, + +1.023714303970337d, + +1.024714469909668d, + +1.0257158279418945d, + +1.0267179012298584d, + +1.0277209281921387d, + +1.0287251472473145d, + +1.0297303199768066d, + +1.0307364463806152d, + +1.0317435264587402d, + +1.0327515602111816d, + +1.0337605476379395d, + +1.0347704887390137d, + +1.0357816219329834d, + +1.0367934703826904d, + +1.037806510925293d, + +1.038820505142212d, + +1.0398354530334473d, + +1.040851354598999d, + +1.0418684482574463d, + +1.0428862571716309d, + +1.043905258178711d, + +1.0449252128601074d, + +1.0459461212158203d, + +1.0469679832458496d, + +1.0479910373687744d, + +1.0490150451660156d, + +1.0500397682189941d, + +1.0510656833648682d, + +1.0520927906036377d, + +1.0531206130981445d, + +1.0541496276855469d, + +1.0551795959472656d, + +1.0562105178833008d, + +1.0572423934936523d, + +1.0582754611968994d, + +1.059309482574463d, + +1.0603444576263428d, + +1.061380386352539d, + +1.0624175071716309d, + +1.06345534324646d, + +1.0644943714141846d, + +1.0655345916748047d, + +1.066575527191162d, + +1.067617654800415d, + +1.0686607360839844d, + +1.0697050094604492d, + +1.0707499980926514d, + +1.071796178817749d, + +1.072843313217163d, + +1.0738916397094727d, + +1.0749409198760986d, + +1.075991153717041d, + +1.0770423412322998d, + +1.078094720840454d, + +1.0791480541229248d, + +1.080202341079712d, + +1.0812578201293945d, + +1.0823142528533936d, + +1.083371639251709d, + +1.08443021774292d, + +1.0854897499084473d, + +1.086550235748291d, + +1.0876119136810303d, + +1.088674545288086d, + +1.089738130569458d, + +1.0908029079437256d, + +1.0918686389923096d, + +1.092935562133789d, + +1.094003438949585d, + +1.0950722694396973d, + +1.096142053604126d, + +1.0972130298614502d, + +1.09828519821167d, + +1.099358320236206d, + +1.1004323959350586d, + +1.1015074253082275d, + +1.102583646774292d, + +1.103661060333252d, + +1.1047391891479492d, + +1.105818748474121d, + +1.1068990230560303d, + +1.107980489730835d, + +1.1090631484985352d, + +1.1101467609405518d, + +1.1112313270568848d, + +1.1123170852661133d, + +1.1134037971496582d, + +1.1144917011260986d, + +1.1155805587768555d, + +1.1166706085205078d, + +1.1177616119384766d, + +1.1188538074493408d, + +1.1199469566345215d, + +1.1210410594940186d, + +1.1221363544464111d, + +1.1232328414916992d, + +1.1243302822113037d, + +1.1254286766052246d, + +1.126528263092041d, + +1.127629041671753d, + +1.1287307739257812d, + +1.129833459854126d, + +1.1309373378753662d, + +1.132042407989502d, + +1.133148431777954d, + +1.1342556476593018d, + +1.1353638172149658d, + +1.1364731788635254d, + +1.1375834941864014d, + +1.1386950016021729d, + +1.1398074626922607d, + +1.1409211158752441d, + +1.142035961151123d, + +1.1431517601013184d, + +1.14426851272583d, + +1.1453864574432373d, + +1.14650559425354d, + +1.1476259231567383d, + +1.148747205734253d, + +1.149869441986084d, + +1.1509928703308105d, + +1.1521174907684326d, + +1.153243064880371d, + +1.154369831085205d, + +1.1554977893829346d, + +1.1566267013549805d, + +1.1577568054199219d, + +1.1588881015777588d, + +1.160020351409912d, + +1.161153793334961d, + +1.1622881889343262d, + +1.163423776626587d, + +1.1645605564117432d, + +1.1656982898712158d, + +1.166837215423584d, + +1.1679773330688477d, + +1.1691184043884277d, + +1.1702606678009033d, + +1.1714041233062744d, + +1.172548532485962d, + +1.173694133758545d, + +1.1748409271240234d, + +1.1759889125823975d, + +1.177137851715088d, + +1.1782879829406738d, + +1.1794393062591553d, + +1.1805915832519531d, + +1.1817450523376465d, + +1.1828997135162354d, + +1.1840553283691406d, + +1.1852121353149414d, + +1.1863701343536377d, + +1.1875293254852295d, + +1.1886897087097168d, + +1.1898510456085205d, + +1.1910135746002197d, + +1.1921772956848145d, + +1.1933419704437256d, + +1.1945080757141113d, + +1.1956751346588135d, + +1.1968433856964111d, + +1.1980125904083252d, + +1.1991832256317139d, + +1.200354814529419d, + +1.2015275955200195d, + +1.2027015686035156d, + +1.2038767337799072d, + +1.2050528526306152d, + +1.2062301635742188d, + +1.2074086666107178d, + +1.2085883617401123d, + +1.2097692489624023d, + +1.210951328277588d, + +1.2121343612670898d, + +1.2133188247680664d, + +1.2145042419433594d, + +1.2156908512115479d, + +1.2168786525726318d, + +1.2180676460266113d, + +1.2192575931549072d, + +1.2204489707946777d, + +1.2216413021087646d, + +1.222834825515747d, + +1.224029779434204d, + +1.2252256870269775d, + +1.2264227867126465d, + +1.227621078491211d, + +1.2288203239440918d, + +1.2300209999084473d, + +1.2312228679656982d, + +1.2324256896972656d, + +1.2336299419403076d, + +1.234835147857666d, + +1.23604154586792d, + +1.2372493743896484d, + +1.2384581565856934d, + +1.2396681308746338d, + +1.2408792972564697d, + +1.2420918941497803d, + +1.2433054447174072d, + +1.2445201873779297d, + +1.2457361221313477d, + +1.2469532489776611d, + +1.2481715679168701d, + +1.2493910789489746d, + +1.2506117820739746d, + +1.2518336772918701d, + +1.2530567646026611d, + +1.2542810440063477d, + +1.2555065155029297d, + +1.2567331790924072d, + +1.2579610347747803d, + +1.2591900825500488d, + +1.260420322418213d, + +1.2616519927978516d, + +1.2628846168518066d, + +1.2641184329986572d, + +1.2653534412384033d, + +1.266589879989624d, + +1.2678272724151611d, + +1.2690660953521729d, + +1.27030611038208d, + +1.2715470790863037d, + +1.272789478302002d, + +1.2740330696105957d, + +1.275277853012085d, + +1.2765238285064697d, + +1.27777099609375d, + +1.2790195941925049d, + +1.2802691459655762d, + +1.281519889831543d, + +1.2827720642089844d, + +1.2840254306793213d, + +1.2852799892425537d, + +1.2865357398986816d, + +1.287792682647705d, + +1.2890510559082031d, + +1.2903103828430176d, + +1.2915711402893066d, + +1.2928330898284912d, + +1.2940962314605713d, + +1.2953605651855469d, + +1.296626091003418d, + +1.2978930473327637d, + +1.2991611957550049d, + +1.3004305362701416d, + +1.3017010688781738d, + +1.3029727935791016d, + +1.304245948791504d, + +1.3055200576782227d, + +1.3067958354949951d, + +1.308072566986084d, + +1.3093504905700684d, + +1.3106298446655273d, + +1.3119103908538818d, + +1.3131921291351318d, + +1.3144752979278564d, + +1.3157594203948975d, + +1.317044973373413d, + +1.3183319568634033d, + +1.31961989402771d, + +1.3209092617034912d, + +1.322199821472168d, + +1.3234915733337402d, + +1.324784755706787d, + +1.3260791301727295d, + +1.3273746967315674d, + +1.3286716938018799d, + +1.329969882965088d, + +1.3312692642211914d, + +1.3325698375701904d, + +1.333871841430664d, + +1.3351752758026123d, + +1.336479663848877d, + +1.3377854824066162d, + +1.339092493057251d, + +1.3404009342193604d, + +1.3417105674743652d, + +1.3430213928222656d, + +1.3443336486816406d, + +1.3456470966339111d, + +1.3469617366790771d, + +1.3482778072357178d, + +1.349595069885254d, + +1.3509137630462646d, + +1.352233648300171d, + +1.3535549640655518d, + +1.3548774719238281d, + +1.356201171875d, + +1.3575263023376465d, + +1.3588526248931885d, + +1.360180139541626d, + +1.361509084701538d, + +1.3628394603729248d, + +1.364171028137207d, + +1.3655037879943848d, + +1.366837978363037d, + +1.368173360824585d, + +1.3695101737976074d, + +1.3708481788635254d, + +1.372187614440918d, + +1.373528242111206d, + +1.3748703002929688d, + +1.376213550567627d, + +1.3775582313537598d, + +1.378904104232788d, + +1.380251407623291d, + +1.3815999031066895d, + +1.3829498291015625d, + +1.384300947189331d, + +1.3856534957885742d, + +1.387007236480713d, + +1.3883624076843262d, + +1.389719009399414d, + +1.3910768032073975d, + +1.3924360275268555d, + +1.393796443939209d, + +1.395158290863037d, + +1.3965213298797607d, + +1.397885799407959d, + +1.3992514610290527d, + +1.4006187915802002d, + +1.401987075805664d, + +1.4033570289611816d, + +1.4047281742095947d, + +1.4061005115509033d, + +1.4074742794036865d, + +1.4088494777679443d, + +1.4102261066436768d, + +1.4116039276123047d, + +1.4129831790924072d, + +1.4143636226654053d, + +1.415745496749878d, + +1.4171288013458252d, + +1.418513298034668d, + +1.4198992252349854d, + +1.4212865829467773d, + +1.4226751327514648d, + +1.424065351486206d, + +1.4254565238952637d, + +1.426849365234375d, + +1.4282433986663818d, + +1.4296388626098633d, + +1.4310357570648193d, + +1.432433843612671d, + +1.433833360671997d, + +1.4352343082427979d, + +1.4366366863250732d, + +1.4380402565002441d, + +1.4394452571868896d, + +1.4408516883850098d, + +1.4422595500946045d, + +1.4436686038970947d, + +1.4450790882110596d, + +1.446491003036499d, + +1.447904348373413d, + +1.4493188858032227d, + +1.450735092163086d, + +1.4521524906158447d, + +1.4535713195800781d, + +1.454991340637207d, + +1.4564130306243896d, + +1.4578359127044678d, + +1.4592602252960205d, + +1.460686206817627d, + +1.4621131420135498d, + +1.4635417461395264d, + +1.4649717807769775d, + +1.4664030075073242d, + +1.4678359031677246d, + +1.4692699909210205d, + +1.470705509185791d, + +1.4721424579620361d, + +1.4735808372497559d, + +1.475020408630371d, + +1.47646164894104d, + +1.4779040813446045d, + +1.4793481826782227d, + +1.4807934761047363d, + +1.4822404384613037d, + +1.4836885929107666d, + +1.485138177871704d, + +1.4865891933441162d, + +1.488041639328003d, + +1.4894955158233643d, + +1.4909508228302002d, + +1.4924075603485107d, + +1.493865728378296d, + +1.4953253269195557d, + +1.49678635597229d, + +1.49824857711792d, + +1.4997124671936035d, + +1.5011777877807617d, + +1.5026445388793945d, + +1.504112720489502d, + +1.505582332611084d, + +1.5070531368255615d, + +1.5085256099700928d, + +1.5099995136260986d, + +1.511474847793579d, + +1.5129516124725342d, + +1.5144298076629639d, + +1.5159096717834473d, + +1.5173907279968262d, + +1.5188732147216797d, + +1.5203571319580078d, + +1.5218427181243896d, + +1.523329496383667d, + +1.524817943572998d, + +1.5263078212738037d, + +1.5277988910675049d, + +1.5292916297912598d, + +1.5307857990264893d, + +1.5322813987731934d, + +1.5337786674499512d, + +1.5352771282196045d, + +1.5367772579193115d, + +1.538278579711914d, + +1.5397815704345703d, + +1.5412859916687012d, + +1.5427920818328857d, + +1.5442993640899658d, + +1.5458080768585205d, + +1.547318458557129d, + +1.548830270767212d, + +1.5503435134887695d, + +1.5518584251403809d, + +1.5533745288848877d, + +1.5548923015594482d, + +1.5564115047454834d, + +1.5579321384429932d, + +1.5594542026519775d, + +1.5609779357910156d, + +1.5625030994415283d, + +1.5640296936035156d, + +1.5655577182769775d, + +1.5670874118804932d, + +1.5686185359954834d, + +1.5701510906219482d, + +1.5716853141784668d, + +1.5732207298278809d, + +1.5747578144073486d, + +1.5762965679168701d, + +1.577836513519287d, + +1.5793781280517578d, + +1.5809214115142822d, + +1.5824658870697021d, + +1.5840120315551758d, + +1.5855598449707031d, + +1.587108850479126d, + +1.5886595249176025d, + +1.5902118682861328d, + +1.5917654037475586d, + +1.593320608139038d, + +1.5948774814605713d, + +1.596435785293579d, + +1.5979955196380615d, + +1.5995566844940186d, + +1.6011195182800293d, + +1.6026840209960938d, + +1.6042497158050537d, + +1.6058173179626465d, + +1.6073861122131348d, + +1.6089565753936768d, + +1.6105287075042725d, + +1.6121022701263428d, + +1.6136772632598877d, + +1.6152539253234863d, + +1.6168320178985596d, + +1.6184117794036865d, + +1.619992971420288d, + +1.6215758323669434d, + +1.6231601238250732d, + +1.6247460842132568d, + +1.626333475112915d, + +1.627922534942627d, + +1.6295130252838135d, + +1.6311051845550537d, + +1.6326987743377686d, + +1.634294033050537d, + +1.6358907222747803d, + +1.6374890804290771d, + +1.6390891075134277d, + +1.640690565109253d, + +1.6422934532165527d, + +1.6438980102539062d, + +1.6455042362213135d, + +1.6471118927001953d, + +1.6487212181091309d, + +1.6503322124481201d, + +1.651944637298584d, + +1.6535584926605225d, + +1.6551742553710938d, + +1.6567914485931396d, + +1.6584100723266602d, + +1.6600303649902344d, + +1.6616523265838623d, + +1.663275957107544d, + +1.6649010181427002d, + +1.666527509689331d, + +1.6681559085845947d, + +1.669785737991333d, + +1.671417236328125d, + +1.6730501651763916d, + +1.674684762954712d, + +1.676321029663086d, + +1.6779589653015137d, + +1.679598331451416d, + +1.681239366531372d, + +1.6828820705413818d, + +1.6845262050628662d, + +1.6861720085144043d, + +1.687819480895996d, + +1.6894686222076416d, + +1.6911191940307617d, + +1.6927716732025146d, + +1.6944255828857422d, + +1.6960809230804443d, + +1.6977381706237793d, + +1.6993968486785889d, + +1.7010571956634521d, + +1.7027192115783691d, + +1.7043828964233398d, + +1.7060482501983643d, + +1.7077150344848633d, + +1.709383487701416d, + +1.7110536098480225d, + +1.7127254009246826d, + +1.7143988609313965d, + +1.716073989868164d, + +1.7177505493164062d, + +1.7194287776947021d, + +1.7211089134216309d, + +1.7227904796600342d, + +1.7244737148284912d, + +1.726158618927002d, + +1.7278449535369873d, + +1.7295331954956055d, + +1.7312231063842773d, + +1.7329144477844238d, + +1.7346076965332031d, + +1.736302375793457d, + +1.7379989624023438d, + +1.739696979522705d, + +1.7413966655731201d, + +1.7430980205535889d, + +1.7448012828826904d, + +1.7465059757232666d, + +1.7482123374938965d, + +1.74992036819458d, + +1.7516300678253174d, + +1.7533416748046875d, + +1.7550547122955322d, + +1.7567694187164307d, + +1.7584857940673828d, + +1.7602040767669678d, + +1.7619237899780273d, + +1.7636451721191406d, + +1.7653684616088867d, + +1.7670931816101074d, + +1.768819808959961d, + +1.770547866821289d, + +1.77227783203125d, + +1.7740094661712646d, + +1.775742769241333d, + +1.777477741241455d, + +1.7792143821716309d, + +1.7809526920318604d, + +1.7826926708221436d, + +1.7844345569610596d, + +1.7861778736114502d, + +1.7879230976104736d, + +1.7896699905395508d, + +1.7914185523986816d, + +1.7931687831878662d, + +1.7949209213256836d, + +1.7966744899749756d, + +1.7984299659729004d, + +1.800187110900879d, + +1.8019459247589111d, + +1.8037066459655762d, + +1.8054687976837158d, + +1.8072328567504883d, + +1.8089985847473145d, + +1.8107659816741943d, + +1.812535285949707d, + +1.8143062591552734d, + +1.8160789012908936d, + +1.8178532123565674d, + +1.819629430770874d, + +1.8214070796966553d, + +1.8231868743896484d, + +1.8249680995941162d, + +1.8267512321472168d, + +1.828536033630371d, + +1.830322504043579d, + +1.83211088180542d, + +1.8339009284973145d, + +1.8356926441192627d, + +1.8374862670898438d, + +1.8392815589904785d, + +1.841078519821167d, + +1.8428773880004883d, + +1.8446779251098633d, + +1.846480131149292d, + +1.8482842445373535d, + +1.8500902652740479d, + +1.8518977165222168d, + +1.8537070751190186d, + +1.8555183410644531d, + +1.8573312759399414d, + +1.8591458797454834d, + +1.8609623908996582d, + +1.8627805709838867d, + +1.864600658416748d, + +1.866422414779663d, + +1.8682458400726318d, + +1.8700714111328125d, + +1.8718984127044678d, + +1.8737273216247559d, + +1.8755581378936768d, + +1.8773906230926514d, + +1.8792247772216797d, + +1.8810608386993408d, + +1.8828988075256348d, + +1.8847384452819824d, + +1.886579990386963d, + +1.888423204421997d, + +1.890268325805664d, + +1.8921151161193848d, + +1.8939638137817383d, + +1.8958141803741455d, + +1.8976664543151855d, + +1.8995206356048584d, + +1.901376485824585d, + +1.9032342433929443d, + +1.9050939083099365d, + +1.9069552421569824d, + +1.908818244934082d, + +1.9106833934783936d, + +1.9125502109527588d, + +1.9144186973571777d, + +1.9162893295288086d, + +1.9181616306304932d, + +1.9200356006622314d, + +1.9219114780426025d, + +1.9237892627716064d, + +1.9256689548492432d, + +1.9275505542755127d, + +1.929433822631836d, + +1.931318759918213d, + +1.9332058429718018d, + +1.9350945949554443d, + +1.9369852542877197d, + +1.938877820968628d, + +1.940772294998169d, + +1.9426684379577637d, + +1.9445664882659912d, + +1.9464664459228516d, + +1.9483680725097656d, + +1.9502718448638916d, + +1.9521772861480713d, + +1.9540846347808838d, + +1.955993890762329d, + +1.9579050540924072d, + +1.959817886352539d, + +1.9617326259613037d, + +1.9636495113372803d, + +1.9655680656433105d, + +1.9674885272979736d, + +1.9694106578826904d, + +1.9713349342346191d, + +1.9732608795166016d, + +1.975188970565796d, + +1.977118730545044d, + +1.9790503978729248d, + +1.9809842109680176d, + +1.982919692993164d, + +1.9848570823669434d, + +1.9867963790893555d, + +1.9887375831604004d, + +1.990680456161499d, + +1.9926254749298096d, + +1.994572401046753d, + +1.996521234512329d, + +1.998471736907959d, + +2.000424385070801d, + +2.0023789405822754d, + +2.004335403442383d, + +2.006293773651123d, + +2.008254051208496d, + +2.010216236114502d, + +2.0121798515319824d, + +2.014145851135254d, + +2.016113758087158d, + +2.0180835723876953d, + +2.0200552940368652d, + +2.022029399871826d, + +2.0240049362182617d, + +2.02598237991333d, + +2.0279617309570312d, + +2.0299429893493652d, + +2.0319266319274902d, + +2.03391170501709d, + +2.0358991622924805d, + +2.0378880500793457d, + +2.039879322052002d, + +2.041872501373291d, + +2.0438671112060547d, + +2.0458641052246094d, + +2.047863006591797d, + +2.049863815307617d, + +2.0518670082092285d, + +2.0538716316223145d, + +2.055878162384033d, + +2.057887077331543d, + +2.0598974227905273d, + +2.0619101524353027d, + +2.063924789428711d, + +2.065941333770752d, + +2.067959785461426d, + +2.0699801445007324d, + +2.07200288772583d, + +2.0740270614624023d, + +2.0760536193847656d, + +2.0780820846557617d, + +2.0801124572753906d, + +2.0821447372436523d, + +2.084178924560547d, + +2.0862154960632324d, + +2.0882534980773926d, + +2.0902938842773438d, + +2.0923361778259277d, + +2.0943803787231445d, + +2.0964269638061523d, + +2.0984749794006348d, + +2.100525379180908d, + +2.1025776863098145d, + +2.1046319007873535d, + +2.1066884994506836d, + +2.1087465286254883d, + +2.110806941986084d, + +2.1128692626953125d, + +2.114933490753174d, + +2.117000102996826d, + +2.1190686225891113d, + +2.1211390495300293d, + +2.12321138381958d, + +2.1252856254577637d, + +2.1273622512817383d, + +2.1294407844543457d, + +2.131521224975586d, + +2.133604049682617d, + +2.135688304901123d, + +2.13777494430542d, + +2.139863967895508d, + +2.1419544219970703d, + +2.144047260284424d, + +2.14614200592041d, + +2.1482391357421875d, + +2.1503376960754395d, + +2.1524391174316406d, + +2.1545419692993164d, + +2.156647205352783d, + +2.1587538719177246d, + +2.1608633995056152d, + +2.1629743576049805d, + +2.1650876998901367d, + +2.167203426361084d, + +2.169320583343506d, + +2.1714401245117188d, + +2.1735615730285645d, + +2.175685405731201d, + +2.1778111457824707d, + +2.179938793182373d, + +2.1820688247680664d, + +2.1842007637023926d, + +2.1863350868225098d, + +2.1884708404541016d, + +2.1906094551086426d, + +2.192749500274658d, + +2.194891929626465d, + +2.1970362663269043d, + +2.1991829872131348d, + +2.201331615447998d, + +2.2034826278686523d, + +2.2056355476379395d, + +2.2077903747558594d, + +2.2099475860595703d, + +2.212106704711914d, + +2.214268207550049d, + +2.2164316177368164d, + +2.218596935272217d, + +2.220764636993408d, + +2.2229342460632324d, + +2.2251062393188477d, + +2.2272801399230957d, + +2.2294564247131348d, + +2.2316346168518066d, + +2.2338151931762695d, + +2.2359976768493652d, + +2.2381820678710938d, + +2.2403693199157715d, + +2.242558002471924d, + +2.244749069213867d, + +2.2469425201416016d, + +2.2491378784179688d, + +2.2513351440429688d, + +2.2535347938537598d, + +2.2557363510131836d, + +2.2579402923583984d, + +2.2601466178894043d, + +2.262354850769043d, + +2.2645654678344727d, + +2.266777992248535d, + +2.2689924240112305d, + +2.271209716796875d, + +2.273428440093994d, + +2.2756495475769043d, + +2.2778730392456055d, + +2.2800989151000977d, + +2.2823266983032227d, + +2.2845563888549805d, + +2.2867884635925293d, + +2.289022922515869d, + +2.291259288787842d, + +2.2934980392456055d, + +2.295738697052002d, + +2.2979817390441895d, + +2.300227165222168d, + +2.3024744987487793d, + +2.3047242164611816d, + +2.306975841522217d, + +2.309229850769043d, + +2.31148624420166d, + +2.31374454498291d, + +2.316005229949951d, + +2.318267822265625d, + +2.32053279876709d, + +2.3228001594543457d, + +2.3250694274902344d, + +2.3273415565490723d, + +2.3296151161193848d, + +2.3318915367126465d, + +2.334169864654541d, + +2.3364500999450684d, + +2.338733196258545d, + +2.3410181999206543d, + +2.3433055877685547d, + +2.345594882965088d, + +2.347886562347412d, + +2.3501806259155273d, + +2.3524770736694336d, + +2.3547754287719727d, + +2.3570761680603027d, + +2.3593788146972656d, + +2.3616843223571777d, + +2.3639917373657227d, + +2.3663015365600586d, + +2.3686132431030273d, + +2.370927333831787d, + +2.373243808746338d, + +2.3755626678466797d, + +2.3778839111328125d, + +2.380207061767578d, + +2.3825325965881348d, + +2.3848605155944824d, + +2.387190818786621d, + +2.3895230293273926d, + +2.391857624053955d, + +2.3941946029663086d, + +2.396533966064453d, + +2.3988752365112305d, + +2.401218891143799d, + +2.4035654067993164d, + +2.4059133529663086d, + +2.40826416015625d, + +2.4106173515319824d, + +2.4129724502563477d, + +2.415329933166504d, + +2.417689800262451d, + +2.4200520515441895d, + +2.4224166870117188d, + +2.424783229827881d, + +2.427152633666992d, + +2.4295239448547363d, + +2.4318976402282715d, + +2.4342737197875977d, + +2.436652183532715d, + +2.439032554626465d, + +2.441415786743164d, + +2.4438014030456543d, + +2.4461889266967773d, + +2.4485788345336914d, + +2.4509711265563965d, + +2.4533658027648926d, + +2.4557628631591797d, + +2.458162307739258d, + +2.460564136505127d, + +2.462968349456787d, + +2.46537446975708d, + +2.4677834510803223d, + +2.4701943397521973d, + +2.4726080894470215d, + +2.4750237464904785d, + +2.4774417877197266d, + +2.479862689971924d, + +2.482285499572754d, + +2.484710693359375d, + +2.487138271331787d, + +2.4895682334899902d, + +2.4920010566711426d, + +2.4944357872009277d, + +2.496872901916504d, + +2.499312400817871d, + +2.5017542839050293d, + +2.5041985511779785d, + +2.5066452026367188d, + +2.50909423828125d, + +2.5115456581115723d, + +2.5139999389648438d, + +2.516456127166748d, + +2.5189146995544434d, + +2.5213756561279297d, + +2.5238394737243652d, + +2.5263051986694336d, + +2.528773307800293d, + +2.5312442779541016d, + +2.533717155456543d, + +2.5361928939819336d, + +2.538670539855957d, + +2.5411510467529297d, + +2.5436339378356934d, + +2.546119213104248d, + +2.5486068725585938d, + +2.5510969161987305d, + +2.553589344024658d, + +2.556084632873535d, + +2.558581829071045d, + +2.5610814094543457d, + +2.5635838508605957d, + +2.5660886764526367d, + +2.5685958862304688d, + +2.571105480194092d, + +2.573617458343506d, + +2.576131820678711d, + +2.5786490440368652d, + +2.5811686515808105d, + +2.5836901664733887d, + +2.586214542388916d, + +2.5887417793273926d, + +2.591270923614502d, + +2.5938024520874023d, + +2.596336841583252d, + +2.5988736152648926d, + +2.601412773132324d, + +2.603954315185547d, + +2.6064987182617188d, + +2.6090455055236816d, + +2.6115946769714355d, + +2.6141462326049805d, + +2.6167001724243164d, + +2.6192569732666016d, + +2.6218161582946777d, + +2.624377727508545d, + +2.626941680908203d, + +2.6295084953308105d, + +2.632077217102051d, + +2.6346492767333984d, + +2.637223243713379d, + +2.6398000717163086d, + +2.6423792839050293d, + +2.644960880279541d, + +2.6475448608398438d, + +2.6501317024230957d, + +2.6527209281921387d, + +2.655313014984131d, + +2.657907009124756d, + +2.6605043411254883d, + +2.6631035804748535d, + +2.665705680847168d, + +2.6683101654052734d, + +2.67091703414917d, + +2.6735267639160156d, + +2.6761388778686523d, + +2.67875337600708d, + +2.681370735168457d, + +2.683990478515625d, + +2.686613082885742d, + +2.689237594604492d, + +2.6918654441833496d, + +2.69449520111084d, + +2.6971278190612793d, + +2.699763298034668d, + +2.7024011611938477d, + +2.7050414085388184d, + +2.70768404006958d, + +2.710329532623291d, + +2.712977886199951d, + +2.7156286239624023d, + +2.7182817459106445d, + }; + + /** + * Exponential over the range of 0 - 1 in increments of 2^-10 exp(x/1024) = expFracTableA[x] + + * expFracTableB[x]. + */ + private static final double[] EXP_FRAC_B = + new double[] { + +0.0d, + +1.552583321178453E-10d, + +1.2423699995465188E-9d, + +4.194022929828008E-9d, + +9.94381632344361E-9d, + +1.9426261544163577E-8d, + +3.3576783010266685E-8d, + +5.3331719086630523E-8d, + +7.962832297769345E-8d, + +1.1340476362128895E-7d, + -8.281845251820919E-8d, + -3.126416414805498E-8d, + +3.058997113995161E-8d, + +1.0368579417304741E-7d, + -4.9452513107409435E-8d, + +4.8955889659397494E-8d, + -7.698155155722897E-8d, + +5.051784853384516E-8d, + -4.443661736519001E-8d, + +1.1593958457401774E-7d, + +5.575759739697068E-8d, + +1.4385227981629147E-8d, + -7.227368462584163E-9d, + -8.129108387083023E-9d, + +1.263202100290635E-8d, + +5.600896265625552E-8d, + -1.154629885168314E-7d, + -2.399186832888246E-8d, + +9.295948298604103E-8d, + -2.070841011504222E-9d, + -6.97066538508643E-8d, + -1.0898941254272996E-7d, + -1.1895963756343625E-7d, + -9.865691193993138E-8d, + -4.711988033385175E-8d, + +3.6613751875298095E-8d, + -8.491135959370133E-8d, + +6.610611940107793E-8d, + +1.3794148633283659E-8d, + -2.462631860370667E-9d, + +1.830278273495162E-8d, + +7.705834203598065E-8d, + -6.364563771711373E-8d, + +7.39978436695387E-8d, + +1.4122417557484554E-8d, + -3.881598887298574E-9d, + +2.0958481826069642E-8d, + +8.96162975425619E-8d, + -3.535214171178576E-8d, + -1.1455271549574576E-7d, + +9.140964977432485E-8d, + +1.0667524445105459E-7d, + -6.777752790396222E-8d, + +4.586785041291296E-8d, + -2.8245462428022094E-8d, + -5.071761314397018E-8d, + -2.0566368810068663E-8d, + +6.319146317890346E-8d, + -3.687854305539139E-8d, + -8.137269363160008E-8d, + -6.930491127388755E-8d, + +3.1184473002226595E-10d, + -1.0995299963140049E-7d, + +7.772668425499348E-8d, + +8.750367485925089E-8d, + -7.963112393823186E-8d, + +5.415131809829094E-8d, + +1.3006683896462346E-8d, + +3.634736373360733E-8d, + -1.132504393233074E-7d, + +4.2046187038837375E-8d, + +2.6396811618001066E-8d, + +7.92177143584738E-8d, + -3.691100820545433E-8d, + -8.257112559083188E-8d, + -5.676200971739166E-8d, + +4.151794514828518E-8d, + -2.5147255753587636E-8d, + -1.7335469415174996E-8d, + +6.595784859136531E-8d, + -1.2680354928109105E-8d, + -1.3824992526093461E-8d, + +6.353142754175797E-8d, + -1.8021197722549054E-8d, + -1.9054827792903468E-8d, + +6.144098503892116E-8d, + -1.3940903373095247E-8d, + -5.7694907599522404E-9d, + +8.696863522320578E-8d, + +2.6869297963554945E-8d, + +5.3366470162689076E-8d, + -7.094204160127543E-8d, + -1.0662027949814858E-7d, + -5.26498707801063E-8d, + +9.198855229106814E-8d, + +8.989677431456647E-8d, + -5.790384407322479E-8d, + -1.1197236522467887E-7d, + -7.12854317090566E-8d, + +6.51813137650059E-8d, + +6.003465022483798E-8d, + -8.569906238528267E-8d, + +1.0584469687624562E-7d, + -7.956144278281947E-8d, + +7.43676272093501E-8d, + +9.182512565315022E-8d, + -2.6157563728873715E-8d, + -4.012947040998503E-8d, + +5.094280572218447E-8d, + +9.675095351161728E-9d, + +7.552139802281006E-8d, + +1.1099566726533146E-8d, + +5.58656252899437E-8d, + -2.756054703800197E-8d, + +2.791018095971047E-10d, + -9.799351869734466E-8d, + -8.291832428736212E-8d, + +4.654720780112994E-8d, + +5.302803981406403E-8d, + -6.243126731995636E-8d, + -6.036655299348577E-8d, + +6.026878587378257E-8d, + +6.210379583313526E-8d, + -5.381287389094251E-8d, + -4.8012970400697E-8d, + +8.055420567281602E-8d, + +9.452180117175641E-8d, + -5.057430382371206E-9d, + +2.1288872215266507E-8d, + -6.380305844689076E-8d, + -2.0858800984600168E-8d, + -8.724006061713588E-8d, + -2.3470351753125604E-8d, + -6.690931338790221E-8d, + +2.192160831263035E-8d, + +5.6648446166177225E-9d, + -1.1461755745719884E-7d, + -9.944393412663547E-8d, + +5.2249837964645906E-8d, + +1.0311034276196487E-7d, + +5.4203784018566126E-8d, + -9.340259278913173E-8d, + -1.0022192034216903E-7d, + +3.481513333662908E-8d, + +7.436036590244714E-8d, + +1.9485199912395296E-8d, + +1.0968068384729757E-7d, + +1.0760175582979094E-7d, + +1.4322981952798675E-8d, + +6.933855730431659E-8d, + +3.530656968851287E-8d, + -8.669526204279467E-8d, + -5.7169586962345785E-8d, + -1.1345515834332824E-7d, + -1.605251622332555E-8d, + -2.298302779758532E-9d, + -7.110952399338234E-8d, + +1.70164513845372E-8d, + +2.4746155561368937E-8d, + -4.6834239957353325E-8d, + +4.1781076667923185E-8d, + +5.326182134294869E-8d, + -1.1302647617762544E-8d, + +8.759667154796094E-8d, + +1.126326877851684E-7d, + +6.48979555673987E-8d, + -5.451390316294111E-8d, + -6.0896188500539086E-9d, + -2.7152010585461855E-8d, + -1.1660424775832058E-7d, + -3.492984900939992E-8d, + -1.944841848873016E-8d, + -6.905990750285027E-8d, + +5.575538653428039E-8d, + +1.1768108384670781E-7d, + +1.178204606523101E-7d, + +5.727787111340131E-8d, + -6.284125161007433E-8d, + -3.0118152047565877E-9d, + -5.448044533034374E-10d, + -5.433154287341921E-8d, + +7.515630833946181E-8d, + -8.780756503572527E-8d, + -6.527407547535494E-8d, + -9.45487863616303E-8d, + +6.390098458668406E-8d, + -6.564672913105876E-8d, + -5.238488022920792E-9d, + +7.824500749252316E-9d, + -2.5339299158309795E-8d, + -1.036103313062145E-7d, + +1.2550633697348567E-8d, + +8.584676196065558E-8d, + +1.1740089468291563E-7d, + +1.0833697012353316E-7d, + +5.978002467397905E-8d, + -2.7143806069290897E-8d, + +8.711129287069315E-8d, + -7.316349947981893E-8d, + -3.00015852582934E-8d, + -2.0691000399732483E-8d, + -4.4100097152254264E-8d, + -9.909612209943178E-8d, + +5.38733640215475E-8d, + -6.0893829005035E-8d, + +3.457553391989844E-8d, + +1.0300006058273187E-7d, + -9.290053015365092E-8d, + -7.514966995961323E-8d, + -8.10254145615142E-8d, + -1.0938612624777085E-7d, + +7.932952721989251E-8d, + +9.428257290008738E-9d, + -7.952636967837795E-8d, + +5.203033137154554E-8d, + -7.159157201731446E-8d, + +2.7593424989059015E-8d, + +1.1231621190000476E-7d, + -5.469119869891027E-8d, + +4.560067256086347E-9d, + +5.280427179595944E-8d, + +9.119538242455128E-8d, + -1.1753008498403413E-7d, + -9.537874867759656E-8d, + -7.96118345325538E-8d, + -6.907085854395348E-8d, + -6.259620482221904E-8d, + -5.902712448725381E-8d, + -5.720173456146447E-8d, + -5.5957016861703E-8d, + -5.412881689012608E-8d, + -5.0551842723970724E-8d, + -4.405966390424518E-8d, + -3.348471032333413E-8d, + -1.7658271111516935E-8d, + +4.589506477601956E-9d, + +3.4429618182751655E-8d, + +7.303420385174346E-8d, + -1.168420305422519E-7d, + -5.718749537552229E-8d, + +1.4754809136835937E-8d, + +1.001616104682875E-7d, + -3.8207793300052055E-8d, + +7.766278405014509E-8d, + -2.7883635712109803E-8d, + -1.1524714043067699E-7d, + +5.517333625963128E-8d, + +7.724278756071081E-9d, + -1.7990934773848504E-8d, + -2.0786347668702902E-8d, + +5.251554594269693E-10d, + +4.7131849857076246E-8d, + -1.1819540733893871E-7d, + -1.742885956093543E-8d, + +1.1220467571570283E-7d, + +3.347954541376715E-8d, + -1.399157980498908E-8d, + -2.9013441705763093E-8d, + -1.0389614239253089E-8d, + +4.307749759934266E-8d, + -1.0583192018912101E-7d, + +2.0919226941745448E-8d, + -5.2305110482722706E-8d, + -8.588407110184028E-8d, + -7.861419797923639E-8d, + -2.929085835358592E-8d, + +6.329175751021792E-8d, + -3.807794163054899E-8d, + -9.377320954068088E-8d, + -1.0258469865953145E-7d, + -6.330187984612758E-8d, + +2.5286958775281306E-8d, + -7.40238661307607E-8d, + +1.1681688445204168E-7d, + -1.1623125976292733E-7d, + -5.6696107089038004E-8d, + +5.822140627806124E-8d, + -8.678466172071259E-9d, + -1.7757121899175995E-8d, + +3.220665454652531E-8d, + -9.598330731102836E-8d, + +7.573375369829243E-8d, + +7.174547784678893E-8d, + -1.0672213971363184E-7d, + +1.8395252217743006E-8d, + -2.8511112548600118E-8d, + -7.79306270997787E-9d, + +8.178019529487065E-8d, + +3.0220784595602374E-9d, + -4.4156343103298585E-9d, + +6.07014616741277E-8d, + -3.8809601937571554E-8d, + -6.329342805230603E-8d, + -1.1511990258493999E-8d, + +1.177739474561431E-7d, + +8.738625278484571E-8d, + -1.0143341551207646E-7d, + +2.9394972678456236E-8d, + +4.278345398213486E-9d, + +6.28805835150457E-8d, + -3.197037359731606E-8d, + -4.060821046423735E-8d, + +3.82160283750664E-8d, + -3.2666060441373307E-8d, + -1.3584500601329896E-8d, + +9.671332777035621E-8d, + +6.10626893063691E-8d, + +1.1913723189736356E-7d, + +3.3774671482641995E-8d, + +4.4651109654500895E-8d, + -8.539328154875224E-8d, + -1.166799420361101E-7d, + -4.794765976694151E-8d, + -1.1635256954820579E-7d, + -8.221241452580445E-8d, + +5.5737717715868425E-8d, + +6.034539636024073E-8d, + -6.712199323081945E-8d, + -8.697724830833087E-8d, + +2.0494942705297694E-9d, + -3.718924074653624E-8d, + +3.499747150995707E-8d, + -1.8535359161566028E-8d, + +4.1905679587096103E-8d, + -2.0821912536551675E-8d, + +3.297776915751238E-8d, + -3.3835280846270374E-8d, + +1.8437339356553904E-8d, + -4.734187609526424E-8d, + +8.527976799299225E-9d, + -5.1088103279787804E-8d, + +1.3513294656751725E-8d, + -3.480032127343472E-8d, + +4.367697180842916E-8d, + +1.1815196363705356E-8d, + +1.0932279207149782E-7d, + +9.907230065250944E-8d, + -1.764389559496152E-8d, + -1.1135725625095859E-9d, + -8.846040040259342E-8d, + -3.996962588736431E-8d, + -9.276238757878814E-8d, + -7.12139818505956E-9d, + -2.016525972830718E-8d, + +1.0782585410141121E-7d, + -9.868269632073771E-8d, + +7.686861750031585E-8d, + -7.947087669425045E-8d, + -8.955768055535647E-8d, + +4.791582240886607E-8d, + +9.583994718167641E-8d, + +5.5524866689108584E-8d, + -7.171796605211277E-8d, + -4.6157237582310713E-8d, + -1.0489751005162237E-7d, + -8.204903560604627E-9d, + +6.818588687884566E-9d, + -5.850916105103205E-8d, + +3.5549586192569994E-8d, + +5.1896700056778354E-8d, + -8.146080588190463E-9d, + +9.516285362051742E-8d, + -1.1368933260611668E-7d, + +8.187871486648885E-8d, + -3.206182925646474E-8d, + +2.265440168347286E-8d, + +8.938334752179552E-9d, + -7.187922490287331E-8d, + +1.9952407216533937E-8d, + +4.734805892507655E-8d, + +1.1642439930208906E-8d, + -8.582843599651953E-8d, + -5.3086706437795354E-9d, + +1.6121782610217253E-8d, + -2.0197142620980974E-8d, + -1.129242035557684E-7d, + -2.2298267863810133E-8d, + +1.4605950309628873E-8d, + -8.663710700190489E-10d, + -6.736873974532501E-8d, + +5.486523121881414E-8d, + -1.0965249168570443E-7d, + -8.27343074126263E-8d, + -1.0144703278439455E-7d, + +7.39809943048038E-8d, + -3.193297932837415E-8d, + +5.900393284617182E-8d, + +1.0973020465397083E-7d, + -1.1681436418514489E-7d, + +9.5985669644661E-8d, + +3.423560333632085E-8d, + -6.22836197265283E-8d, + +4.621027492345726E-8d, + -1.1575484316683829E-7d, + -6.997545435826076E-8d, + -5.3502441327259514E-8d, + -6.49667713553005E-8d, + -1.029980741248172E-7d, + +7.219393868923887E-8d, + -1.4854841678687828E-8d, + +1.1406713393562271E-7d, + -1.650155887561251E-8d, + +7.165331603232264E-8d, + -9.692697614257269E-8d, + -4.402550702194912E-8d, + -6.679737442193143E-9d, + +1.6492800268960003E-8d, + +2.68759245092879E-8d, + +2.5854805721793077E-8d, + +1.4815967715704613E-8d, + -4.852711011229633E-9d, + -3.176199594915881E-8d, + -6.452129525125173E-8d, + -1.01738658407525E-7d, + +9.639780418418697E-8d, + +5.4445606140746644E-8d, + +1.2219361033150988E-8d, + -2.8883532688356087E-8d, + -6.746431126005811E-8d, + -1.0212284427080097E-7d, + +1.0696094577483825E-7d, + +8.43527683868743E-8d, + +6.987544103716777E-8d, + +6.493457409236137E-8d, + +7.093715125593688E-8d, + +8.929153091001965E-8d, + -1.1701113164306871E-7d, + -6.972256643013266E-8d, + -5.848862070736576E-9d, + +7.602385197610123E-8d, + -6.110775144284437E-8d, + +6.101012058093429E-8d, + -3.304167134225169E-8d, + -1.0342514383702196E-7d, + +8.969907328603505E-8d, + +7.091600108064668E-8d, + +8.006778743052707E-8d, + +1.1857939200074815E-7d, + -5.0541412403312774E-8d, + +5.0970277930552287E-8d, + -5.229355472795119E-8d, + +1.1793478462381443E-7d, + +8.625007227318527E-8d, + +9.250422086873268E-8d, + -1.0028661472061573E-7d, + -1.384914052949463E-8d, + +1.1483560326413004E-7d, + +4.878798101459259E-8d, + +2.7866921183936055E-8d, + +5.3514180410849046E-8d, + -1.1124565511436785E-7d, + +1.186914813275767E-8d, + -5.253258132241335E-8d, + -6.458486486369316E-8d, + -2.2838888809969377E-8d, + +7.415557606805398E-8d, + -1.0568403170659571E-8d, + -3.7139182948393606E-8d, + -4.1022790876160215E-9d, + +8.999821367768787E-8d, + +8.201043988912348E-9d, + -9.616457442665051E-9d, + +3.8005886250603055E-8d, + -8.588890051473289E-8d, + +9.699937202692456E-8d, + +1.11298006674538E-7d, + -4.1527104733570825E-8d, + +1.1682852007826251E-7d, + +1.1099648061301941E-7d, + -5.755303038890997E-8d, + +8.948877445235827E-8d, + +7.675780395028194E-8d, + -9.427143563390596E-8d, + +5.471416081500162E-8d, + +4.8354824064383506E-8d, + -1.118706134478866E-7d, + +5.235528379688445E-8d, + +6.567708120053687E-8d, + -7.042204992948526E-8d, + -1.1603891006723397E-7d, + -6.968742825553785E-8d, + +7.01199184127881E-8d, + +6.645352711199266E-8d, + -7.919617109348822E-8d, + +1.1149986927391714E-7d, + -7.522074418324674E-8d, + +7.739252980388984E-8d, + +9.39987974788905E-8d, + -2.390421480210064E-8d, + -3.639873824357815E-8d, + +5.8015881615938497E-8d, + +2.2423186335040668E-8d, + +9.674534330665206E-8d, + +4.4068830785712375E-8d, + +1.0431875573076199E-7d, + +4.0584538834428926E-8d, + +9.279423236781974E-8d, + +2.404020521381534E-8d, + +7.425346071427343E-8d, + +6.529321706138789E-9d, + +6.080174837146273E-8d, + +1.6902327633329284E-10d, + +6.456806922371733E-8d, + +1.7100134295216033E-8d, + +9.770510970673519E-8d, + +6.94872148530716E-8d, + -6.602926393514549E-8d, + -6.889997193778161E-8d, + +6.240235720677117E-8d, + +9.098790295810902E-8d, + +1.8386917534879182E-8d, + +8.454972737414241E-8d, + +5.259099728747365E-8d, + -7.595453077213505E-8d, + -6.113203624663034E-8d, + +9.859622328905143E-8d, + -7.206766550807255E-8d, + -9.474579567171831E-8d, + +3.210408693366267E-8d, + +7.160716418525417E-8d, + +2.530870537724554E-8d, + -1.0524451040704701E-7d, + -8.008561371849434E-8d, + +1.0233519853128553E-7d, + -3.326791455362767E-8d, + -8.504961764629757E-9d, + -6.024017201863256E-8d, + +5.1500902632092514E-8d, + +8.98570720774568E-8d, + +5.638724693948384E-8d, + -4.734813904255994E-8d, + +1.8631451577542948E-8d, + +1.7470924137873214E-8d, + -4.926470933588261E-8d, + +5.84096713620797E-8d, + +1.0364355880696472E-7d, + +8.800655674349468E-8d, + +1.3069802481237792E-8d, + +1.1882454749452428E-7d, + -6.999215748398631E-8d, + -7.49674072510849E-8d, + +1.054760847603618E-7d, + -3.920012014371067E-9d, + +7.526183084319617E-8d, + +1.0618494853096868E-7d, + +9.043280094115832E-8d, + +2.9590395068826316E-8d, + -7.475571347653619E-8d, + +1.7401160143611842E-8d, + +6.923209420670962E-8d, + +8.232829924979753E-8d, + +5.82825404854514E-8d, + -1.3108606792380822E-9d, + -9.485602512220194E-8d, + +1.7663064617118723E-8d, + +9.942682855652123E-8d, + -8.638275100090915E-8d, + -6.132639063569726E-8d, + -6.221897889344726E-8d, + -8.745525834919404E-8d, + +1.029901759234897E-7d, + +3.3888561478632076E-8d, + -5.47315553588771E-8d, + +7.715994473741065E-8d, + -4.566098167230033E-8d, + +5.5257514455273825E-8d, + -9.530545662611411E-8d, + -1.889488909834863E-8d, + +4.769006625301079E-8d, + +1.0607041998938709E-7d, + -8.054981263802322E-8d, + -3.370929373457322E-8d, + +9.799164177397836E-9d, + +5.160291611526656E-8d, + +9.333090708652975E-8d, + -1.0180490545927503E-7d, + -5.533523366931846E-8d, + -4.044932340334176E-9d, + +5.370131904567218E-8d, + -1.1887814032213867E-7d, + -4.3307634616102625E-8d, + +4.363437558318513E-8d, + -9.482896784430338E-8d, + +1.9782818312325887E-8d, + -8.77224935488516E-8d, + +6.113879253864931E-8d, + -8.822335132515693E-9d, + -5.753754066078771E-8d, + -8.335545536862392E-8d, + -8.462309712606694E-8d, + -5.968586877433824E-8d, + -6.887556547891059E-9d, + +7.542967150507818E-8d, + -4.949331199790077E-8d, + +9.684172421525468E-8d, + +3.9260317944365246E-8d, + +1.784536881359796E-8d, + +3.426282345243592E-8d, + +9.018025618601154E-8d, + -5.1151708476133135E-8d, + +8.877492215808044E-8d, + +3.479545684576179E-8d, + +2.7002575714977818E-8d, + +6.707201545505014E-8d, + -8.173742908533777E-8d, + +5.909041310777802E-8d, + +1.439903710393587E-8d, + +2.4289317341982113E-8d, + +9.044519282818302E-8d, + -2.3866331257845713E-8d, + -7.853944465095286E-8d, + -7.188526769607005E-8d, + -2.2132706360079843E-9d, + -1.0624985110080394E-7d, + +9.453598391231829E-8d, + -1.134160131581847E-7d, + -1.315295870404327E-8d, + -7.981320644583728E-8d, + -7.327771300038971E-8d, + +8.155647334672472E-9d, + -7.222791579580787E-8d, + -7.430436987497092E-8d, + +3.633404807819848E-9d, + -7.512438321498593E-8d, + -7.044869765481105E-8d, + +1.9372589859580955E-8d, + -4.2365298585101096E-8d, + -1.552830824758035E-8d, + +1.0160071259930585E-7d, + +7.232201430620959E-8d, + -1.0164389431039905E-7d, + +5.826233477413577E-8d, + +7.6927415825689E-8d, + -4.392309439525734E-8d, + -6.414337408955734E-8d, + +1.799550702470095E-8d, + -3.4194410638967946E-8d, + +1.9437762419688045E-8d, + -5.7792549966531335E-8d, + -2.5731071572354522E-8d, + +1.173595905705643E-7d, + -1.0361863127101014E-7d, + +2.8330789837569332E-8d, + +3.81131861433539E-8d, + -7.252724942149532E-8d, + -6.342604067787756E-8d, + +6.716441526213986E-8d, + +8.257484966196574E-8d, + -1.5443717968117592E-8d, + +1.3280021798948244E-8d, + -6.79180673261558E-8d, + -1.8863249269709046E-8d, + -7.62162303263991E-8d, + +2.011589233663723E-10d, + -2.62683511147141E-8d, + +8.455684903712996E-8d, + +9.602293320384794E-8d, + +9.896378545255258E-9d, + +6.636396724067746E-8d, + +2.8777050870552646E-8d, + -1.0109271059094341E-7d, + -8.305334708631055E-8d, + +8.467026501338835E-8d, + -7.29821745001452E-8d, + -7.739491336852633E-8d, + +7.321238022013781E-8d, + -9.621538067089515E-8d, + -1.0705722541811197E-7d, + +4.247240125405735E-8d, + +1.1574222007764044E-7d, + +1.145412771487496E-7d, + +4.066036653218687E-8d, + -1.0410796803072171E-7d, + -7.955085231106037E-8d, + +1.1612776191572459E-7d, + +7.888519481107568E-9d, + +7.436813814737735E-8d, + +7.894935661289349E-8d, + +2.343525263620692E-8d, + -9.036933434595339E-8d, + -2.2239222395888823E-8d, + -8.784622656707742E-9d, + -4.819540032304379E-8d, + +9.975892708522332E-8d, + -3.9945124955316294E-8d, + +1.1345047468988893E-8d, + +1.702808472925844E-8d, + -2.10770182066344E-8d, + -1.0114948914089626E-7d, + +1.70518021921727E-8d, + +9.693260855961159E-8d, + -9.809953482725758E-8d, + -8.937957126662392E-8d, + -1.134963954323427E-7d, + +6.980004387880031E-8d, + -1.4494150014095534E-8d, + +1.122932337832262E-7d, + -2.483811732227808E-8d, + +5.278759515330048E-8d, + +1.0859222881334994E-7d, + -9.400056055939758E-8d, + -7.630957994128623E-8d, + -7.490757191850264E-8d, + -8.794689652049879E-8d, + -1.1357810855950775E-7d, + +8.846862323478745E-8d, + +4.32092015744956E-8d, + -9.082923009890997E-9d, + -6.655106680680314E-8d, + +1.1108184705020206E-7d, + +4.8838973948592766E-8d, + -1.2998975819628988E-8d, + -7.25680516883106E-8d, + -1.280024819379844E-7d, + -1.7743467191652895E-7d, + -2.1899520225809197E-7d, + +2.2602433110285232E-7d, + +2.0582268590356215E-7d, + +1.9911192455808124E-7d, + +2.0776878313278689E-7d, + +2.3367183133931002E-7d, + -1.9813568387704588E-7d, + -1.320972037315105E-7d, + -4.316580502355056E-8d, + +7.054443447243064E-8d, + +2.109212796025238E-7d, + -9.698281856949837E-8d, + +1.0239791185239086E-7d, + -1.4271754202157014E-7d, + +1.232402895636637E-7d, + -5.150590480969644E-8d, + -1.882201085012735E-7d, + +1.918355503889933E-7d, + +1.368893262241355E-7d, + +1.256828068633383E-7d, + +1.601222826656464E-7d, + -2.3472125169205568E-7d, + -1.032634625827871E-7d, + +7.957037517331382E-8d, + -1.6114314525832115E-7d, + +1.3018591370778052E-7d, + +1.8007284821359149E-9d, + -6.75421764491544E-8d, + -7.592155950645605E-8d, + -2.1414301981236817E-8d, + +9.79045937979623E-8d, + -1.9287515190177685E-7d, + +6.184953843236509E-8d, + -8.966500602352001E-8d, + -1.686490951669855E-7d, + -1.7316830893872364E-7d, + -1.0128633727463388E-7d, + +4.8935021740786486E-8d, + -1.9740129448026905E-7d, + +1.1532102163380318E-7d, + +3.5371542244169364E-8d, + +4.153321337726989E-8d, + +1.3575372396796738E-7d, + -1.5685449228299222E-7d, + +1.1933437776279623E-7d, + +1.2599421120614435E-8d, + +1.7331079674066365E-9d, + +8.869266069401045E-8d, + -2.013999442282902E-7d, + +8.709065843311144E-8d, + +2.453117120472083E-9d, + +2.3489472779602617E-8d, + +1.5216652792122652E-7d, + -8.638415150333099E-8d, + -2.1335475961524608E-7d, + -2.2677272333821516E-7d, + -1.246635423141374E-7d, + +9.494921297991565E-8d, + -4.27932550865546E-8d, + -5.907349480138712E-8d, + +4.809072216941908E-8d, + -1.9615359732789476E-7d, + +1.6385396676990034E-7d, + +1.7642714221524228E-7d, + -1.564440844355254E-7d, + +1.2090653407564583E-7d, + +5.679855838941285E-8d, + +1.3006497185242537E-7d, + -1.341336085949317E-7d, + +2.1987686050231372E-7d, + -2.3641341460419062E-7d, + -7.048932272279454E-8d, + -2.3401958604540354E-7d, + +2.2867766559333004E-7d, + -1.1089952719756529E-7d, + +1.7977178878541792E-7d, + +1.4903074102418675E-7d, + -2.011072593789072E-7d, + +8.504948422097802E-8d, + +5.5846006716348844E-8d, + +1.9014079059505456E-7d, + +1.3119976852347583E-8d, + +3.645999732952202E-9d, + +1.6374611405314333E-7d, + +1.8612397134087598E-8d, + +4.7113225346448296E-8d, + -2.2555535676499395E-7d, + +1.5631615647329739E-7d, + -2.3574653182047758E-7d, + +3.08072210937242E-8d, + +4.344259288116142E-9d, + +1.6374489573868447E-7d, + +3.42171232580676E-8d, + +9.46452492584643E-8d, + -1.297587351085525E-7d, + -1.601065201853145E-7d, + +5.6550495386976275E-9d, + -1.0725602261510391E-7d, + -1.9945408945084193E-8d, + -2.071910882200156E-7d, + -1.900947109027913E-7d, + +3.34069282059055E-8d, + -1.145810806477298E-8d, + +1.5421457732308477E-7d, + +5.5657084775121975E-8d, + +1.7177785285061278E-7d, + +2.7813027425289027E-8d, + +1.0267509648109748E-7d, + -7.839574072711142E-8d, + -3.648293887796095E-8d, + +2.3049492079013518E-7d, + -2.290530257391564E-7d, + +1.747018414872141E-8d, + +1.8477759656842807E-8d, + -2.2394073401050633E-7d, + -2.3085653185818848E-7d, + -1.7598351175286083E-10d, + -6.640551220774385E-9d, + +2.2868466674913266E-7d, + +2.3106230530437902E-7d, + +2.594209135294356E-9d, + +2.2221434720602702E-8d, + -1.847872222755186E-7d, + -1.3948659218254467E-7d, + +1.6023339607737848E-7d, + -2.3718944120137026E-7d, + +1.0087056692827474E-7d, + +2.228553660510707E-7d, + +1.3088328582956644E-7d, + -1.7292527438195104E-7d, + -2.0961068531216087E-7d, + +2.2951597845188004E-8d, + +5.005103745740068E-8d, + -1.2618366811281002E-7d, + -2.6784582477238417E-8d, + -1.2645600379949252E-7d, + +5.3774170051560117E-8d, + +3.9205810725333715E-8d, + -1.6802196396307013E-7d, + -8.893078799284047E-8d, + -1.9821451970481713E-7d, + -1.689060694498032E-8d, + -1.9648717830943396E-8d, + -2.0433926409457167E-7d, + -9.1973399031975E-8d, + -1.5723449006087263E-7d, + +7.887051614592191E-8d, + +1.4166246290402286E-7d, + +3.330146018487787E-8d, + +2.3278688667580978E-7d, + -2.1139124097042925E-7d, + +1.334449995534113E-7d, + -1.6104730195920897E-7d, + -1.3902314592614197E-7d, + +2.0169027167169864E-7d, + -9.040643863751471E-8d, + -5.946190852360168E-8d, + -1.8013411720005014E-7d, + +2.6595401669835947E-8d, + +8.607292924069425E-8d, + +4.84038176769263E-10d, + -2.2798356346688802E-7d, + -1.203028719549339E-7d, + -1.5111906039270745E-7d, + +1.5859915617670956E-7d, + -1.426262681506497E-7d, + -9.892260062323546E-8d, + -1.8492643515928268E-7d, + +7.840210076743552E-8d, + +2.1643071541578027E-7d, + +2.313664294893465E-7d, + +1.2541842003811723E-7d, + -9.920197743470107E-8d, + +3.655589133934081E-8d, + +5.807052689551411E-8d, + -3.244024724169575E-8d, + -2.327564406466327E-7d, + -6.38187356721971E-8d, + -2.3995994000400915E-10d, + -3.9793609609721186E-8d, + -1.802510054588344E-7d, + +5.745586744591196E-8d, + +1.987228872666507E-7d, + -2.3105188606976847E-7d, + +2.0088042407239129E-7d, + +6.624793114025702E-8d, + -1.5587043044056635E-7d, + +1.3606464059428694E-8d, + +1.0008761540741556E-7d, + +1.058213771597129E-7d, + +3.3058299602856804E-8d, + -1.1594886810010702E-7d, + +1.378919824418909E-7d, + -1.5683631181406778E-7d, + -4.4200075770425176E-8d, + +1.2250985436706623E-9d, + -1.8297013058336644E-8d, + -1.005004229646318E-7d, + +2.337202285991116E-7d, + +3.296104292035678E-8d, + -2.23668185816307E-7d, + -5.7055442971184756E-8d, + +5.82391923137467E-8d, + +1.244950238958056E-7d, + +1.4399358260219398E-7d, + +1.1901862840583523E-7d, + +5.1856152603337505E-8d, + -5.520562000491495E-8d, + -1.9987622893254038E-7d, + +9.697418238031897E-8d, + -1.1603376405901542E-7d, + +1.170714288147407E-7d, + -1.550851303094034E-7d, + +2.3472546699189522E-8d, + +1.78211222185955E-7d, + -1.6540009048230807E-7d, + -5.137865010872577E-8d, + +4.57490653163866E-8d, + +1.2829599363166098E-7d, + +1.985773325073412E-7d, + -2.1792661654989742E-7d, + -1.652218131743459E-7d, + -1.178234251477505E-7d, + -7.34071933723896E-8d, + -2.9646587857612632E-8d, + +1.5787194498912167E-8d, + +6.52252321321176E-8d, + +1.2100088103262734E-7d, + +1.8544977697201776E-7d, + -2.159273204728711E-7d, + -1.2711589287782304E-7d, + -2.2610609958205195E-8d, + +9.993330547750349E-8d, + -2.33974236642384E-7d, + -6.830955860192377E-8d, + +1.2244183812423448E-7d, + -1.3620325027706252E-7d, + +1.1178574689680927E-7d, + -8.490693031052439E-8d, + +2.2975389535985893E-7d, + +1.0445707500867073E-7d, + +1.8405243253979117E-8d, + -2.6033812325397097E-8d, + -2.6489990728664908E-8d, + +1.9409124727247465E-8d, + +1.1403826867020365E-7d, + -2.1706266226554237E-7d, + -1.7839974359909697E-8d, + +2.3725087624341041E-7d, + +7.37567604176979E-8d, + -2.9098805266958403E-8d, + -6.892713087722722E-8d, + -4.333719263537725E-8d, + +5.006436936098099E-8d, + +2.1367325342138113E-7d, + -2.6949659655907758E-8d, + -1.9256682968755803E-7d, + +1.960616287777496E-7d, + +1.876664741413704E-7d, + -2.1534486893602122E-7d, + -5.688830723853217E-8d, + +1.8861113228746644E-7d, + +4.6730779443102234E-8d, + -3.275360514112964E-9d, + +4.1011920825226876E-8d, + +1.820141955326842E-7d, + -5.468175655175594E-8d, + -1.8981247089866317E-7d, + -2.209492705846306E-7d, + -1.4566110577298295E-7d, + +3.848544860465368E-8d, + -1.429109630340783E-7d, + -2.105749999899302E-7d, + -1.6206609756618993E-7d, + +5.058693461947143E-9d, + -1.8359244902596882E-7d, + +2.2810251664891242E-7d, + -1.8791776732592608E-7d, + +1.3106843166204263E-9d, + -1.5543153797220025E-7d, + -1.7884997059081524E-7d, + -6.648490725635754E-8d, + +1.8412576154421806E-7d, + +9.860939269906055E-8d, + +1.5627006743114285E-7d, + -1.17260039161597E-7d, + +2.3416513526430908E-7d, + -2.1749172296989992E-7d, + -3.9242560971295217E-8d, + -1.822826971477839E-7d, + -1.6729355321895212E-7d, + +8.208715337901827E-9d, + -1.301267783434537E-7d, + -1.029741755377153E-7d, + +9.215765583599035E-8d, + -1.907487641016455E-8d, + +4.2661388254716074E-8d, + -1.9697226735187428E-7d, + +2.1819935527247946E-7d, + -1.398318929248588E-7d, + +1.6195123407015624E-7d, + +1.723826394935661E-7d, + -1.0602700638269148E-7d, + -1.9392742205954563E-7d, + -8.880302882034106E-8d, + +2.1186420987133E-7d, + +2.3375763256988976E-7d, + -2.0599801342241997E-8d, + -7.184550924856607E-8d, + +8.254840070367875E-8d, + }; + + /** Extended precision logarithm table over the range 1 - 2 in increments of 2^-10. */ + private static final double[][] LN_MANT = + new double[][] { + { + +0.0d, +0.0d, + }, // 0 + { + +9.760860120877624E-4d, -3.903230345984362E-11d, + }, // 1 + { + +0.0019512202125042677d, -8.124251825289188E-11d, + }, // 2 + { + +0.0029254043474793434d, -1.8374207360194882E-11d, + }, // 3 + { + +0.0038986406289041042d, -2.1324678121885073E-10d, + }, // 4 + { + +0.004870930686593056d, -4.5199654318611534E-10d, + }, // 5 + { + +0.00584227591753006d, -2.933016992001806E-10d, + }, // 6 + { + +0.006812678650021553d, -2.325147219074669E-10d, + }, // 7 + { + +0.007782140746712685d, -3.046577356838847E-10d, + }, // 8 + { + +0.008750664070248604d, -5.500631513861575E-10d, + }, // 9 + { + +0.00971824862062931d, +8.48292035519895E-10d, + }, // 10 + { + +0.010684899985790253d, +1.1422610134013436E-10d, + }, // 11 + { + +0.01165061630308628d, +9.168889933128375E-10d, + }, // 12 + { + +0.012615403160452843d, -5.303786078838E-10d, + }, // 13 + { + +0.013579258695244789d, -5.688639355498786E-10d, + }, // 14 + { + +0.01454218477010727d, +7.296670293275653E-10d, + }, // 15 + { + +0.015504186972975731d, -4.370104767451421E-10d, + }, // 16 + { + +0.016465261578559875d, +1.43695591408832E-9d, + }, // 17 + { + +0.01742541790008545d, -1.1862263158849434E-9d, + }, // 18 + { + +0.018384650349617004d, -9.482976524690715E-10d, + }, // 19 + { + +0.01934296265244484d, +1.9068609515836638E-10d, + }, // 20 + { + +0.020300358533859253d, +2.655990315697216E-10d, + }, // 21 + { + +0.021256837993860245d, +1.0315548713040775E-9d, + }, // 22 + { + +0.022212404757738113d, +5.13345647019085E-10d, + }, // 23 + { + +0.02316705882549286d, +4.5604151934208014E-10d, + }, // 24 + { + +0.02412080392241478d, -1.1255706987475148E-9d, + }, // 25 + { + +0.025073636323213577d, +1.2289023836765196E-9d, + }, // 26 + { + +0.02602556347846985d, +1.7990281828096504E-9d, + }, // 27 + { + +0.026976589113473892d, -1.4152718164638451E-9d, + }, // 28 + { + +0.02792670577764511d, +7.568772963781632E-10d, + }, // 29 + { + +0.0288759246468544d, -1.1449998592111558E-9d, + }, // 30 + { + +0.029824241995811462d, -1.6850976862319495E-9d, + }, // 31 + { + +0.030771657824516296d, +8.422373919843096E-10d, + }, // 32 + { + +0.0317181795835495d, +6.872350402175489E-10d, + }, // 33 + { + +0.03266380727291107d, -4.541194749189272E-10d, + }, // 34 + { + +0.03360854089260101d, -8.9064764856495E-10d, + }, // 35 + { + +0.034552380442619324d, +1.0640404096769032E-9d, + }, // 36 + { + +0.0354953333735466d, -3.5901655945224663E-10d, + }, // 37 + { + +0.03643739968538284d, -3.4829517943661266E-9d, + }, // 38 + { + +0.037378571927547455d, +8.149473794244232E-10d, + }, // 39 + { + +0.03831886500120163d, -6.990650304449166E-10d, + }, // 40 + { + +0.03925827145576477d, +1.0883076226453258E-9d, + }, // 41 + { + +0.040196798741817474d, +3.845192807999274E-10d, + }, // 42 + { + +0.04113444685935974d, -1.1570594692045927E-9d, + }, // 43 + { + +0.04207121580839157d, -1.8877045166697178E-9d, + }, // 44 + { + +0.043007105588912964d, -1.6332083257987747E-10d, + }, // 45 + { + +0.04394212365150452d, -1.7950057534514933E-9d, + }, // 46 + { + +0.04487626254558563d, +2.302710041648838E-9d, + }, // 47 + { + +0.045809537172317505d, -1.1410233017161343E-9d, + }, // 48 + { + +0.04674194008111954d, -3.0498741599744685E-9d, + }, // 49 + { + +0.04767347127199173d, -1.8026348269183678E-9d, + }, // 50 + { + +0.04860413819551468d, -3.233204600453039E-9d, + }, // 51 + { + +0.04953393340110779d, +1.7211688427961583E-9d, + }, // 52 + { + +0.05046287178993225d, -2.329967807055457E-10d, + }, // 53 + { + +0.05139094591140747d, -4.191810118556531E-11d, + }, // 54 + { + +0.052318163216114044d, -3.5574324788328143E-9d, + }, // 55 + { + +0.053244516253471375d, -1.7346590916458485E-9d, + }, // 56 + { + +0.05417001247406006d, -4.343048751383674E-10d, + }, // 57 + { + +0.055094651877880096d, +1.92909364037955E-9d, + }, // 58 + { + +0.056018441915512085d, -5.139745677199588E-10d, + }, // 59 + { + +0.05694137513637543d, +1.2637629975129189E-9d, + }, // 60 + { + +0.05786345899105072d, +1.3840561112481119E-9d, + }, // 61 + { + +0.058784693479537964d, +1.414889689612056E-9d, + }, // 62 + { + +0.05970507860183716d, +2.9199191907666474E-9d, + }, // 63 + { + +0.0606246218085289d, +7.90594243412116E-12d, + }, // 64 + { + +0.06154331564903259d, +1.6844747839686189E-9d, + }, // 65 + { + +0.06246116757392883d, +2.0498074572151747E-9d, + }, // 66 + { + +0.06337818503379822d, -4.800180493433863E-9d, + }, // 67 + { + +0.06429435312747955d, -2.4220822960064277E-9d, + }, // 68 + { + +0.06520968675613403d, -4.179048566709334E-9d, + }, // 69 + { + +0.06612417101860046d, +6.363872957010456E-9d, + }, // 70 + { + +0.06703783571720123d, +9.339468680056365E-10d, + }, // 71 + { + +0.06795066595077515d, -4.04226739708981E-9d, + }, // 72 + { + +0.0688626617193222d, -7.043545052852817E-9d, + }, // 73 + { + +0.06977382302284241d, -6.552819560439773E-9d, + }, // 74 + { + +0.07068414986133575d, -1.0571674860370546E-9d, + }, // 75 + { + +0.07159365713596344d, -3.948954622015801E-9d, + }, // 76 + { + +0.07250232994556427d, +1.1776625988228244E-9d, + }, // 77 + { + +0.07341018319129944d, +9.221072639606492E-10d, + }, // 78 + { + +0.07431721687316895d, -3.219119568928366E-9d, + }, // 79 + { + +0.0752234160900116d, +5.147575929018918E-9d, + }, // 80 + { + +0.07612881064414978d, -2.291749683541979E-9d, + }, // 81 + { + +0.07703337073326111d, +5.749565906124772E-9d, + }, // 82 + { + +0.07793712615966797d, +9.495158151301779E-10d, + }, // 83 + { + +0.07884006202220917d, -3.144331429489291E-10d, + }, // 84 + { + +0.0797421783208847d, +3.430029236134205E-9d, + }, // 85 + { + +0.08064348995685577d, -1.2499290483167703E-9d, + }, // 86 + { + +0.08154398202896118d, +2.011215719133196E-9d, + }, // 87 + { + +0.08244366943836212d, -2.2728753031387152E-10d, + }, // 88 + { + +0.0833425521850586d, -6.508966857277253E-9d, + }, // 89 + { + +0.0842406153678894d, -4.801131671405377E-10d, + }, // 90 + { + +0.08513787388801575d, +4.406750291994231E-9d, + }, // 91 + { + +0.08603434264659882d, -5.304795662536171E-9d, + }, // 92 + { + +0.08692999184131622d, +1.6284313912612293E-9d, + }, // 93 + { + +0.08782485127449036d, -3.158898981674071E-9d, + }, // 94 + { + +0.08871890604496002d, -3.3324878834139977E-9d, + }, // 95 + { + +0.08961215615272522d, +2.536961912893389E-9d, + }, // 96 + { + +0.09050461649894714d, +9.737596728980696E-10d, + }, // 97 + { + +0.0913962870836258d, -6.600437262505396E-9d, + }, // 98 + { + +0.09228715300559998d, -3.866609889222889E-9d, + }, // 99 + { + +0.09317722916603088d, -4.311847594020281E-9d, + }, // 100 + { + +0.09406651556491852d, -6.525851105645959E-9d, + }, // 101 + { + +0.09495499730110168d, +5.799080912675435E-9d, + }, // 102 + { + +0.09584270417690277d, +4.2634204358490415E-9d, + }, // 103 + { + +0.09672962129116058d, +5.167390528799477E-9d, + }, // 104 + { + +0.09761576354503632d, -4.994827392841906E-9d, + }, // 105 + { + +0.09850110113620758d, +4.970725577861395E-9d, + }, // 106 + { + +0.09938566386699677d, +6.6496705953229645E-9d, + }, // 107 + { + +0.10026945173740387d, +1.4262712796792241E-9d, + }, // 108 + { + +0.1011524498462677d, +5.5822855204629114E-9d, + }, // 109 + { + +0.10203467309474945d, +5.593494835247651E-9d, + }, // 110 + { + +0.10291612148284912d, +2.8332008343480686E-9d, + }, // 111 + { + +0.10379679501056671d, -1.3289231465997192E-9d, + }, // 112 + { + +0.10467669367790222d, -5.526819276639527E-9d, + }, // 113 + { + +0.10555580258369446d, +6.503128678219282E-9d, + }, // 114 + { + +0.10643415153026581d, +6.317463237641817E-9d, + }, // 115 + { + +0.10731174051761627d, -4.728528221305482E-9d, + }, // 116 + { + +0.10818853974342346d, +4.519199083083901E-9d, + }, // 117 + { + +0.10906457901000977d, +5.606492666349878E-9d, + }, // 118 + { + +0.10993985831737518d, -1.220176214398581E-10d, + }, // 119 + { + +0.11081436276435852d, +3.5759315936869937E-9d, + }, // 120 + { + +0.11168810725212097d, +3.1367659571899855E-9d, + }, // 121 + { + +0.11256109178066254d, -1.0543075713098835E-10d, + }, // 122 + { + +0.11343331634998322d, -4.820065619207094E-9d, + }, // 123 + { + +0.11430476605892181d, +5.221136819669415E-9d, + }, // 124 + { + +0.11517547070980072d, +1.5395018670011342E-9d, + }, // 125 + { + +0.11604541540145874d, +3.5638391501880846E-10d, + }, // 126 + { + +0.11691460013389587d, +2.9885336757136527E-9d, + }, // 127 + { + +0.11778303980827332d, -4.151889860890893E-9d, + }, // 128 + { + +0.11865071952342987d, -4.853823938804204E-9d, + }, // 129 + { + +0.11951763927936554d, +2.189226237170704E-9d, + }, // 130 + { + +0.12038381397724152d, +3.3791993048776982E-9d, + }, // 131 + { + +0.1212492436170578d, +1.5811884868243975E-11d, + }, // 132 + { + +0.12211392819881439d, -6.6045909118908625E-9d, + }, // 133 + { + +0.1229778528213501d, -2.8786263916116364E-10d, + }, // 134 + { + +0.12384103238582611d, +5.354472503748251E-9d, + }, // 135 + { + +0.12470348179340363d, -3.2924463896248744E-9d, + }, // 136 + { + +0.12556517124176025d, +4.856678149580005E-9d, + }, // 137 + { + +0.12642613053321838d, +1.2791850600366742E-9d, + }, // 138 + { + +0.12728634476661682d, +2.1525945093362843E-9d, + }, // 139 + { + +0.12814581394195557d, +8.749974471767862E-9d, + }, // 140 + { + +0.129004567861557d, -7.461209161105275E-9d, + }, // 141 + { + +0.12986254692077637d, +1.4390208226263824E-8d, + }, // 142 + { + +0.1307198405265808d, -1.3839477920475328E-8d, + }, // 143 + { + +0.13157635927200317d, -1.483283901239408E-9d, + }, // 144 + { + +0.13243216276168823d, -6.889072914229094E-9d, + }, // 145 + { + +0.1332872211933136d, +9.990351100568362E-10d, + }, // 146 + { + +0.13414156436920166d, -6.370937412495338E-9d, + }, // 147 + { + +0.13499516248703003d, +2.05047480130511E-9d, + }, // 148 + { + +0.1358480453491211d, -2.29509872547079E-9d, + }, // 149 + { + +0.13670018315315247d, +1.16354361977249E-8d, + }, // 150 + { + +0.13755163550376892d, -1.452496267904829E-8d, + }, // 151 + { + +0.1384023129940033d, +9.865115839786888E-9d, + }, // 152 + { + +0.13925230503082275d, -3.369999130712228E-9d, + }, // 153 + { + +0.14010155200958252d, +6.602496401651853E-9d, + }, // 154 + { + +0.14095008373260498d, +1.1205312852298845E-8d, + }, // 155 + { + +0.14179790019989014d, +1.1660367213160203E-8d, + }, // 156 + { + +0.142645001411438d, +9.186471222585239E-9d, + }, // 157 + { + +0.14349138736724854d, +4.999341878263704E-9d, + }, // 158 + { + +0.14433705806732178d, +3.11611905696257E-10d, + }, // 159 + { + +0.14518201351165771d, -3.6671598175618173E-9d, + }, // 160 + { + +0.14602625370025635d, -5.730477881659618E-9d, + }, // 161 + { + +0.14686977863311768d, -4.674900007989718E-9d, + }, // 162 + { + +0.1477125883102417d, +6.999732437141968E-10d, + }, // 163 + { + +0.14855468273162842d, +1.159150872494107E-8d, + }, // 164 + { + +0.14939609169960022d, -6.082714828488485E-10d, + }, // 165 + { + +0.15023678541183472d, -4.905712741596318E-9d, + }, // 166 + { + +0.1510767638683319d, -1.124848988733307E-10d, + }, // 167 + { + +0.15191605687141418d, -1.484557220949851E-8d, + }, // 168 + { + +0.15275460481643677d, +1.1682026251371384E-8d, + }, // 169 + { + +0.15359249711036682d, -8.757272519238786E-9d, + }, // 170 + { + +0.15442964434623718d, +1.4419920764774415E-8d, + }, // 171 + { + +0.15526613593101501d, -7.019891063126053E-9d, + }, // 172 + { + +0.15610191226005554d, -1.230153548825964E-8d, + }, // 173 + { + +0.15693697333335876d, -2.574172005933276E-10d, + }, // 174 + { + +0.15777134895324707d, +4.748140799544371E-10d, + }, // 175 + { + +0.15860503911972046d, -8.943081874891003E-9d, + }, // 176 + { + +0.15943801403045654d, +2.4500739038517657E-9d, + }, // 177 + { + +0.1602703034877777d, +6.007922084557054E-9d, + }, // 178 + { + +0.16110190749168396d, +2.8835418231126645E-9d, + }, // 179 + { + +0.1619328260421753d, -5.772862039728412E-9d, + }, // 180 + { + +0.16276302933692932d, +1.0988372954605789E-8d, + }, // 181 + { + +0.16359257698059082d, -5.292913162607026E-9d, + }, // 182 + { + +0.16442140936851501d, +6.12956339275823E-9d, + }, // 183 + { + +0.16524958610534668d, -1.3210039516811888E-8d, + }, // 184 + { + +0.16607704758644104d, -2.5711014608334873E-9d, + }, // 185 + { + +0.16690382361412048d, +9.37721319457112E-9d, + }, // 186 + { + +0.1677299439907074d, -6.0370682395944045E-9d, + }, // 187 + { + +0.168555349111557d, +1.1918249660105651E-8d, + }, // 188 + { + +0.1693800985813141d, +4.763282949656017E-9d, + }, // 189 + { + +0.17020416259765625d, +3.4223342273948817E-9d, + }, // 190 + { + +0.1710275411605835d, +9.014612241310916E-9d, + }, // 191 + { + +0.1718502640724182d, -7.145758990550526E-9d, + }, // 192 + { + +0.172672301530838d, -1.4142763934081504E-8d, + }, // 193 + { + +0.1734936535358429d, -1.0865453656579032E-8d, + }, // 194 + { + +0.17431432008743286d, +3.794385569450774E-9d, + }, // 195 + { + +0.1751343309879303d, +1.1399188501627291E-9d, + }, // 196 + { + +0.17595365643501282d, +1.2076238768270153E-8d, + }, // 197 + { + +0.1767723262310028d, +7.901084730502162E-9d, + }, // 198 + { + +0.17759034037590027d, -1.0288181007465474E-8d, + }, // 199 + { + +0.1784076690673828d, -1.15945645153806E-8d, + }, // 200 + { + +0.17922431230545044d, +5.073923825786778E-9d, + }, // 201 + { + +0.18004029989242554d, +1.1004278077575267E-8d, + }, // 202 + { + +0.1808556318283081d, +7.2831502374676964E-9d, + }, // 203 + { + +0.18167030811309814d, -5.0054634662706464E-9d, + }, // 204 + { + +0.18248429894447327d, +5.022108460298934E-9d, + }, // 205 + { + +0.18329763412475586d, +8.642254225732676E-9d, + }, // 206 + { + +0.18411031365394592d, +6.931054493326395E-9d, + }, // 207 + { + +0.18492233753204346d, +9.619685356326533E-10d, + }, // 208 + { + +0.18573370575904846d, -8.194157257980706E-9d, + }, // 209 + { + +0.18654438853263855d, +1.0333241479437797E-8d, + }, // 210 + { + +0.1873544454574585d, -1.9948340196027965E-9d, + }, // 211 + { + +0.1881638467311859d, -1.4313002926259948E-8d, + }, // 212 + { + +0.1889725625514984d, +4.241536392174967E-9d, + }, // 213 + { + +0.18978065252304077d, -4.877952454011428E-9d, + }, // 214 + { + +0.1905880868434906d, -1.0813801247641613E-8d, + }, // 215 + { + +0.1913948655128479d, -1.2513218445781325E-8d, + }, // 216 + { + +0.19220098853111267d, -8.925958555729115E-9d, + }, // 217 + { + +0.1930064558982849d, +9.956860681280245E-10d, + }, // 218 + { + +0.193811297416687d, -1.1505428993246996E-8d, + }, // 219 + { + +0.1946154534816742d, +1.4217997464522202E-8d, + }, // 220 + { + +0.19541901350021362d, -1.0200858727747717E-8d, + }, // 221 + { + +0.19622188806533813d, +5.682607223902455E-9d, + }, // 222 + { + +0.1970241367816925d, +3.2988908516009827E-9d, + }, // 223 + { + +0.19782572984695435d, +1.3482965534659446E-8d, + }, // 224 + { + +0.19862669706344604d, +7.462678536479685E-9d, + }, // 225 + { + +0.1994270384311676d, -1.3734273888891115E-8d, + }, // 226 + { + +0.20022669434547424d, +1.0521983802642893E-8d, + }, // 227 + { + +0.20102575421333313d, -8.152742388541905E-9d, + }, // 228 + { + +0.2018241584300995d, -9.133484280193855E-9d, + }, // 229 + { + +0.20262190699577332d, +8.59763959528144E-9d, + }, // 230 + { + +0.2034190595149994d, -1.3548568223001414E-8d, + }, // 231 + { + +0.20421552658081055d, +1.4847880344628818E-8d, + }, // 232 + { + +0.20501139760017395d, +5.390620378060543E-9d, + }, // 233 + { + +0.2058066427707672d, -1.1109834472051523E-8d, + }, // 234 + { + +0.20660123229026794d, -3.845373872038116E-9d, + }, // 235 + { + +0.20739519596099854d, -1.6149279479975042E-9d, + }, // 236 + { + +0.20818853378295898d, -3.4174925203771133E-9d, + }, // 237 + { + +0.2089812457561493d, -8.254443919468538E-9d, + }, // 238 + { + +0.20977330207824707d, +1.4672790944499144E-8d, + }, // 239 + { + +0.2105647623538971d, +6.753452542942992E-9d, + }, // 240 + { + +0.21135559678077698d, -1.218609462241927E-9d, + }, // 241 + { + +0.21214580535888672d, -8.254218316367887E-9d, + }, // 242 + { + +0.21293538808822632d, -1.3366540360587255E-8d, + }, // 243 + { + +0.2137243151664734d, +1.4231244750190031E-8d, + }, // 244 + { + +0.2145126760005951d, -1.3885660525939072E-8d, + }, // 245 + { + +0.21530038118362427d, -7.3304404046850136E-9d, + }, // 246 + { + +0.2160874605178833d, +5.072117654842356E-9d, + }, // 247 + { + +0.21687394380569458d, -5.505080220459036E-9d, + }, // 248 + { + +0.21765980124473572d, -8.286782292266659E-9d, + }, // 249 + { + +0.2184450328350067d, -2.302351152358085E-9d, + }, // 250 + { + +0.21922963857650757d, +1.3416565858314603E-8d, + }, // 251 + { + +0.22001364827156067d, +1.0033721426962048E-8d, + }, // 252 + { + +0.22079706192016602d, -1.1487079818684332E-8d, + }, // 253 + { + +0.22157981991767883d, +9.420348186357043E-9d, + }, // 254 + { + +0.2223619818687439d, +1.4110645699377834E-8d, + }, // 255 + { + +0.2231435477733612d, +3.5408485497116107E-9d, + }, // 256 + { + +0.22392448782920837d, +8.468072777056227E-9d, + }, // 257 + { + +0.2247048318386078d, +4.255446699237779E-11d, + }, // 258 + { + +0.22548454999923706d, +9.016946273084244E-9d, + }, // 259 + { + +0.22626367211341858d, +6.537034810260226E-9d, + }, // 260 + { + +0.22704219818115234d, -6.451285264969768E-9d, + }, // 261 + { + +0.22782009840011597d, +7.979956357126066E-10d, + }, // 262 + { + +0.22859740257263184d, -5.759582672039005E-10d, + }, // 263 + { + +0.22937411069869995d, -9.633854121180397E-9d, + }, // 264 + { + +0.23015019297599792d, +4.363736368635843E-9d, + }, // 265 + { + +0.23092567920684814d, +1.2549416560182509E-8d, + }, // 266 + { + +0.231700599193573d, -1.3946383592553814E-8d, + }, // 267 + { + +0.2324748933315277d, -1.458843364504023E-8d, + }, // 268 + { + +0.23324856162071228d, +1.1551692104697154E-8d, + }, // 269 + { + +0.23402166366577148d, +5.795621295524984E-9d, + }, // 270 + { + +0.23479416966438293d, -1.1301979046684263E-9d, + }, // 271 + { + +0.23556607961654663d, -8.303779721781787E-9d, + }, // 272 + { + +0.23633739352226257d, -1.4805271785394075E-8d, + }, // 273 + { + +0.23710808157920837d, +1.0085373835899469E-8d, + }, // 274 + { + +0.2378782033920288d, +7.679117635349454E-9d, + }, // 275 + { + +0.2386477291584015d, +8.69177352065934E-9d, + }, // 276 + { + +0.23941665887832642d, +1.4034725764547136E-8d, + }, // 277 + { + +0.24018502235412598d, -5.185064518887831E-9d, + }, // 278 + { + +0.2409527599811554d, +1.1544236628121676E-8d, + }, // 279 + { + +0.24171993136405945d, +5.523085719902123E-9d, + }, // 280 + { + +0.24248650670051575d, +7.456824943331887E-9d, + }, // 281 + { + +0.24325251579284668d, -1.1555923403029638E-8d, + }, // 282 + { + +0.24401789903640747d, +8.988361382732908E-9d, + }, // 283 + { + +0.2447827160358429d, +1.0381848020926893E-8d, + }, // 284 + { + +0.24554696679115295d, -6.480706118857055E-9d, + }, // 285 + { + +0.24631062150001526d, -1.0904271124793968E-8d, + }, // 286 + { + +0.2470736801624298d, -1.998183061531611E-9d, + }, // 287 + { + +0.247836172580719d, -8.676137737360023E-9d, + }, // 288 + { + +0.24859806895256042d, -2.4921733203932487E-10d, + }, // 289 + { + +0.2493593990802765d, -5.635173762130303E-9d, + }, // 290 + { + +0.2501201629638672d, -2.3951455355985637E-8d, + }, // 291 + { + +0.25088030099868774d, +5.287121672447825E-9d, + }, // 292 + { + +0.2516399025917053d, -6.447877375049486E-9d, + }, // 293 + { + +0.25239890813827515d, +1.32472428796441E-9d, + }, // 294 + { + +0.2531573176383972d, +2.9479464287605006E-8d, + }, // 295 + { + +0.2539151906967163d, +1.9284247135543574E-8d, + }, // 296 + { + +0.2546725273132324d, -2.8390360197221716E-8d, + }, // 297 + { + +0.255429208278656d, +6.533522495226226E-9d, + }, // 298 + { + +0.2561853528022766d, +5.713225978895991E-9d, + }, // 299 + { + +0.25694090127944946d, +2.9618050962556135E-8d, + }, // 300 + { + +0.25769591331481934d, +1.950605015323617E-8d, + }, // 301 + { + +0.25845038890838623d, -2.3762031507525576E-8d, + }, // 302 + { + +0.2592042088508606d, +1.98818938195077E-8d, + }, // 303 + { + +0.25995755195617676d, -2.751925069084042E-8d, + }, // 304 + { + +0.2607102394104004d, +1.3703391844683932E-8d, + }, // 305 + { + +0.26146239042282104d, +2.5193525310038174E-8d, + }, // 306 + { + +0.2622140049934387d, +7.802219817310385E-9d, + }, // 307 + { + +0.26296502351760864d, +2.1983272709242607E-8d, + }, // 308 + { + +0.2637155055999756d, +8.979279989292184E-9d, + }, // 309 + { + +0.2644653916358948d, +2.9240221157844312E-8d, + }, // 310 + { + +0.265214741230011d, +2.4004885823813374E-8d, + }, // 311 + { + +0.2659635543823242d, -5.885186277410878E-9d, + }, // 312 + { + +0.2667117714881897d, +1.4300386517357162E-11d, + }, // 313 + { + +0.2674594521522522d, -1.7063531531989365E-8d, + }, // 314 + { + +0.26820653676986694d, +3.3218524692903896E-9d, + }, // 315 + { + +0.2689530849456787d, +2.3998252479954764E-9d, + }, // 316 + { + +0.2696990966796875d, -1.8997462070389404E-8d, + }, // 317 + { + +0.27044451236724854d, -4.350745270980051E-10d, + }, // 318 + { + +0.2711893916130066d, -6.892221115467135E-10d, + }, // 319 + { + +0.27193373441696167d, -1.89333199110902E-8d, + }, // 320 + { + +0.272677481174469d, +5.262017392507765E-9d, + }, // 321 + { + +0.27342069149017334d, +1.3115046679980076E-8d, + }, // 322 + { + +0.2741633653640747d, +5.4468361834451975E-9d, + }, // 323 + { + +0.2749055027961731d, -1.692337384653611E-8d, + }, // 324 + { + +0.27564704418182373d, +6.426479056697412E-9d, + }, // 325 + { + +0.2763880491256714d, +1.670735065191342E-8d, + }, // 326 + { + +0.27712851762771606d, +1.4733029698334834E-8d, + }, // 327 + { + +0.27786844968795776d, +1.315498542514467E-9d, + }, // 328 + { + +0.2786078453063965d, -2.2735061539223372E-8d, + }, // 329 + { + +0.27934664487838745d, +2.994379757313727E-9d, + }, // 330 + { + +0.28008490800857544d, +1.970577274107218E-8d, + }, // 331 + { + +0.28082263469696045d, +2.820392733542077E-8d, + }, // 332 + { + +0.2815598249435425d, +2.929187356678173E-8d, + }, // 333 + { + +0.28229647874832153d, +2.377086680926386E-8d, + }, // 334 + { + +0.2830325961112976d, +1.2440393009992529E-8d, + }, // 335 + { + +0.2837681770324707d, -3.901826104778096E-9d, + }, // 336 + { + +0.2845032215118408d, -2.4459827842685974E-8d, + }, // 337 + { + +0.2852376699447632d, +1.1165241398059789E-8d, + }, // 338 + { + +0.28597164154052734d, -1.54434478239181E-8d, + }, // 339 + { + +0.28670501708984375d, +1.5714110564653245E-8d, + }, // 340 + { + +0.28743791580200195d, -1.3782394940142479E-8d, + }, // 341 + { + +0.2881702184677124d, +1.6063569876284005E-8d, + }, // 342 + { + +0.28890204429626465d, -1.317176818216125E-8d, + }, // 343 + { + +0.28963327407836914d, +1.8504673536253893E-8d, + }, // 344 + { + +0.29036402702331543d, -7.334319635123628E-9d, + }, // 345 + { + +0.29109418392181396d, +2.9300903540317107E-8d, + }, // 346 + { + +0.2918238639831543d, +9.979706999541057E-9d, + }, // 347 + { + +0.29255300760269165d, -4.916314210412424E-9d, + }, // 348 + { + +0.293281614780426d, -1.4611908070155308E-8d, + }, // 349 + { + +0.2940096855163574d, -1.833351586679361E-8d, + }, // 350 + { + +0.29473721981048584d, -1.530926726615185E-8d, + }, // 351 + { + +0.2954642176628113d, -4.7689754029101934E-9d, + }, // 352 + { + +0.29619067907333374d, +1.4055868011423819E-8d, + }, // 353 + { + +0.296916663646698d, -1.7672547212604003E-8d, + }, // 354 + { + +0.2976420521736145d, +2.0020234215759705E-8d, + }, // 355 + { + +0.2983669638633728d, +8.688424478730524E-9d, + }, // 356 + { + +0.2990913391113281d, +8.69851089918337E-9d, + }, // 357 + { + +0.29981517791748047d, +2.0810681643102672E-8d, + }, // 358 + { + +0.3005385398864746d, -1.3821169493779352E-8d, + }, // 359 + { + +0.301261305809021d, +2.4769140784919128E-8d, + }, // 360 + { + +0.3019835948944092d, +1.8127576600610336E-8d, + }, // 361 + { + +0.3027053475379944d, +2.6612401062437074E-8d, + }, // 362 + { + +0.3034266233444214d, -8.629042891789934E-9d, + }, // 363 + { + +0.3041473627090454d, -2.724174869314043E-8d, + }, // 364 + { + +0.30486756563186646d, -2.8476975783775358E-8d, + }, // 365 + { + +0.3055872321128845d, -1.1587600174449919E-8d, + }, // 366 + { + +0.3063063621520996d, +2.417189020581056E-8d, + }, // 367 + { + +0.3070250153541565d, +1.99407553679345E-8d, + }, // 368 + { + +0.3077431917190552d, -2.35387025694381E-8d, + }, // 369 + { + +0.3084607720375061d, +1.3683509995845583E-8d, + }, // 370 + { + +0.30917787551879883d, +1.3137214081023085E-8d, + }, // 371 + { + +0.30989450216293335d, -2.444006866174775E-8d, + }, // 372 + { + +0.3106105327606201d, +2.0896888605749563E-8d, + }, // 373 + { + +0.31132614612579346d, -2.893149098508887E-8d, + }, // 374 + { + +0.31204116344451904d, +5.621509038251498E-9d, + }, // 375 + { + +0.3127557039260864d, +6.0778104626050015E-9d, + }, // 376 + { + +0.3134697675704956d, -2.6832941696716294E-8d, + }, // 377 + { + +0.31418323516845703d, +2.6826625274495256E-8d, + }, // 378 + { + +0.31489628553390503d, -1.1030897183911054E-8d, + }, // 379 + { + +0.31560879945755005d, -2.047124671392676E-8d, + }, // 380 + { + +0.3163207769393921d, -7.709990443086711E-10d, + }, // 381 + { + +0.3170322775840759d, -1.0812918808112342E-8d, + }, // 382 + { + +0.3177432417869568d, +9.727979174888975E-9d, + }, // 383 + { + +0.31845372915267944d, +1.9658551724508715E-9d, + }, // 384 + { + +0.3191636800765991d, +2.6222628001695826E-8d, + }, // 385 + { + +0.3198731541633606d, +2.3609400272358744E-8d, + }, // 386 + { + +0.32058215141296387d, -5.159602957634814E-9d, + }, // 387 + { + +0.32129061222076416d, +2.329701319016099E-10d, + }, // 388 + { + +0.32199859619140625d, -1.910633190395738E-8d, + }, // 389 + { + +0.32270604372024536d, -2.863180390093667E-9d, + }, // 390 + { + +0.32341301441192627d, -9.934041364456825E-9d, + }, // 391 + { + +0.3241194486618042d, +1.999240777687192E-8d, + }, // 392 + { + +0.3248254060745239d, +2.801670341647724E-8d, + }, // 393 + { + +0.32553088665008545d, +1.4842534265191358E-8d, + }, // 394 + { + +0.32623589038848877d, -1.882789920477354E-8d, + }, // 395 + { + +0.3269403576850891d, -1.268923579073577E-8d, + }, // 396 + { + +0.32764434814453125d, -2.564688370677835E-8d, + }, // 397 + { + +0.3283478021621704d, +2.6015626820520968E-9d, + }, // 398 + { + +0.32905077934265137d, +1.3147747907784344E-8d, + }, // 399 + { + +0.3297532796859741d, +6.686493860720675E-9d, + }, // 400 + { + +0.33045530319213867d, -1.608884086544153E-8d, + }, // 401 + { + +0.33115679025650024d, +5.118287907840204E-9d, + }, // 402 + { + +0.3318578004837036d, +1.139367970944884E-8d, + }, // 403 + { + +0.3325583338737488d, +3.426327822115399E-9d, + }, // 404 + { + +0.33325839042663574d, -1.809622142990733E-8d, + }, // 405 + { + +0.3339579105377197d, +7.116780143398601E-9d, + }, // 406 + { + +0.3346569538116455d, +2.0145352306345386E-8d, + }, // 407 + { + +0.3353555202484131d, +2.167272474431968E-8d, + }, // 408 + { + +0.33605360984802246d, +1.2380696294966822E-8d, + }, // 409 + { + +0.33675122261047363d, -7.050361059209181E-9d, + }, // 410 + { + +0.3374482989311218d, +2.366314656322868E-8d, + }, // 411 + { + +0.3381449580192566d, -1.4010540194086646E-8d, + }, // 412 + { + +0.3388410806655884d, -1.860165465666482E-10d, + }, // 413 + { + +0.33953672647476196d, +6.206776940880773E-9d, + }, // 414 + { + +0.34023189544677734d, +5.841137379010982E-9d, + }, // 415 + { + +0.3409265875816345d, -6.11041311179286E-10d, + }, // 416 + { + +0.3416208028793335d, -1.2479264502054702E-8d, + }, // 417 + { + +0.34231454133987427d, -2.909443297645926E-8d, + }, // 418 + { + +0.34300774335861206d, +9.815805717097634E-9d, + }, // 419 + { + +0.3437005281448364d, -1.4291517981101049E-8d, + }, // 420 + { + +0.3443927764892578d, +1.8457821628427503E-8d, + }, // 421 + { + +0.34508460760116577d, -1.0481908869377813E-8d, + }, // 422 + { + +0.34577590227127075d, +1.876076001514746E-8d, + }, // 423 + { + +0.3464667797088623d, -1.2362653723769037E-8d, + }, // 424 + { + +0.3471571207046509d, +1.6016578405624026E-8d, + }, // 425 + { + +0.347847044467926d, -1.4652759033760925E-8d, + }, // 426 + { + +0.3485364317893982d, +1.549533655901835E-8d, + }, // 427 + { + +0.34922540187835693d, -1.2093068629412478E-8d, + }, // 428 + { + +0.3499138355255127d, +2.244531711424792E-8d, + }, // 429 + { + +0.35060185194015503d, +5.538565518604807E-10d, + }, // 430 + { + +0.35128939151763916d, -1.7511499366215853E-8d, + }, // 431 + { + +0.3519763946533203d, +2.850385787215544E-8d, + }, // 432 + { + +0.35266298055648804d, +2.003926370146842E-8d, + }, // 433 + { + +0.35334908962249756d, +1.734665280502264E-8d, + }, // 434 + { + +0.3540347218513489d, +2.1071983674869414E-8d, + }, // 435 + { + +0.35471993684768677d, -2.774475773922311E-8d, + }, // 436 + { + +0.3554046154022217d, -9.250975291734664E-9d, + }, // 437 + { + +0.3560888171195984d, +1.7590672330295415E-8d, + }, // 438 + { + +0.35677260160446167d, -6.1837904549178745E-9d, + }, // 439 + { + +0.35745590925216675d, -2.0330362973820856E-8d, + }, // 440 + { + +0.3581387400627136d, -2.42109990366786E-8d, + }, // 441 + { + +0.3588210940361023d, -1.7188958587407816E-8d, + }, // 442 + { + +0.35950297117233276d, +1.3711958590112228E-9d, + }, // 443 + { + +0.3601844310760498d, -2.7501042008405925E-8d, + }, // 444 + { + +0.36086535453796387d, +1.6036460343275798E-8d, + }, // 445 + { + +0.3615458607673645d, +1.3405964389498495E-8d, + }, // 446 + { + +0.36222589015960693d, +2.484237749027735E-8d, + }, // 447 + { + +0.36290550231933594d, -8.629967484362177E-9d, + }, // 448 + { + +0.36358463764190674d, -2.6778729562324134E-8d, + }, // 449 + { + +0.36426329612731934d, -2.8977490516960565E-8d, + }, // 450 + { + +0.36494147777557373d, -1.4601106624823502E-8d, + }, // 451 + { + +0.3656191825866699d, +1.69742947894444E-8d, + }, // 452 + { + +0.3662964701652527d, +6.7666740211281175E-9d, + }, // 453 + { + +0.36697328090667725d, +1.500201674336832E-8d, + }, // 454 + { + +0.3676496744155884d, -1.730424167425052E-8d, + }, // 455 + { + +0.36832553148269653d, +2.9676011119845104E-8d, + }, // 456 + { + +0.36900103092193604d, -2.2253590346826743E-8d, + }, // 457 + { + +0.36967599391937256d, +6.3372065441089185E-9d, + }, // 458 + { + +0.37035053968429565d, -3.145816653215968E-9d, + }, // 459 + { + +0.37102460861206055d, +9.515812117036965E-9d, + }, // 460 + { + +0.371698260307312d, -1.4669965113042639E-8d, + }, // 461 + { + +0.3723714351654053d, -1.548715389333397E-8d, + }, // 462 + { + +0.37304413318634033d, +7.674361647125109E-9d, + }, // 463 + { + +0.37371641397476196d, -4.181177882069608E-9d, + }, // 464 + { + +0.3743882179260254d, +9.158530500130718E-9d, + }, // 465 + { + +0.3750596046447754d, -1.13047236597869E-8d, + }, // 466 + { + +0.3757305145263672d, -5.36108186384227E-9d, + }, // 467 + { + +0.3764009475708008d, +2.7593452284747873E-8d, + }, // 468 + { + +0.37707096338272095d, +2.8557016344085205E-8d, + }, // 469 + { + +0.3777405619621277d, -1.868818164036E-9d, + }, // 470 + { + +0.3784096837043762d, -3.479042513414447E-9d, + }, // 471 + { + +0.37907832860946655d, +2.432550290565648E-8d, + }, // 472 + { + +0.37974655628204346d, +2.2538131805476768E-8d, + }, // 473 + { + +0.38041436672210693d, -8.244395239939089E-9d, + }, // 474 + { + +0.3810817003250122d, -7.821867597227376E-9d, + }, // 475 + { + +0.3817485570907593d, +2.4400089062515914E-8d, + }, // 476 + { + +0.3824149966239929d, +2.9410015940087773E-8d, + }, // 477 + { + +0.38308101892471313d, +7.799913824734797E-9d, + }, // 478 + { + +0.38374656438827515d, +1.976524624939355E-8d, + }, // 479 + { + +0.38441169261932373d, +6.291008309266035E-9d, + }, // 480 + { + +0.3850763440132141d, +2.757030889767851E-8d, + }, // 481 + { + +0.38574057817459106d, +2.4585794728405612E-8d, + }, // 482 + { + +0.3864043951034546d, -2.0764122246389383E-9d, + }, // 483 + { + +0.3870677351951599d, +7.77328837578952E-9d, + }, // 484 + { + +0.3877306580543518d, -4.8859560029989374E-9d, + }, // 485 + { + +0.3883931040763855d, +2.0133131420595028E-8d, + }, // 486 + { + +0.38905513286590576d, +2.380738071335498E-8d, + }, // 487 + { + +0.3897167444229126d, +6.7171126157142075E-9d, + }, // 488 + { + +0.39037787914276123d, +2.9046141593926277E-8d, + }, // 489 + { + +0.3910386562347412d, -2.7836800219410262E-8d, + }, // 490 + { + +0.3916988968849182d, +1.545909820981726E-8d, + }, // 491 + { + +0.39235877990722656d, -1.930436269002062E-8d, + }, // 492 + { + +0.3930181860923767d, -1.2343297554921835E-8d, + }, // 493 + { + +0.3936771750450134d, -2.268889128622553E-8d, + }, // 494 + { + +0.39433568716049194d, +9.835827818608177E-9d, + }, // 495 + { + +0.39499378204345703d, +2.6197411946856397E-8d, + }, // 496 + { + +0.3956514596939087d, +2.6965931069318893E-8d, + }, // 497 + { + +0.3963087201118469d, +1.2710331127772166E-8d, + }, // 498 + { + +0.39696556329727173d, -1.6001563011916016E-8d, + }, // 499 + { + +0.39762192964553833d, +1.0016001590267064E-9d, + }, // 500 + { + +0.3982778787612915d, +4.680767399874334E-9d, + }, // 501 + { + +0.39893341064453125d, -4.399582029272418E-9d, + }, // 502 + { + +0.39958852529525757d, -2.5676078228301587E-8d, + }, // 503 + { + +0.4002431631088257d, +1.0181870233355787E-9d, + }, // 504 + { + +0.40089738368988037d, +1.6639728835984655E-8d, + }, // 505 + { + +0.40155118703842163d, +2.174860642202632E-8d, + }, // 506 + { + +0.40220457315444946d, +1.6903781197123503E-8d, + }, // 507 + { + +0.40285754203796387d, +2.663119647467697E-9d, + }, // 508 + { + +0.40351009368896484d, -2.0416603812329616E-8d, + }, // 509 + { + +0.4041621685028076d, +7.82494078472695E-9d, + }, // 510 + { + +0.40481382608413696d, +2.833770747113627E-8d, + }, // 511 + { + +0.40546512603759766d, -1.7929433274271985E-8d, + }, // 512 + { + +0.40611594915390015d, -1.1214757379328965E-8d, + }, // 513 + { + +0.4067663550376892d, -1.0571553019207106E-8d, + }, // 514 + { + +0.40741634368896484d, -1.5449538712332313E-8d, + }, // 515 + { + +0.40806591510772705d, -2.529950530235105E-8d, + }, // 516 + { + +0.40871500968933105d, +2.0031331601617008E-8d, + }, // 517 + { + +0.4093637466430664d, +1.880755298741952E-9d, + }, // 518 + { + +0.41001206636428833d, -1.9600580584843318E-8d, + }, // 519 + { + +0.41065990924835205d, +1.573691633515306E-8d, + }, // 520 + { + +0.4113073945045471d, -1.0772154376548336E-8d, + }, // 521 + { + +0.411954402923584d, +2.0624330192486066E-8d, + }, // 522 + { + +0.4126010537147522d, -8.741139170029572E-9d, + }, // 523 + { + +0.4132472276687622d, +2.0881457123894216E-8d, + }, // 524 + { + +0.41389304399490356d, -9.177488027521808E-9d, + }, // 525 + { + +0.4145383834838867d, +2.0829952491625585E-8d, + }, // 526 + { + +0.4151833653450012d, -7.767915492597301E-9d, + }, // 527 + { + +0.4158278703689575d, +2.4774753446082082E-8d, + }, // 528 + { + +0.41647201776504517d, -2.1581119071750435E-10d, + }, // 529 + { + +0.4171157479286194d, -2.260047972865202E-8d, + }, // 530 + { + +0.4177590012550354d, +1.775884601423381E-8d, + }, // 531 + { + +0.41840189695358276d, +2.185301053838889E-9d, + }, // 532 + { + +0.4190443754196167d, -9.185071463667081E-9d, + }, // 533 + { + +0.4196864366531372d, -1.5821896727910552E-8d, + }, // 534 + { + +0.4203280806541443d, -1.719582086188318E-8d, + }, // 535 + { + +0.42096930742263794d, -1.2778508303324259E-8d, + }, // 536 + { + +0.42161011695861816d, -2.042639194493364E-9d, + }, // 537 + { + +0.42225050926208496d, +1.5538093219698803E-8d, + }, // 538 + { + +0.4228905439376831d, -1.9115659590156936E-8d, + }, // 539 + { + +0.42353010177612305d, +1.3729680248843432E-8d, + }, // 540 + { + +0.42416930198669434d, -4.611893838830296E-9d, + }, // 541 + { + +0.4248080849647522d, -1.4013456880651706E-8d, + }, // 542 + { + +0.42544645071029663d, -1.3953728897042917E-8d, + }, // 543 + { + +0.42608439922332764d, -3.912427573594197E-9d, + }, // 544 + { + +0.4267219305038452d, +1.6629734283189315E-8d, + }, // 545 + { + +0.42735910415649414d, -1.1413593493354881E-8d, + }, // 546 + { + +0.42799586057662964d, -2.792046157580119E-8d, + }, // 547 + { + +0.42863214015960693d, +2.723009182661306E-8d, + }, // 548 + { + +0.42926812171936035d, -2.4260535621557444E-8d, + }, // 549 + { + +0.42990362644195557d, -3.064060124024764E-9d, + }, // 550 + { + +0.43053877353668213d, -2.787640178598121E-8d, + }, // 551 + { + +0.4311734437942505d, +2.102412085257792E-8d, + }, // 552 + { + +0.4318077564239502d, +2.4939635093999683E-8d, + }, // 553 + { + +0.43244171142578125d, -1.5619414792273914E-8d, + }, // 554 + { + +0.4330751895904541d, +1.9065734894871523E-8d, + }, // 555 + { + +0.4337083101272583d, +1.0294301092654604E-8d, + }, // 556 + { + +0.4343410134315491d, +1.8178469851136E-8d, + }, // 557 + { + +0.4349733591079712d, -1.6379825102473853E-8d, + }, // 558 + { + +0.4356052279472351d, +2.6334323946685834E-8d, + }, // 559 + { + +0.43623673915863037d, +2.761628769925529E-8d, + }, // 560 + { + +0.436867892742157d, -1.2030229087793677E-8d, + }, // 561 + { + +0.4374985694885254d, +2.7106814809424793E-8d, + }, // 562 + { + +0.43812888860702515d, +2.631993083235205E-8d, + }, // 563 + { + +0.43875885009765625d, -1.3890028312254422E-8d, + }, // 564 + { + +0.43938833475112915d, +2.6186133735555794E-8d, + }, // 565 + { + +0.4400174617767334d, +2.783809071694788E-8d, + }, // 566 + { + +0.440646231174469d, -8.436135220472006E-9d, + }, // 567 + { + +0.44127458333969116d, -2.2534815932619883E-8d, + }, // 568 + { + +0.4419025182723999d, -1.3961804471714283E-8d, + }, // 569 + { + +0.4425300359725952d, +1.7778112039716255E-8d, + }, // 570 + { + +0.4431571960449219d, +1.3574569976673652E-8d, + }, // 571 + { + +0.4437839984893799d, -2.607907890164073E-8d, + }, // 572 + { + +0.4444103240966797d, +1.8518879652136628E-8d, + }, // 573 + { + +0.44503629207611084d, +2.865065604247164E-8d, + }, // 574 + { + +0.44566190242767334d, +4.806827797299427E-9d, + }, // 575 + { + +0.4462870955467224d, +7.0816970994232115E-9d, + }, // 576 + { + +0.44691193103790283d, -2.3640641240074437E-8d, + }, // 577 + { + +0.4475363492965698d, -2.7267718387865538E-8d, + }, // 578 + { + +0.4481603503227234d, -3.3126235292976077E-9d, + }, // 579 + { + +0.4487839937210083d, -1.0894001590268427E-8d, + }, // 580 + { + +0.4494072198867798d, +1.0077883359971829E-8d, + }, // 581 + { + +0.4500300884246826d, +4.825712712114668E-10d, + }, // 582 + { + +0.450652539730072d, +2.0407987470746858E-8d, + }, // 583 + { + +0.4512746334075928d, +1.073186581170719E-8d, + }, // 584 + { + +0.4518963694572449d, -2.8064314757880205E-8d, + }, // 585 + { + +0.45251762866973877d, +2.3709316816226527E-8d, + }, // 586 + { + +0.4531385898590088d, -1.2281487504266522E-8d, + }, // 587 + { + +0.4537591338157654d, -1.634864487421458E-8d, + }, // 588 + { + +0.45437926054000854d, +1.1985747222409522E-8d, + }, // 589 + { + +0.45499902963638306d, +1.3594057956219485E-8d, + }, // 590 + { + +0.4556184411048889d, -1.1047585095328619E-8d, + }, // 591 + { + +0.45623743534088135d, -1.8592937532754405E-9d, + }, // 592 + { + +0.4568560719490051d, -1.797135137545755E-8d, + }, // 593 + { + +0.4574742913246155d, +6.943684261645378E-10d, + }, // 594 + { + +0.4580921530723572d, -4.994175141684681E-9d, + }, // 595 + { + +0.45870959758758545d, +2.5039391215625133E-8d, + }, // 596 + { + +0.45932674407958984d, -2.7943366835352838E-8d, + }, // 597 + { + +0.45994341373443604d, +1.534146910128904E-8d, + }, // 598 + { + +0.46055978536605835d, -2.3450920230816267E-8d, + }, // 599 + { + +0.46117573976516724d, -2.4642997069960124E-8d, + }, // 600 + { + +0.4617912769317627d, +1.2232622070370946E-8d, + }, // 601 + { + +0.4624064564704895d, +2.80378133047839E-8d, + }, // 602 + { + +0.46302127838134766d, +2.3238237048117092E-8d, + }, // 603 + { + +0.46363574266433716d, -1.7013046451109475E-9d, + }, // 604 + { + +0.46424978971481323d, +1.3287778803035383E-8d, + }, // 605 + { + +0.46486347913742065d, +9.06393426961373E-9d, + }, // 606 + { + +0.4654768109321594d, -1.3910598647592876E-8d, + }, // 607 + { + +0.46608972549438477d, +4.430214458933614E-9d, + }, // 608 + { + +0.46670228242874146d, +4.942270562885745E-9d, + }, // 609 + { + +0.4673144817352295d, -1.1914734393460718E-8d, + }, // 610 + { + +0.4679262638092041d, +1.3922696570638494E-8d, + }, // 611 + { + +0.46853768825531006d, +2.3307929211781914E-8d, + }, // 612 + { + +0.46914875507354736d, +1.669813444584674E-8d, + }, // 613 + { + +0.469759464263916d, -5.450354376430758E-9d, + }, // 614 + { + +0.47036975622177124d, +1.6922605350647674E-8d, + }, // 615 + { + +0.4709796905517578d, +2.4667033200046904E-8d, + }, // 616 + { + +0.47158926725387573d, +1.8236762070433784E-8d, + }, // 617 + { + +0.472198486328125d, -1.915204563140137E-9d, + }, // 618 + { + +0.47280728816986084d, +2.426795414605756E-8d, + }, // 619 + { + +0.4734157919883728d, -2.19717006713618E-8d, + }, // 620 + { + +0.47402387857437134d, -2.0974352165535873E-8d, + }, // 621 + { + +0.47463154792785645d, +2.770970558184228E-8d, + }, // 622 + { + +0.4752389192581177d, +5.32006955298355E-9d, + }, // 623 + { + +0.47584593296051025d, -2.809054633964104E-8d, + }, // 624 + { + +0.4764525294303894d, -1.2470243596102937E-8d, + }, // 625 + { + +0.4770587682723999d, -6.977226702440138E-9d, + }, // 626 + { + +0.47766464948654175d, -1.1165866833118273E-8d, + }, // 627 + { + +0.47827017307281494d, -2.4591344661022708E-8d, + }, // 628 + { + +0.4788752794265747d, +1.2794996377383974E-8d, + }, // 629 + { + +0.4794800877571106d, -1.7772927065973874E-8d, + }, // 630 + { + +0.48008447885513306d, +3.35657712457243E-9d, + }, // 631 + { + +0.48068851232528687d, +1.7020465042442242E-8d, + }, // 632 + { + +0.481292188167572d, +2.365953779624783E-8d, + }, // 633 + { + +0.4818955063819885d, +2.3713798664443718E-8d, + }, // 634 + { + +0.4824984669685364d, +1.7622455019548098E-8d, + }, // 635 + { + +0.4831010699272156d, +5.823920246566496E-9d, + }, // 636 + { + +0.4837033152580261d, -1.1244184344361017E-8d, + }, // 637 + { + +0.48430514335632324d, +2.645961716432205E-8d, + }, // 638 + { + +0.4849066734313965d, +1.6207809718247905E-10d, + }, // 639 + { + +0.4855077862739563d, +2.9507744508973654E-8d, + }, // 640 + { + +0.48610860109329224d, -4.278201128741098E-9d, + }, // 641 + { + +0.48670899868011475d, +1.844722015961139E-8d, + }, // 642 + { + +0.4873090982437134d, -2.1092372471088425E-8d, + }, // 643 + { + +0.4879087805747986d, -3.2555596107382053E-9d, + }, // 644 + { + +0.48850810527801514d, +1.2784366845429667E-8d, + }, // 645 + { + +0.48910707235336304d, +2.7457984659996047E-8d, + }, // 646 + { + +0.48970574140548706d, -1.8409546441412518E-8d, + }, // 647 + { + +0.49030399322509766d, -5.179903818099661E-9d, + }, // 648 + { + +0.4909018874168396d, +7.97053127828682E-9d, + }, // 649 + { + +0.4914994239807129d, +2.146925464473481E-8d, + }, // 650 + { + +0.4920966625213623d, -2.3861648589988232E-8d, + }, // 651 + { + +0.4926934838294983d, -8.386923035320549E-9d, + }, // 652 + { + +0.4932899475097656d, +8.713990131749256E-9d, + }, // 653 + { + +0.4938860535621643d, +2.7865534085810115E-8d, + }, // 654 + { + +0.4944818615913391d, -1.011325138560159E-8d, + }, // 655 + { + +0.4950772523880005d, +1.4409851026316708E-8d, + }, // 656 + { + +0.495672345161438d, -1.735227547472004E-8d, + }, // 657 + { + +0.49626702070236206d, +1.4231078209064581E-8d, + }, // 658 + { + +0.49686139822006226d, -9.628709342929729E-9d, + }, // 659 + { + +0.4974554181098938d, -2.8907074856577267E-8d, + }, // 660 + { + +0.4980490207672119d, +1.6419797090870802E-8d, + }, // 661 + { + +0.49864232540130615d, +7.561041519403049E-9d, + }, // 662 + { + +0.49923527240753174d, +4.538983468118194E-9d, + }, // 663 + { + +0.49982786178588867d, +7.770560657946324E-9d, + }, // 664 + { + +0.500420093536377d, +1.767197002609876E-8d, + }, // 665 + { + +0.5010119676589966d, +3.46586694799214E-8d, + }, // 666 + { + +0.5016034841537476d, +5.914537964556077E-8d, + }, // 667 + { + +0.5021947622299194d, -2.7663203939320167E-8d, + }, // 668 + { + +0.5027855634689331d, +1.3064749115929298E-8d, + }, // 669 + { + +0.5033761262893677d, -5.667682106730711E-8d, + }, // 670 + { + +0.503966212272644d, +1.9424534974370594E-9d, + }, // 671 + { + +0.5045560598373413d, -4.908494602153544E-8d, + }, // 672 + { + +0.5051454305648804d, +2.906989285008994E-8d, + }, // 673 + { + +0.5057345628738403d, -1.602000800745108E-9d, + }, // 674 + { + +0.5063233375549316d, -2.148245271118002E-8d, + }, // 675 + { + +0.5069117546081543d, -3.016329994276181E-8d, + }, // 676 + { + +0.5074998140335083d, -2.7237099632871992E-8d, + }, // 677 + { + +0.5080875158309937d, -1.2297127301923986E-8d, + }, // 678 + { + +0.5086748600006104d, +1.5062624834468093E-8d, + }, // 679 + { + +0.5092618465423584d, +5.524744954836658E-8d, + }, // 680 + { + +0.5098485946655273d, -1.054736327333046E-8d, + }, // 681 + { + +0.5104348659515381d, +5.650063324725722E-8d, + }, // 682 + { + +0.5110208988189697d, +1.8376017791642605E-8d, + }, // 683 + { + +0.5116065740585327d, -5.309470636324855E-9d, + }, // 684 + { + +0.512191891670227d, -1.4154089255217218E-8d, + }, // 685 + { + +0.5127768516540527d, -7.756800301729815E-9d, + }, // 686 + { + +0.5133614540100098d, +1.4282730618002001E-8d, + }, // 687 + { + +0.5139456987380981d, +5.2364136172269755E-8d, + }, // 688 + { + +0.5145297050476074d, -1.2322940607922115E-8d, + }, // 689 + { + +0.5151132345199585d, +5.903831350855322E-8d, + }, // 690 + { + +0.5156965255737305d, +2.8426856726994483E-8d, + }, // 691 + { + +0.5162794589996338d, +1.544882070711032E-8d, + }, // 692 + { + +0.5168620347976685d, +2.0500353979930155E-8d, + }, // 693 + { + +0.5174442529678345d, +4.397691311390564E-8d, + }, // 694 + { + +0.5180262327194214d, -3.2936025225250634E-8d, + }, // 695 + { + +0.5186077356338501d, +2.857419553449673E-8d, + }, // 696 + { + +0.5191890001296997d, -9.51761338269325E-9d, + }, // 697 + { + +0.5197699069976807d, -2.7609457648450225E-8d, + }, // 698 + { + +0.520350456237793d, -2.5309316441333305E-8d, + }, // 699 + { + +0.5209306478500366d, -2.2258513086839407E-9d, + }, // 700 + { + +0.5215104818344116d, +4.203159541613745E-8d, + }, // 701 + { + +0.5220900774002075d, -1.1356287358852729E-8d, + }, // 702 + { + +0.5226693153381348d, -4.279090925831093E-8d, + }, // 703 + { + +0.5232481956481934d, -5.188364552285819E-8d, + }, // 704 + { + +0.5238267183303833d, -3.82465458937857E-8d, + }, // 705 + { + +0.5244048833847046d, -1.4923330530645769E-9d, + }, // 706 + { + +0.5249826908111572d, +5.8765598932137004E-8d, + }, // 707 + { + +0.5255602598190308d, +2.3703896609663678E-8d, + }, // 708 + { + +0.5261374711990356d, +1.2917117341231647E-8d, + }, // 709 + { + +0.5267143249511719d, +2.6789862192139226E-8d, + }, // 710 + { + +0.527290940284729d, -5.350322253112414E-8d, + }, // 711 + { + +0.5278670787811279d, +1.0839714455426386E-8d, + }, // 712 + { + +0.5284429788589478d, -1.821729591343314E-8d, + }, // 713 + { + +0.5290185213088989d, -2.1083014672301448E-8d, + }, // 714 + { + +0.5295937061309814d, +2.623848491704216E-9d, + }, // 715 + { + +0.5301685333251953d, +5.328392630534142E-8d, + }, // 716 + { + +0.5307431221008301d, +1.206790586971942E-8d, + }, // 717 + { + +0.5313173532485962d, -1.4356011804377797E-9d, + }, // 718 + { + +0.5318912267684937d, +1.3152074173459994E-8d, + }, // 719 + { + +0.5324647426605225d, +5.6208949382936426E-8d, + }, // 720 + { + +0.5330380201339722d, +8.90310227565917E-9d, + }, // 721 + { + +0.5336109399795532d, -9.179458802504127E-9d, + }, // 722 + { + +0.5341835021972656d, +2.337337845617735E-9d, + }, // 723 + { + +0.5347557067871094d, +4.3828918300477925E-8d, + }, // 724 + { + +0.535327672958374d, -3.5392250480081715E-9d, + }, // 725 + { + +0.53589928150177d, -2.0183663375378704E-8d, + }, // 726 + { + +0.5364705324172974d, -5.730898606435436E-9d, + }, // 727 + { + +0.537041425704956d, +4.0191927599879235E-8d, + }, // 728 + { + +0.5376120805740356d, -1.2522542401353875E-9d, + }, // 729 + { + +0.5381823778152466d, -1.0482571326594316E-8d, + }, // 730 + { + +0.5387523174285889d, +1.2871924223480165E-8d, + }, // 731 + { + +0.539322018623352d, -5.002774317612589E-8d, + }, // 732 + { + +0.539891242980957d, +3.960668706590162E-8d, + }, // 733 + { + +0.5404602289199829d, +4.372568630242375E-8d, + }, // 734 + { + +0.5410289764404297d, -3.730232461206926E-8d, + }, // 735 + { + +0.5415972471237183d, +3.5309026109857795E-8d, + }, // 736 + { + +0.5421652793884277d, +2.3508325311148225E-8d, + }, // 737 + { + +0.5427329540252686d, +4.6871403168921666E-8d, + }, // 738 + { + +0.5433003902435303d, -1.3445113140270216E-8d, + }, // 739 + { + +0.5438674688339233d, -3.786663982218041E-8d, + }, // 740 + { + +0.5444341897964478d, -2.602850370608209E-8d, + }, // 741 + { + +0.5450005531311035d, +2.2433348713144506E-8d, + }, // 742 + { + +0.5455666780471802d, -1.1326936872620137E-8d, + }, // 743 + { + +0.5461324453353882d, -7.737252533211342E-9d, + }, // 744 + { + +0.5466978549957275d, +3.3564604642699844E-8d, + }, // 745 + { + +0.5472630262374878d, -6.269066061111782E-9d, + }, // 746 + { + +0.5478278398513794d, -7.667998948729528E-9d, + }, // 747 + { + +0.5483922958374023d, +2.9728170818998143E-8d, + }, // 748 + { + +0.5489565134048462d, -1.2930091396008281E-8d, + }, // 749 + { + +0.5495203733444214d, -1.607434968107079E-8d, + }, // 750 + { + +0.5500838756561279d, +2.0653935146671156E-8d, + }, // 751 + { + +0.5506471395492554d, -2.1596593091833788E-8d, + }, // 752 + { + +0.5512100458145142d, -2.3259315921149476E-8d, + }, // 753 + { + +0.5517725944519043d, +1.6022492496522704E-8d, + }, // 754 + { + +0.5523349046707153d, -2.260433328226171E-8d, + }, // 755 + { + +0.5528968572616577d, -1.957497997726303E-8d, + }, // 756 + { + +0.5534584522247314d, +2.5465477111883854E-8d, + }, // 757 + { + +0.5540198087692261d, -6.33792454933092E-9d, + }, // 758 + { + +0.554580807685852d, +4.577835263278281E-9d, + }, // 759 + { + +0.5551414489746094d, +5.856589221771548E-8d, + }, // 760 + { + +0.5557018518447876d, +3.6769498759522324E-8d, + }, // 761 + { + +0.5562618970870972d, +5.874989409410614E-8d, + }, // 762 + { + +0.5568217039108276d, +5.649147309876989E-9d, + }, // 763 + { + +0.5573811531066895d, -2.9726830960751796E-9d, + }, // 764 + { + +0.5579402446746826d, +3.323458344853057E-8d, + }, // 765 + { + +0.5584990978240967d, -4.588749093664028E-9d, + }, // 766 + { + +0.5590575933456421d, +3.115616594184543E-9d, + }, // 767 + { + +0.5596157312393188d, +5.6696103838614634E-8d, + }, // 768 + { + +0.5601736307144165d, +3.7291263280048303E-8d, + }, // 769 + { + +0.5607312917709351d, -5.4751646725093355E-8d, + }, // 770 + { + +0.5612884759902954d, +1.9332630743320287E-8d, + }, // 771 + { + +0.5618454217910767d, +2.147161515775941E-8d, + }, // 772 + { + +0.5624021291732788d, -4.7989172862560625E-8d, + }, // 773 + { + +0.5629583597183228d, +4.971378973445109E-8d, + }, // 774 + { + +0.5635144710540771d, -4.2702997139152675E-8d, + }, // 775 + { + +0.5640701055526733d, +3.273212962622764E-8d, + }, // 776 + { + +0.5646255016326904d, +3.79438125545842E-8d, + }, // 777 + { + +0.5651806592941284d, -2.6725298288329835E-8d, + }, // 778 + { + +0.5657354593276978d, -4.1723833577410244E-8d, + }, // 779 + { + +0.5662899017333984d, -6.71028256490915E-9d, + }, // 780 + { + +0.56684410572052d, -4.055299181908475E-8d, + }, // 781 + { + +0.567397952079773d, -2.3702295314000405E-8d, + }, // 782 + { + +0.5679514408111572d, +4.4181618172507453E-8d, + }, // 783 + { + +0.5685046911239624d, +4.4228706309734985E-8d, + }, // 784 + { + +0.5690577030181885d, -2.3222346436879016E-8d, + }, // 785 + { + +0.5696103572845459d, -3.862412756175274E-8d, + }, // 786 + { + +0.5701626539230347d, -1.6390743801589046E-9d, + }, // 787 + { + +0.5707147121429443d, -3.1139472791083883E-8d, + }, // 788 + { + +0.5712664127349854d, -7.579587391156013E-9d, + }, // 789 + { + +0.5718178749084473d, -4.983281844744412E-8d, + }, // 790 + { + +0.5723689794540405d, -3.835454246739619E-8d, + }, // 791 + { + +0.5729197263717651d, +2.7190020372374008E-8d, + }, // 792 + { + +0.5734702348709106d, +2.7925807446276126E-8d, + }, // 793 + { + +0.574020504951477d, -3.5813506001861646E-8d, + }, // 794 + { + +0.5745704174041748d, -4.448550564530588E-8d, + }, // 795 + { + +0.5751199722290039d, +2.2423840341717488E-9d, + }, // 796 + { + +0.5756692886352539d, -1.450709904687712E-8d, + }, // 797 + { + +0.5762182474136353d, +2.4806815282282017E-8d, + }, // 798 + { + +0.5767669677734375d, +1.3057724436551892E-9d, + }, // 799 + { + +0.5773153305053711d, +3.4529452510568104E-8d, + }, // 800 + { + +0.5778634548187256d, +5.598413198183808E-9d, + }, // 801 + { + +0.5784112215042114d, +3.405124925700107E-8d, + }, // 802 + { + +0.5789587497711182d, +1.0074354568442952E-9d, + }, // 803 + { + +0.5795059204101562d, +2.600448597385527E-8d, + }, // 804 + { + +0.5800528526306152d, -9.83920263200211E-9d, + }, // 805 + { + +0.5805994272232056d, +1.3012807963586057E-8d, + }, // 806 + { + +0.5811457633972168d, -2.432215917965441E-8d, + }, // 807 + { + +0.5816917419433594d, -2.308736892479391E-9d, + }, // 808 + { + +0.5822374820709229d, -3.983067093146514E-8d, + }, // 809 + { + +0.5827828645706177d, -1.735366061128156E-8d, + }, // 810 + { + +0.5833280086517334d, -5.376251584638963E-8d, + }, // 811 + { + +0.5838727951049805d, -2.952399778965259E-8d, + }, // 812 + { + +0.5844172239303589d, +5.5685313670430624E-8d, + }, // 813 + { + +0.5849615335464478d, -3.6230268489088716E-8d, + }, // 814 + { + +0.5855053663253784d, +5.267948957869391E-8d, + }, // 815 + { + +0.5860490798950195d, -3.489144132234588E-8d, + }, // 816 + { + +0.5865923166275024d, +5.9006122320612716E-8d, + }, // 817 + { + +0.5871354341506958d, -2.2934896740542648E-8d, + }, // 818 + { + +0.5876781940460205d, -4.1975650319859075E-8d, + }, // 819 + { + +0.5882205963134766d, +2.2036094805348692E-9d, + }, // 820 + { + +0.5887627601623535d, -9.287179048539306E-9d, + }, // 821 + { + +0.5893045663833618d, +4.3079982556221595E-8d, + }, // 822 + { + +0.589846134185791d, +4.041399585161321E-8d, + }, // 823 + { + +0.5903874635696411d, -1.696746473863933E-8d, + }, // 824 + { + +0.5909284353256226d, -9.53795080582038E-9d, + }, // 825 + { + +0.5914691686630249d, -5.619010749352923E-8d, + }, // 826 + { + +0.5920095443725586d, -3.7398514182529506E-8d, + }, // 827 + { + +0.5925495624542236d, +4.71524479659295E-8d, + }, // 828 + { + +0.5930894613265991d, -4.0640692434639215E-8d, + }, // 829 + { + +0.5936288833618164d, +5.716453096255401E-8d, + }, // 830 + { + +0.5941681861877441d, -1.6745661720946737E-8d, + }, // 831 + { + +0.5947071313858032d, -2.3639110433141897E-8d, + }, // 832 + { + +0.5952457189559937d, +3.67972590471072E-8d, + }, // 833 + { + +0.595784068107605d, +4.566672575206695E-8d, + }, // 834 + { + +0.5963221788406372d, +3.2813537149653483E-9d, + }, // 835 + { + +0.5968599319458008d, +2.916199305533732E-8d, + }, // 836 + { + +0.5973974466323853d, +4.410412409109416E-9d, + }, // 837 + { + +0.5979346036911011d, +4.85464582112459E-8d, + }, // 838 + { + +0.5984715223312378d, +4.267089756924666E-8d, + }, // 839 + { + +0.5990082025527954d, -1.2906712010774655E-8d, + }, // 840 + { + +0.5995445251464844d, +1.3319784467641742E-9d, + }, // 841 + { + +0.6000806093215942d, -3.35137581974451E-8d, + }, // 842 + { + +0.6006163358688354d, +2.0734340706476473E-9d, + }, // 843 + { + +0.6011518239974976d, -1.0808162722402073E-8d, + }, // 844 + { + +0.601686954498291d, +4.735781872502109E-8d, + }, // 845 + { + +0.6022218465805054d, +5.76686738430634E-8d, + }, // 846 + { + +0.6027565002441406d, +2.043049589651736E-8d, + }, // 847 + { + +0.6032907962799072d, +5.515817703577808E-8d, + }, // 848 + { + +0.6038248538970947d, +4.2947540692649586E-8d, + }, // 849 + { + +0.6043586730957031d, -1.589678872195875E-8d, + }, // 850 + { + +0.6048921346664429d, -1.8613847754677912E-9d, + }, // 851 + { + +0.6054253578186035d, -3.3851886626187444E-8d, + }, // 852 + { + +0.6059582233428955d, +7.64416021682279E-9d, + }, // 853 + { + +0.6064908504486084d, +3.7201467248814224E-9d, + }, // 854 + { + +0.6070232391357422d, -4.532172996647129E-8d, + }, // 855 + { + +0.6075552701950073d, -1.997046552871766E-8d, + }, // 856 + { + +0.6080870628356934d, -3.913411606668587E-8d, + }, // 857 + { + +0.6086184978485107d, +1.6697361107868944E-8d, + }, // 858 + { + +0.609149694442749d, +2.8614950293715483E-8d, + }, // 859 + { + +0.6096806526184082d, -3.081552929643174E-9d, + }, // 860 + { + +0.6102112531661987d, +4.111645931319645E-8d, + }, // 861 + { + +0.6107416152954102d, +4.2298539553668435E-8d, + }, // 862 + { + +0.6112717390060425d, +7.630546413718035E-10d, + }, // 863 + { + +0.6118015050888062d, +3.601718675118614E-8d, + }, // 864 + { + +0.6123310327529907d, +2.914906573537692E-8d, + }, // 865 + { + +0.6128603219985962d, -1.9544361222269494E-8d, + }, // 866 + { + +0.613389253616333d, +9.442671392695732E-9d, + }, // 867 + { + +0.6139179468154907d, -2.8031202304593286E-9d, + }, // 868 + { + +0.6144464015960693d, -5.598619958143586E-8d, + }, // 869 + { + +0.6149744987487793d, -3.060220883766096E-8d, + }, // 870 + { + +0.6155023574829102d, -4.556583652800433E-8d, + }, // 871 + { + +0.6160298585891724d, +1.8626341656366314E-8d, + }, // 872 + { + +0.6165571212768555d, +4.305870564227991E-8d, + }, // 873 + { + +0.6170841455459595d, +2.8024460607734262E-8d, + }, // 874 + { + +0.6176109313964844d, -2.6183651590639875E-8d, + }, // 875 + { + +0.6181373596191406d, -6.406189112730307E-11d, + }, // 876 + { + +0.6186635494232178d, -1.2534241706168776E-8d, + }, // 877 + { + +0.6191893815994263d, +5.5906456251308664E-8d, + }, // 878 + { + +0.6197150945663452d, -3.286964881802063E-8d, + }, // 879 + { + +0.6202404499053955d, -4.0153537978961E-8d, + }, // 880 + { + +0.6207654476165771d, +3.434477109643361E-8d, + }, // 881 + { + +0.6212903261184692d, -4.750377491075032E-8d, + }, // 882 + { + +0.6218148469924927d, -4.699152670372743E-8d, + }, // 883 + { + +0.6223390102386475d, +3.617013128065961E-8d, + }, // 884 + { + +0.6228630542755127d, -3.6149218175202596E-8d, + }, // 885 + { + +0.6233867406845093d, -2.5243286814648133E-8d, + }, // 886 + { + +0.6239101886749268d, -5.003410681432538E-8d, + }, // 887 + { + +0.6244332790374756d, +8.974417915105033E-9d, + }, // 888 + { + +0.6249561309814453d, +3.285935446876949E-8d, + }, // 889 + { + +0.6254787445068359d, +2.190661054038537E-8d, + }, // 890 + { + +0.6260011196136475d, -2.3598354190515998E-8d, + }, // 891 + { + +0.6265231370925903d, +1.5838762427747586E-8d, + }, // 892 + { + +0.6270449161529541d, +2.129323729978037E-8d, + }, // 893 + { + +0.6275664567947388d, -6.950808333865794E-9d, + }, // 894 + { + +0.6280876398086548d, +5.059959203156465E-8d, + }, // 895 + { + +0.6286087036132812d, -4.41909071122557E-8d, + }, // 896 + { + +0.6291294097900391d, -5.262093550784066E-8d, + }, // 897 + { + +0.6296497583389282d, +2.559185648444699E-8d, + }, // 898 + { + +0.6301699876785278d, -4.768920119497491E-8d, + }, // 899 + { + +0.6306898593902588d, -3.376406008397877E-8d, + }, // 900 + { + +0.6312094926834106d, -5.156097914033476E-8d, + }, // 901 + { + +0.6317287683486938d, +1.840992392368355E-8d, + }, // 902 + { + +0.632247805595398d, +5.721951534729663E-8d, + }, // 903 + { + +0.6327667236328125d, -5.406177467045421E-8d, + }, // 904 + { + +0.6332851648330688d, +4.247320713683124E-8d, + }, // 905 + { + +0.6338034868240356d, -1.0524557502830645E-8d, + }, // 906 + { + +0.6343214511871338d, +2.5641927558519502E-8d, + }, // 907 + { + +0.6348391771316528d, +3.204135737993823E-8d, + }, // 908 + { + +0.6353566646575928d, +8.951285029786536E-9d, + }, // 909 + { + +0.6358739137649536d, -4.335116707228395E-8d, + }, // 910 + { + +0.6363908052444458d, -5.380016714089483E-9d, + }, // 911 + { + +0.6369074583053589d, +3.931710344901743E-9d, + }, // 912 + { + +0.6374238729476929d, -1.5140150088220166E-8d, + }, // 913 + { + +0.6379399299621582d, +5.688910024377372E-8d, + }, // 914 + { + +0.638455867767334d, -1.8124135273572568E-8d, + }, // 915 + { + +0.6389714479446411d, -1.486720391901626E-9d, + }, // 916 + { + +0.6394867897033691d, -1.2133811978747018E-8d, + }, // 917 + { + +0.6400018930435181d, -4.9791700939901716E-8d, + }, // 918 + { + +0.6405166387557983d, +5.022188652837274E-9d, + }, // 919 + { + +0.6410311460494995d, +3.337143177933685E-8d, + }, // 920 + { + +0.6415454149246216d, +3.55284719912458E-8d, + }, // 921 + { + +0.6420594453811646d, +1.1765332726757802E-8d, + }, // 922 + { + +0.6425732374191284d, -3.7646381826067834E-8d, + }, // 923 + { + +0.6430866718292236d, +6.773803682579552E-9d, + }, // 924 + { + +0.6435998678207397d, +2.608736797081283E-8d, + }, // 925 + { + +0.6441128253936768d, +2.056466263408266E-8d, + }, // 926 + { + +0.6446255445480347d, -9.524376551107945E-9d, + }, // 927 + { + +0.6451379060745239d, +5.5299060775883977E-8d, + }, // 928 + { + +0.6456501483917236d, -2.3114497793159813E-8d, + }, // 929 + { + +0.6461620330810547d, -6.077779731902102E-9d, + }, // 930 + { + +0.6466736793518066d, -1.2531793589140273E-8d, + }, // 931 + { + +0.6471850872039795d, -4.220866994206517E-8d, + }, // 932 + { + +0.6476961374282837d, +2.4368339445199057E-8d, + }, // 933 + { + +0.6482070684432983d, -5.095229574221907E-8d, + }, // 934 + { + +0.6487176418304443d, -2.9485356677301627E-8d, + }, // 935 + { + +0.6492279767990112d, -3.0173901411577916E-8d, + }, // 936 + { + +0.649738073348999d, -5.275210583909726E-8d, + }, // 937 + { + +0.6502478122711182d, +2.2254737134350224E-8d, + }, // 938 + { + +0.6507574319839478d, -4.330693978322885E-8d, + }, // 939 + { + +0.6512666940689087d, -1.0753950588009912E-8d, + }, // 940 + { + +0.6517757177352905d, +9.686179886293545E-10d, + }, // 941 + { + +0.6522845029830933d, -7.875434494414498E-9d, + }, // 942 + { + +0.6527930498123169d, -3.702271091849158E-8d, + }, // 943 + { + +0.6533012390136719d, +3.2999073763758614E-8d, + }, // 944 + { + +0.6538093090057373d, -3.5966064858620067E-8d, + }, // 945 + { + +0.6543170213699341d, -5.23735298540578E-9d, + }, // 946 + { + +0.6548244953155518d, +6.237715351293023E-9d, + }, // 947 + { + +0.6553317308425903d, -1.279462699936282E-9d, + }, // 948 + { + +0.6558387279510498d, -2.7527887552743672E-8d, + }, // 949 + { + +0.6563453674316406d, +4.696233317356646E-8d, + }, // 950 + { + +0.6568518877029419d, -1.5967172745329108E-8d, + }, // 951 + { + +0.6573580503463745d, +2.2361985518423144E-8d, + }, // 952 + { + +0.657863974571228d, +4.2999935789083046E-8d, + }, // 953 + { + +0.6583696603775024d, +4.620570188811826E-8d, + }, // 954 + { + +0.6588751077651978d, +3.223791487908353E-8d, + }, // 955 + { + +0.659380316734314d, +1.3548138612715822E-9d, + }, // 956 + { + +0.6598852872848511d, -4.618575323863973E-8d, + }, // 957 + { + +0.6603899002075195d, +9.082960673843353E-9d, + }, // 958 + { + +0.6608942747116089d, +4.820873399634487E-8d, + }, // 959 + { + +0.6613985300064087d, -4.776104368314602E-8d, + }, // 960 + { + +0.6619024276733398d, -4.0151502150238136E-8d, + }, // 961 + { + +0.6624060869216919d, -4.791602708710648E-8d, + }, // 962 + { + +0.6629093885421753d, +4.8410188461165925E-8d, + }, // 963 + { + +0.6634125709533691d, +1.0663697110471944E-8d, + }, // 964 + { + +0.6639155149459839d, -4.1691464781797555E-8d, + }, // 965 + { + +0.66441810131073d, +1.080835500478704E-8d, + }, // 966 + { + +0.664920449256897d, +4.920784622407246E-8d, + }, // 967 + { + +0.6654226779937744d, -4.544868396511241E-8d, + }, // 968 + { + +0.6659245491027832d, -3.448944157854234E-8d, + }, // 969 + { + +0.6664261817932129d, -3.6870882345139385E-8d, + }, // 970 + { + +0.6669275760650635d, -5.234055273962444E-8d, + }, // 971 + { + +0.6674286127090454d, +3.856291077979099E-8d, + }, // 972 + { + +0.6679295301437378d, -2.327375671320742E-9d, + }, // 973 + { + +0.6684302091598511d, -5.555080534042001E-8d, + }, // 974 + { + +0.6689305305480957d, -1.6471487337453832E-9d, + }, // 975 + { + +0.6694306135177612d, +4.042486803683015E-8d, + }, // 976 + { + +0.6699305772781372d, -4.8293856891818295E-8d, + }, // 977 + { + +0.6704301834106445d, -2.9134931730784303E-8d, + }, // 978 + { + +0.6709295511245728d, -2.1058207594753368E-8d, + }, // 979 + { + +0.6714286804199219d, -2.3814619551682855E-8d, + }, // 980 + { + +0.6719275712966919d, -3.7155475428252136E-8d, + }, // 981 + { + +0.6724261045455933d, +5.8376834484391746E-8d, + }, // 982 + { + +0.6729245185852051d, +2.4611679969129262E-8d, + }, // 983 + { + +0.6734226942062378d, -1.899407107267079E-8d, + }, // 984 + { + +0.6739205121994019d, +4.7016079464436395E-8d, + }, // 985 + { + +0.6744182109832764d, -1.5529608026276525E-8d, + }, // 986 + { + +0.6749155521392822d, +3.203391672602453E-8d, + }, // 987 + { + +0.6754127740859985d, -4.8465821804075345E-8d, + }, // 988 + { + +0.6759096384048462d, -1.8364507801369988E-8d, + }, // 989 + { + +0.6764062643051147d, +3.3739397633046517E-9d, + }, // 990 + { + +0.6769026517868042d, +1.6994526063192333E-8d, + }, // 991 + { + +0.6773988008499146d, +2.2741891590028428E-8d, + }, // 992 + { + +0.6778947114944458d, +2.0860312877435047E-8d, + }, // 993 + { + +0.678390383720398d, +1.1593703222523284E-8d, + }, // 994 + { + +0.678885817527771d, -4.814386594291911E-9d, + }, // 995 + { + +0.6793810129165649d, -2.812076759125914E-8d, + }, // 996 + { + +0.6798759698867798d, -5.808261186903479E-8d, + }, // 997 + { + +0.680370569229126d, +2.4751837654582522E-8d, + }, // 998 + { + +0.6808650493621826d, -1.7793890245755405E-8d, + }, // 999 + { + +0.6813591718673706d, +5.294053246347931E-8d, + }, // 1000 + { + +0.681853175163269d, -1.2220826223585654E-9d, + }, // 1001 + { + +0.6823468208312988d, +5.8377876767612725E-8d, + }, // 1002 + { + +0.6828403472900391d, -6.437492120743254E-9d, + }, // 1003 + { + +0.6833335161209106d, +4.2990710043633113E-8d, + }, // 1004 + { + +0.6838265657424927d, -3.1516131027023284E-8d, + }, // 1005 + { + +0.684319257736206d, +8.70017386744679E-9d, + }, // 1006 + { + +0.6848117113113403d, +4.466959125843237E-8d, + }, // 1007 + { + +0.6853040456771851d, -4.25782656420497E-8d, + }, // 1008 + { + +0.6857960224151611d, -1.4386267593671393E-8d, + }, // 1009 + { + +0.6862877607345581d, +1.0274494061148778E-8d, + }, // 1010 + { + +0.686779260635376d, +3.164186629229597E-8d, + }, // 1011 + { + +0.6872705221176147d, +4.995334552140326E-8d, + }, // 1012 + { + +0.687761664390564d, -5.3763211240398744E-8d, + }, // 1013 + { + +0.6882524490356445d, -4.0852427502515625E-8d, + }, // 1014 + { + +0.688742995262146d, -3.0287143914420064E-8d, + }, // 1015 + { + +0.6892333030700684d, -2.183125937905008E-8d, + }, // 1016 + { + +0.6897233724594116d, -1.524901992178814E-8d, + }, // 1017 + { + +0.6902132034301758d, -1.0305018010328949E-8d, + }, // 1018 + { + +0.6907027959823608d, -6.764191876212205E-9d, + }, // 1019 + { + +0.6911921501159668d, -4.391824838015402E-9d, + }, // 1020 + { + +0.6916812658309937d, -2.9535446262017846E-9d, + }, // 1021 + { + +0.6921701431274414d, -2.2153227096187463E-9d, + }, // 1022 + { + +0.6926587820053101d, -1.943473623641502E-9d, + }, // 1023 + }; + + /** Class contains only static methods. */ + private FastMathLiteralArrays() {} + + /** + * Load "EXP_INT_A". + * + * @return a clone of the data array. + */ + static double[] loadExpIntA() { + return EXP_INT_A.clone(); + } + + /** + * Load "EXP_INT_B". + * + * @return a clone of the data array. + */ + static double[] loadExpIntB() { + return EXP_INT_B.clone(); + } + + /** + * Load "EXP_FRAC_A". + * + * @return a clone of the data array. + */ + static double[] loadExpFracA() { + return EXP_FRAC_A.clone(); + } + + /** + * Load "EXP_FRAC_B". + * + * @return a clone of the data array. + */ + static double[] loadExpFracB() { + return EXP_FRAC_B.clone(); + } + + /** + * Load "LN_MANT". + * + * @return a clone of the data array. + */ + static double[][] loadLnMant() { + return LN_MANT.clone(); + } +} diff --git a/src/main/java/org/apache/commons/math3/util/Incrementor.java b/src/main/java/org/apache/commons/math3/util/Incrementor.java new file mode 100644 index 0000000..de9094e --- /dev/null +++ b/src/main/java/org/apache/commons/math3/util/Incrementor.java @@ -0,0 +1,218 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math3.util; + +import org.apache.commons.math3.exception.MaxCountExceededException; +import org.apache.commons.math3.exception.NullArgumentException; + +/** + * Utility that increments a counter until a maximum is reached, at which point, the instance will + * by default throw a {@link MaxCountExceededException}. However, the user is able to override this + * behaviour by defining a custom {@link MaxCountExceededCallback callback}, in order to e.g. select + * which exception must be thrown. + * + * @since 3.0 + * @deprecated Use {@link IntegerSequence.Incrementor} instead. + */ +@Deprecated +public class Incrementor { + /** Upper limit for the counter. */ + private int maximalCount; + + /** Current count. */ + private int count = 0; + + /** Function called at counter exhaustion. */ + private final MaxCountExceededCallback maxCountCallback; + + /** + * Default constructor. For the new instance to be useful, the maximal count must be set by + * calling {@link #setMaximalCount(int) setMaximalCount}. + */ + public Incrementor() { + this(0); + } + + /** + * Defines a maximal count. + * + * @param max Maximal count. + */ + public Incrementor(int max) { + this( + max, + new MaxCountExceededCallback() { + /** {@inheritDoc} */ + public void trigger(int max) throws MaxCountExceededException { + throw new MaxCountExceededException(max); + } + }); + } + + /** + * Defines a maximal count and a callback method to be triggered at counter exhaustion. + * + * @param max Maximal count. + * @param cb Function to be called when the maximal count has been reached. + * @throws NullArgumentException if {@code cb} is {@code null} + */ + public Incrementor(int max, MaxCountExceededCallback cb) throws NullArgumentException { + if (cb == null) { + throw new NullArgumentException(); + } + maximalCount = max; + maxCountCallback = cb; + } + + /** + * Sets the upper limit for the counter. This does not automatically reset the current count to + * zero (see {@link #resetCount()}). + * + * @param max Upper limit of the counter. + */ + public void setMaximalCount(int max) { + maximalCount = max; + } + + /** + * Gets the upper limit of the counter. + * + * @return the counter upper limit. + */ + public int getMaximalCount() { + return maximalCount; + } + + /** + * Gets the current count. + * + * @return the current count. + */ + public int getCount() { + return count; + } + + /** + * Checks whether a single increment is allowed. + * + * @return {@code false} if the next call to {@link #incrementCount(int) incrementCount} will + * trigger a {@code MaxCountExceededException}, {@code true} otherwise. + */ + public boolean canIncrement() { + return count < maximalCount; + } + + /** + * Performs multiple increments. See the other {@link #incrementCount() incrementCount} method). + * + * @param value Number of increments. + * @throws MaxCountExceededException at counter exhaustion. + */ + public void incrementCount(int value) throws MaxCountExceededException { + for (int i = 0; i < value; i++) { + incrementCount(); + } + } + + /** + * Adds one to the current iteration count. At counter exhaustion, this method will call the + * {@link MaxCountExceededCallback#trigger(int) trigger} method of the callback object passed to + * the {@link #Incrementor(int,MaxCountExceededCallback) constructor}. If not explictly set, a + * default callback is used that will throw a {@code MaxCountExceededException}. + * + * @throws MaxCountExceededException at counter exhaustion, unless a custom {@link + * MaxCountExceededCallback callback} has been set at construction. + */ + public void incrementCount() throws MaxCountExceededException { + if (++count > maximalCount) { + maxCountCallback.trigger(maximalCount); + } + } + + /** Resets the counter to 0. */ + public void resetCount() { + count = 0; + } + + /** + * Defines a method to be called at counter exhaustion. The {@link #trigger(int) trigger} method + * should usually throw an exception. + */ + public interface MaxCountExceededCallback { + /** + * Function called when the maximal count has been reached. + * + * @param maximalCount Maximal count. + * @throws MaxCountExceededException at counter exhaustion + */ + void trigger(int maximalCount) throws MaxCountExceededException; + } + + /** + * Create an instance that delegates everything to a {@link IntegerSequence.Incrementor}. + * + * <p>This factory method is intended only as a temporary hack for internal use in Apache + * Commons Math 3.X series, when {@code Incrementor} is required in interface (as a return value + * or in protected fields). It should <em>not</em> be used in other cases. The {@link + * IntegerSequence.Incrementor} class should be used instead of {@code Incrementor}. + * + * <p>All methods are mirrored to the underlying {@link IntegerSequence.Incrementor}, as long as + * neither {@link #setMaximalCount(int)} nor {@link #resetCount()} are called. If one of these + * two methods is called, the created instance becomes independent of the {@link + * IntegerSequence.Incrementor} used at creation. The rationale is that {@link + * IntegerSequence.Incrementor} cannot change their maximal count and cannot be reset. + * + * @param incrementor wrapped {@link IntegerSequence.Incrementor} + * @return an incrementor wrapping an {@link IntegerSequence.Incrementor} + * @since 3.6 + */ + public static Incrementor wrap(final IntegerSequence.Incrementor incrementor) { + return new Incrementor() { + + /** Underlying incrementor. */ + private IntegerSequence.Incrementor delegate; + + { + // set up matching values at initialization + delegate = incrementor; + super.setMaximalCount(delegate.getMaximalCount()); + super.incrementCount(delegate.getCount()); + } + + /** {@inheritDoc} */ + @Override + public void setMaximalCount(int max) { + super.setMaximalCount(max); + delegate = delegate.withMaximalCount(max); + } + + /** {@inheritDoc} */ + @Override + public void resetCount() { + super.resetCount(); + delegate = delegate.withStart(0); + } + + /** {@inheritDoc} */ + @Override + public void incrementCount() { + super.incrementCount(); + delegate.increment(); + } + }; + } +} diff --git a/src/main/java/org/apache/commons/math3/util/IntegerSequence.java b/src/main/java/org/apache/commons/math3/util/IntegerSequence.java new file mode 100644 index 0000000..7859ec3 --- /dev/null +++ b/src/main/java/org/apache/commons/math3/util/IntegerSequence.java @@ -0,0 +1,328 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math3.util; + +import org.apache.commons.math3.exception.MathUnsupportedOperationException; +import org.apache.commons.math3.exception.MaxCountExceededException; +import org.apache.commons.math3.exception.NotStrictlyPositiveException; +import org.apache.commons.math3.exception.NullArgumentException; +import org.apache.commons.math3.exception.ZeroException; + +import java.util.Iterator; + +/** + * Provides a sequence of integers. + * + * @since 3.6 + */ +public class IntegerSequence { + /** Utility class contains only static methods. */ + private IntegerSequence() {} + + /** + * Creates a sequence {@code [start .. end]}. It calls {@link #range(int,int,int) range(start, + * end, 1)}. + * + * @param start First value of the range. + * @param end Last value of the range. + * @return a range. + */ + public static Range range(int start, int end) { + return range(start, end, 1); + } + + /** + * Creates a sequence \( a_i, i < 0 <= n \) where \( a_i = start + i * step \) and \( n \) is + * such that \( a_n <= max \) and \( a_{n+1} > max \). + * + * @param start First value of the range. + * @param max Last value of the range that satisfies the above construction rule. + * @param step Increment. + * @return a range. + */ + public static Range range(final int start, final int max, final int step) { + return new Range(start, max, step); + } + + /** Generates a sequence of integers. */ + public static class Range implements Iterable<Integer> { + /** Number of integers contained in this range. */ + private final int size; + + /** First value. */ + private final int start; + + /** Final value. */ + private final int max; + + /** Increment. */ + private final int step; + + /** + * Creates a sequence \( a_i, i < 0 <= n \) where \( a_i = start + i * step \) and \( n \) + * is such that \( a_n <= max \) and \( a_{n+1} > max \). + * + * @param start First value of the range. + * @param max Last value of the range that satisfies the above construction rule. + * @param step Increment. + */ + public Range(int start, int max, int step) { + this.start = start; + this.max = max; + this.step = step; + + final int s = (max - start) / step + 1; + this.size = s < 0 ? 0 : s; + } + + /** + * Gets the number of elements contained in the range. + * + * @return the size of the range. + */ + public int size() { + return size; + } + + /** {@inheritDoc} */ + public Iterator<Integer> iterator() { + return Incrementor.create() + .withStart(start) + .withMaximalCount(max + (step > 0 ? 1 : -1)) + .withIncrement(step); + } + } + + /** + * Utility that increments a counter until a maximum is reached, at which point, the instance + * will by default throw a {@link MaxCountExceededException}. However, the user is able to + * override this behaviour by defining a custom {@link MaxCountExceededCallback callback}, in + * order to e.g. select which exception must be thrown. + */ + public static class Incrementor implements Iterator<Integer> { + /** Default callback. */ + private static final MaxCountExceededCallback CALLBACK = + new MaxCountExceededCallback() { + /** {@inheritDoc} */ + public void trigger(int max) throws MaxCountExceededException { + throw new MaxCountExceededException(max); + } + }; + + /** Initial value the counter. */ + private final int init; + + /** Upper limit for the counter. */ + private final int maximalCount; + + /** Increment. */ + private final int increment; + + /** Function called at counter exhaustion. */ + private final MaxCountExceededCallback maxCountCallback; + + /** Current count. */ + private int count = 0; + + /** + * Defines a method to be called at counter exhaustion. The {@link #trigger(int) trigger} + * method should usually throw an exception. + */ + public interface MaxCountExceededCallback { + /** + * Function called when the maximal count has been reached. + * + * @param maximalCount Maximal count. + * @throws MaxCountExceededException at counter exhaustion + */ + void trigger(int maximalCount) throws MaxCountExceededException; + } + + /** + * Creates an incrementor. The counter will be exhausted either when {@code max} is reached + * or when {@code nTimes} increments have been performed. + * + * @param start Initial value. + * @param max Maximal count. + * @param step Increment. + * @param cb Function to be called when the maximal count has been reached. + * @throws NullArgumentException if {@code cb} is {@code null}. + */ + private Incrementor(int start, int max, int step, MaxCountExceededCallback cb) + throws NullArgumentException { + if (cb == null) { + throw new NullArgumentException(); + } + this.init = start; + this.maximalCount = max; + this.increment = step; + this.maxCountCallback = cb; + this.count = start; + } + + /** + * Factory method that creates a default instance. The initial and maximal values are set to + * 0. For the new instance to be useful, the maximal count must be set by calling {@link + * #withMaximalCount(int) withMaximalCount}. + * + * @return an new instance. + */ + public static Incrementor create() { + return new Incrementor(0, 0, 1, CALLBACK); + } + + /** + * Creates a new instance with a given initial value. The counter is reset to the initial + * value. + * + * @param start Initial value of the counter. + * @return a new instance. + */ + public Incrementor withStart(int start) { + return new Incrementor(start, this.maximalCount, this.increment, this.maxCountCallback); + } + + /** + * Creates a new instance with a given maximal count. The counter is reset to the initial + * value. + * + * @param max Maximal count. + * @return a new instance. + */ + public Incrementor withMaximalCount(int max) { + return new Incrementor(this.init, max, this.increment, this.maxCountCallback); + } + + /** + * Creates a new instance with a given increment. The counter is reset to the initial value. + * + * @param step Increment. + * @return a new instance. + */ + public Incrementor withIncrement(int step) { + if (step == 0) { + throw new ZeroException(); + } + return new Incrementor(this.init, this.maximalCount, step, this.maxCountCallback); + } + + /** + * Creates a new instance with a given callback. The counter is reset to the initial value. + * + * @param cb Callback to be called at counter exhaustion. + * @return a new instance. + */ + public Incrementor withCallback(MaxCountExceededCallback cb) { + return new Incrementor(this.init, this.maximalCount, this.increment, cb); + } + + /** + * Gets the upper limit of the counter. + * + * @return the counter upper limit. + */ + public int getMaximalCount() { + return maximalCount; + } + + /** + * Gets the current count. + * + * @return the current count. + */ + public int getCount() { + return count; + } + + /** + * Checks whether incrementing the counter {@code nTimes} is allowed. + * + * @return {@code false} if calling {@link #increment()} will trigger a {@code + * MaxCountExceededException}, {@code true} otherwise. + */ + public boolean canIncrement() { + return canIncrement(1); + } + + /** + * Checks whether incrementing the counter several times is allowed. + * + * @param nTimes Number of increments. + * @return {@code false} if calling {@link #increment(int) increment(nTimes)} would call the + * {@link MaxCountExceededCallback callback} {@code true} otherwise. + */ + public boolean canIncrement(int nTimes) { + final int finalCount = count + nTimes * increment; + return increment < 0 ? finalCount > maximalCount : finalCount < maximalCount; + } + + /** + * Performs multiple increments. + * + * @param nTimes Number of increments. + * @throws MaxCountExceededException at counter exhaustion. + * @throws NotStrictlyPositiveException if {@code nTimes <= 0}. + * @see #increment() + */ + public void increment(int nTimes) throws MaxCountExceededException { + if (nTimes <= 0) { + throw new NotStrictlyPositiveException(nTimes); + } + + if (!canIncrement(0)) { + maxCountCallback.trigger(maximalCount); + } + count += nTimes * increment; + } + + /** + * Adds the increment value to the current iteration count. At counter exhaustion, this + * method will call the {@link MaxCountExceededCallback#trigger(int) trigger} method of the + * callback object passed to the {@link #withCallback(MaxCountExceededCallback)} method. If + * not explicitly set, a default callback is used that will throw a {@code + * MaxCountExceededException}. + * + * @throws MaxCountExceededException at counter exhaustion, unless a custom {@link + * MaxCountExceededCallback callback} has been set. + * @see #increment(int) + */ + public void increment() throws MaxCountExceededException { + increment(1); + } + + /** {@inheritDoc} */ + public boolean hasNext() { + return canIncrement(0); + } + + /** {@inheritDoc} */ + public Integer next() { + final int value = count; + increment(); + return value; + } + + /** + * Not applicable. + * + * @throws MathUnsupportedOperationException + */ + public void remove() { + throw new MathUnsupportedOperationException(); + } + } +} diff --git a/src/main/java/org/apache/commons/math3/util/IterationEvent.java b/src/main/java/org/apache/commons/math3/util/IterationEvent.java new file mode 100644 index 0000000..5cbca66 --- /dev/null +++ b/src/main/java/org/apache/commons/math3/util/IterationEvent.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math3.util; + +import java.util.EventObject; + +/** + * The root class from which all events occurring while running an {@link IterationManager} should + * be derived. + */ +public class IterationEvent extends EventObject { + /** */ + private static final long serialVersionUID = 20120128L; + + /** The number of iterations performed so far. */ + private final int iterations; + + /** + * Creates a new instance of this class. + * + * @param source the iterative algorithm on which the event initially occurred + * @param iterations the number of iterations performed at the time {@code this} event is + * created + */ + public IterationEvent(final Object source, final int iterations) { + super(source); + this.iterations = iterations; + } + + /** + * Returns the number of iterations performed at the time {@code this} event is created. + * + * @return the number of iterations performed + */ + public int getIterations() { + return iterations; + } +} diff --git a/src/main/java/org/apache/commons/math3/util/IterationListener.java b/src/main/java/org/apache/commons/math3/util/IterationListener.java new file mode 100644 index 0000000..3064acf --- /dev/null +++ b/src/main/java/org/apache/commons/math3/util/IterationListener.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math3.util; + +import java.util.EventListener; + +/** The listener interface for receiving events occurring in an iterative algorithm. */ +public interface IterationListener extends EventListener { + /** + * Invoked after completion of the initial phase of the iterative algorithm (prior to the main + * iteration loop). + * + * @param e The {@link IterationEvent} object. + */ + void initializationPerformed(IterationEvent e); + + /** + * Invoked each time an iteration is completed (in the main iteration loop). + * + * @param e The {@link IterationEvent} object. + */ + void iterationPerformed(IterationEvent e); + + /** + * Invoked each time a new iteration is completed (in the main iteration loop). + * + * @param e The {@link IterationEvent} object. + */ + void iterationStarted(IterationEvent e); + + /** + * Invoked after completion of the operations which occur after breaking out of the main + * iteration loop. + * + * @param e The {@link IterationEvent} object. + */ + void terminationPerformed(IterationEvent e); +} diff --git a/src/main/java/org/apache/commons/math3/util/IterationManager.java b/src/main/java/org/apache/commons/math3/util/IterationManager.java new file mode 100644 index 0000000..83f350b --- /dev/null +++ b/src/main/java/org/apache/commons/math3/util/IterationManager.java @@ -0,0 +1,191 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math3.util; + +import org.apache.commons.math3.exception.MaxCountExceededException; + +import java.util.Collection; +import java.util.concurrent.CopyOnWriteArrayList; + +/** + * This abstract class provides a general framework for managing iterative algorithms. The maximum + * number of iterations can be set, and methods are provided to monitor the current iteration count. + * A lightweight event framework is also provided. + */ +public class IterationManager { + + /** Keeps a count of the number of iterations. */ + private IntegerSequence.Incrementor iterations; + + /** The collection of all listeners attached to this iterative algorithm. */ + private final Collection<IterationListener> listeners; + + /** + * Creates a new instance of this class. + * + * @param maxIterations the maximum number of iterations + */ + public IterationManager(final int maxIterations) { + this.iterations = IntegerSequence.Incrementor.create().withMaximalCount(maxIterations); + this.listeners = new CopyOnWriteArrayList<IterationListener>(); + } + + /** + * Creates a new instance of this class. + * + * @param maxIterations the maximum number of iterations + * @param callBack the function to be called when the maximum number of iterations has been + * reached + * @throws org.apache.commons.math3.exception.NullArgumentException if {@code callBack} is + * {@code null} + * @since 3.1 + * @deprecated as of 3.6, replaced with {@link #IterationManager(int, + * org.apache.commons.math3.util.IntegerSequence.Incrementor.MaxCountExceededCallback)} + */ + @Deprecated + public IterationManager( + final int maxIterations, final Incrementor.MaxCountExceededCallback callBack) { + this( + maxIterations, + new IntegerSequence.Incrementor.MaxCountExceededCallback() { + /** {@inheritDoc} */ + public void trigger(final int maximalCount) throws MaxCountExceededException { + callBack.trigger(maximalCount); + } + }); + } + + /** + * Creates a new instance of this class. + * + * @param maxIterations the maximum number of iterations + * @param callBack the function to be called when the maximum number of iterations has been + * reached + * @throws org.apache.commons.math3.exception.NullArgumentException if {@code callBack} is + * {@code null} + * @since 3.6 + */ + public IterationManager( + final int maxIterations, + final IntegerSequence.Incrementor.MaxCountExceededCallback callBack) { + this.iterations = + IntegerSequence.Incrementor.create() + .withMaximalCount(maxIterations) + .withCallback(callBack); + this.listeners = new CopyOnWriteArrayList<IterationListener>(); + } + + /** + * Attaches a listener to this manager. + * + * @param listener A {@code IterationListener} object. + */ + public void addIterationListener(final IterationListener listener) { + listeners.add(listener); + } + + /** + * Informs all registered listeners that the initial phase (prior to the main iteration loop) + * has been completed. + * + * @param e The {@link IterationEvent} object. + */ + public void fireInitializationEvent(final IterationEvent e) { + for (IterationListener l : listeners) { + l.initializationPerformed(e); + } + } + + /** + * Informs all registered listeners that a new iteration (in the main iteration loop) has been + * performed. + * + * @param e The {@link IterationEvent} object. + */ + public void fireIterationPerformedEvent(final IterationEvent e) { + for (IterationListener l : listeners) { + l.iterationPerformed(e); + } + } + + /** + * Informs all registered listeners that a new iteration (in the main iteration loop) has been + * started. + * + * @param e The {@link IterationEvent} object. + */ + public void fireIterationStartedEvent(final IterationEvent e) { + for (IterationListener l : listeners) { + l.iterationStarted(e); + } + } + + /** + * Informs all registered listeners that the final phase (post-iterations) has been completed. + * + * @param e The {@link IterationEvent} object. + */ + public void fireTerminationEvent(final IterationEvent e) { + for (IterationListener l : listeners) { + l.terminationPerformed(e); + } + } + + /** + * Returns the number of iterations of this solver, 0 if no iterations has been performed yet. + * + * @return the number of iterations. + */ + public int getIterations() { + return iterations.getCount(); + } + + /** + * Returns the maximum number of iterations. + * + * @return the maximum number of iterations. + */ + public int getMaxIterations() { + return iterations.getMaximalCount(); + } + + /** + * Increments the iteration count by one, and throws an exception if the maximum number of + * iterations is reached. This method should be called at the beginning of a new iteration. + * + * @throws MaxCountExceededException if the maximum number of iterations is reached. + */ + public void incrementIterationCount() throws MaxCountExceededException { + iterations.increment(); + } + + /** + * Removes the specified iteration listener from the list of listeners currently attached to + * {@code this} object. Attempting to remove a listener which was <em>not</em> previously + * registered does not cause any error. + * + * @param listener The {@link IterationListener} to be removed. + */ + public void removeIterationListener(final IterationListener listener) { + listeners.remove(listener); + } + + /** Sets the iteration count to 0. This method must be called during the initial phase. */ + public void resetIterationCount() { + iterations = iterations.withStart(0); + } +} diff --git a/src/main/java/org/apache/commons/math3/util/KthSelector.java b/src/main/java/org/apache/commons/math3/util/KthSelector.java new file mode 100644 index 0000000..ed0f1d5 --- /dev/null +++ b/src/main/java/org/apache/commons/math3/util/KthSelector.java @@ -0,0 +1,154 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math3.util; + +import org.apache.commons.math3.exception.NullArgumentException; + +import java.io.Serializable; +import java.util.Arrays; + +/** + * A Simple K<sup>th</sup> selector implementation to pick up the K<sup>th</sup> ordered element + * from a work array containing the input numbers. + * + * @since 3.4 + */ +public class KthSelector implements Serializable { + + /** Serializable UID. */ + private static final long serialVersionUID = 20140713L; + + /** Minimum selection size for insertion sort rather than selection. */ + private static final int MIN_SELECT_SIZE = 15; + + /** A {@link PivotingStrategyInterface} used for pivoting */ + private final PivotingStrategyInterface pivotingStrategy; + + /** Constructor with default {@link MedianOf3PivotingStrategy median of 3} pivoting strategy */ + public KthSelector() { + this.pivotingStrategy = new MedianOf3PivotingStrategy(); + } + + /** + * Constructor with specified pivoting strategy + * + * @param pivotingStrategy pivoting strategy to use + * @throws NullArgumentException when pivotingStrategy is null + * @see MedianOf3PivotingStrategy + * @see RandomPivotingStrategy + * @see CentralPivotingStrategy + */ + public KthSelector(final PivotingStrategyInterface pivotingStrategy) + throws NullArgumentException { + MathUtils.checkNotNull(pivotingStrategy); + this.pivotingStrategy = pivotingStrategy; + } + + /** + * Get the pivotin strategy. + * + * @return pivoting strategy + */ + public PivotingStrategyInterface getPivotingStrategy() { + return pivotingStrategy; + } + + /** + * Select K<sup>th</sup> value in the array. + * + * @param work work array to use to find out the K<sup>th</sup> value + * @param pivotsHeap cached pivots heap that can be used for efficient estimation + * @param k the index whose value in the array is of interest + * @return K<sup>th</sup> value + */ + public double select(final double[] work, final int[] pivotsHeap, final int k) { + int begin = 0; + int end = work.length; + int node = 0; + final boolean usePivotsHeap = pivotsHeap != null; + while (end - begin > MIN_SELECT_SIZE) { + final int pivot; + + if (usePivotsHeap && node < pivotsHeap.length && pivotsHeap[node] >= 0) { + // the pivot has already been found in a previous call + // and the array has already been partitioned around it + pivot = pivotsHeap[node]; + } else { + // select a pivot and partition work array around it + pivot = partition(work, begin, end, pivotingStrategy.pivotIndex(work, begin, end)); + if (usePivotsHeap && node < pivotsHeap.length) { + pivotsHeap[node] = pivot; + } + } + + if (k == pivot) { + // the pivot was exactly the element we wanted + return work[k]; + } else if (k < pivot) { + // the element is in the left partition + end = pivot; + node = FastMath.min(2 * node + 1, usePivotsHeap ? pivotsHeap.length : end); + } else { + // the element is in the right partition + begin = pivot + 1; + node = FastMath.min(2 * node + 2, usePivotsHeap ? pivotsHeap.length : end); + } + } + Arrays.sort(work, begin, end); + return work[k]; + } + + /** + * Partition an array slice around a pivot.Partitioning exchanges array elements such that all + * elements smaller than pivot are before it and all elements larger than pivot are after it. + * + * @param work work array + * @param begin index of the first element of the slice of work array + * @param end index after the last element of the slice of work array + * @param pivot initial index of the pivot + * @return index of the pivot after partition + */ + private int partition(final double[] work, final int begin, final int end, final int pivot) { + + final double value = work[pivot]; + work[pivot] = work[begin]; + + int i = begin + 1; + int j = end - 1; + while (i < j) { + while (i < j && work[j] > value) { + --j; + } + while (i < j && work[i] < value) { + ++i; + } + + if (i < j) { + final double tmp = work[i]; + work[i++] = work[j]; + work[j--] = tmp; + } + } + + if (i >= end || work[i] > value) { + --i; + } + work[begin] = work[i]; + work[i] = value; + return i; + } +} diff --git a/src/main/java/org/apache/commons/math3/util/MathArrays.java b/src/main/java/org/apache/commons/math3/util/MathArrays.java new file mode 100644 index 0000000..968e626 --- /dev/null +++ b/src/main/java/org/apache/commons/math3/util/MathArrays.java @@ -0,0 +1,1912 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.math3.util; + +import org.apache.commons.math3.Field; +import org.apache.commons.math3.distribution.UniformIntegerDistribution; +import org.apache.commons.math3.exception.DimensionMismatchException; +import org.apache.commons.math3.exception.MathArithmeticException; +import org.apache.commons.math3.exception.MathIllegalArgumentException; +import org.apache.commons.math3.exception.MathInternalError; +import org.apache.commons.math3.exception.NoDataException; +import org.apache.commons.math3.exception.NonMonotonicSequenceException; +import org.apache.commons.math3.exception.NotANumberException; +import org.apache.commons.math3.exception.NotPositiveException; +import org.apache.commons.math3.exception.NotStrictlyPositiveException; +import org.apache.commons.math3.exception.NullArgumentException; +import org.apache.commons.math3.exception.NumberIsTooLargeException; +import org.apache.commons.math3.exception.util.LocalizedFormats; +import org.apache.commons.math3.random.RandomGenerator; +import org.apache.commons.math3.random.Well19937c; + +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.TreeSet; + +/** + * Arrays utilities. + * + * @since 3.0 + */ +public class MathArrays { + + /** Private constructor. */ + private MathArrays() {} + + /** + * Real-valued function that operate on an array or a part of it. + * + * @since 3.1 + */ + public interface Function { + /** + * Operates on an entire array. + * + * @param array Array to operate on. + * @return the result of the operation. + */ + double evaluate(double[] array); + + /** + * @param array Array to operate on. + * @param startIndex Index of the first element to take into account. + * @param numElements Number of elements to take into account. + * @return the result of the operation. + */ + double evaluate(double[] array, int startIndex, int numElements); + } + + /** + * Create a copy of an array scaled by a value. + * + * @param arr Array to scale. + * @param val Scalar. + * @return scaled copy of array with each entry multiplied by val. + * @since 3.2 + */ + public static double[] scale(double val, final double[] arr) { + double[] newArr = new double[arr.length]; + for (int i = 0; i < arr.length; i++) { + newArr[i] = arr[i] * val; + } + return newArr; + } + + /** + * Multiply each element of an array by a value. + * + * <p>The array is modified in place (no copy is created). + * + * @param arr Array to scale + * @param val Scalar + * @since 3.2 + */ + public static void scaleInPlace(double val, final double[] arr) { + for (int i = 0; i < arr.length; i++) { + arr[i] *= val; + } + } + + /** + * Creates an array whose contents will be the element-by-element addition of the arguments. + * + * @param a First term of the addition. + * @param b Second term of the addition. + * @return a new array {@code r} where {@code r[i] = a[i] + b[i]}. + * @throws DimensionMismatchException if the array lengths differ. + * @since 3.1 + */ + public static double[] ebeAdd(double[] a, double[] b) throws DimensionMismatchException { + checkEqualLength(a, b); + + final double[] result = a.clone(); + for (int i = 0; i < a.length; i++) { + result[i] += b[i]; + } + return result; + } + + /** + * Creates an array whose contents will be the element-by-element subtraction of the second + * argument from the first. + * + * @param a First term. + * @param b Element to be subtracted. + * @return a new array {@code r} where {@code r[i] = a[i] - b[i]}. + * @throws DimensionMismatchException if the array lengths differ. + * @since 3.1 + */ + public static double[] ebeSubtract(double[] a, double[] b) throws DimensionMismatchException { + checkEqualLength(a, b); + + final double[] result = a.clone(); + for (int i = 0; i < a.length; i++) { + result[i] -= b[i]; + } + return result; + } + + /** + * Creates an array whose contents will be the element-by-element multiplication of the + * arguments. + * + * @param a First factor of the multiplication. + * @param b Second factor of the multiplication. + * @return a new array {@code r} where {@code r[i] = a[i] * b[i]}. + * @throws DimensionMismatchException if the array lengths differ. + * @since 3.1 + */ + public static double[] ebeMultiply(double[] a, double[] b) throws DimensionMismatchException { + checkEqualLength(a, b); + + final double[] result = a.clone(); + for (int i = 0; i < a.length; i++) { + result[i] *= b[i]; + } + return result; + } + + /** + * Creates an array whose contents will be the element-by-element division of the first argument + * by the second. + * + * @param a Numerator of the division. + * @param b Denominator of the division. + * @return a new array {@code r} where {@code r[i] = a[i] / b[i]}. + * @throws DimensionMismatchException if the array lengths differ. + * @since 3.1 + */ + public static double[] ebeDivide(double[] a, double[] b) throws DimensionMismatchException { + checkEqualLength(a, b); + + final double[] result = a.clone(); + for (int i = 0; i < a.length; i++) { + result[i] /= b[i]; + } + return result; + } + + /** + * Calculates the L<sub>1</sub> (sum of abs) distance between two points. + * + * @param p1 the first point + * @param p2 the second point + * @return the L<sub>1</sub> distance between the two points + * @throws DimensionMismatchException if the array lengths differ. + */ + public static double distance1(double[] p1, double[] p2) throws DimensionMismatchException { + checkEqualLength(p1, p2); + double sum = 0; + for (int i = 0; i < p1.length; i++) { + sum += FastMath.abs(p1[i] - p2[i]); + } + return sum; + } + + /** + * Calculates the L<sub>1</sub> (sum of abs) distance between two points. + * + * @param p1 the first point + * @param p2 the second point + * @return the L<sub>1</sub> distance between the two points + * @throws DimensionMismatchException if the array lengths differ. + */ + public static int distance1(int[] p1, int[] p2) throws DimensionMismatchException { + checkEqualLength(p1, p2); + int sum = 0; + for (int i = 0; i < p1.length; i++) { + sum += FastMath.abs(p1[i] - p2[i]); + } + return sum; + } + + /** + * Calculates the L<sub>2</sub> (Euclidean) distance between two points. + * + * @param p1 the first point + * @param p2 the second point + * @return the L<sub>2</sub> distance between the two points + * @throws DimensionMismatchException if the array lengths differ. + */ + public static double distance(double[] p1, double[] p2) throws DimensionMismatchException { + checkEqualLength(p1, p2); + double sum = 0; + for (int i = 0; i < p1.length; i++) { + final double dp = p1[i] - p2[i]; + sum += dp * dp; + } + return FastMath.sqrt(sum); + } + + /** + * Calculates the cosine of the angle between two vectors. + * + * @param v1 Cartesian coordinates of the first vector. + * @param v2 Cartesian coordinates of the second vector. + * @return the cosine of the angle between the vectors. + * @since 3.6 + */ + public static double cosAngle(double[] v1, double[] v2) { + return linearCombination(v1, v2) / (safeNorm(v1) * safeNorm(v2)); + } + + /** + * Calculates the L<sub>2</sub> (Euclidean) distance between two points. + * + * @param p1 the first point + * @param p2 the second point + * @return the L<sub>2</sub> distance between the two points + * @throws DimensionMismatchException if the array lengths differ. + */ + public static double distance(int[] p1, int[] p2) throws DimensionMismatchException { + checkEqualLength(p1, p2); + double sum = 0; + for (int i = 0; i < p1.length; i++) { + final double dp = p1[i] - p2[i]; + sum += dp * dp; + } + return FastMath.sqrt(sum); + } + + /** + * Calculates the L<sub>∞</sub> (max of abs) distance between two points. + * + * @param p1 the first point + * @param p2 the second point + * @return the L<sub>∞</sub> distance between the two points + * @throws DimensionMismatchException if the array lengths differ. + */ + public static double distanceInf(double[] p1, double[] p2) throws DimensionMismatchException { + checkEqualLength(p1, p2); + double max = 0; + for (int i = 0; i < p1.length; i++) { + max = FastMath.max(max, FastMath.abs(p1[i] - p2[i])); + } + return max; + } + + /** + * Calculates the L<sub>∞</sub> (max of abs) distance between two points. + * + * @param p1 the first point + * @param p2 the second point + * @return the L<sub>∞</sub> distance between the two points + * @throws DimensionMismatchException if the array lengths differ. + */ + public static int distanceInf(int[] p1, int[] p2) throws DimensionMismatchException { + checkEqualLength(p1, p2); + int max = 0; + for (int i = 0; i < p1.length; i++) { + max = FastMath.max(max, FastMath.abs(p1[i] - p2[i])); + } + return max; + } + + /** Specification of ordering direction. */ + public enum OrderDirection { + /** Constant for increasing direction. */ + INCREASING, + /** Constant for decreasing direction. */ + DECREASING + } + + /** + * Check that an array is monotonically increasing or decreasing. + * + * @param <T> the type of the elements in the specified array + * @param val Values. + * @param dir Ordering direction. + * @param strict Whether the order should be strict. + * @return {@code true} if sorted, {@code false} otherwise. + */ + public static <T extends Comparable<? super T>> boolean isMonotonic( + T[] val, OrderDirection dir, boolean strict) { + T previous = val[0]; + final int max = val.length; + for (int i = 1; i < max; i++) { + final int comp; + switch (dir) { + case INCREASING: + comp = previous.compareTo(val[i]); + if (strict) { + if (comp >= 0) { + return false; + } + } else { + if (comp > 0) { + return false; + } + } + break; + case DECREASING: + comp = val[i].compareTo(previous); + if (strict) { + if (comp >= 0) { + return false; + } + } else { + if (comp > 0) { + return false; + } + } + break; + default: + // Should never happen. + throw new MathInternalError(); + } + + previous = val[i]; + } + return true; + } + + /** + * Check that an array is monotonically increasing or decreasing. + * + * @param val Values. + * @param dir Ordering direction. + * @param strict Whether the order should be strict. + * @return {@code true} if sorted, {@code false} otherwise. + */ + public static boolean isMonotonic(double[] val, OrderDirection dir, boolean strict) { + return checkOrder(val, dir, strict, false); + } + + /** + * Check that both arrays have the same length. + * + * @param a Array. + * @param b Array. + * @param abort Whether to throw an exception if the check fails. + * @return {@code true} if the arrays have the same length. + * @throws DimensionMismatchException if the lengths differ and {@code abort} is {@code true}. + * @since 3.6 + */ + public static boolean checkEqualLength(double[] a, double[] b, boolean abort) { + if (a.length == b.length) { + return true; + } else { + if (abort) { + throw new DimensionMismatchException(a.length, b.length); + } + return false; + } + } + + /** + * Check that both arrays have the same length. + * + * @param a Array. + * @param b Array. + * @throws DimensionMismatchException if the lengths differ. + * @since 3.6 + */ + public static void checkEqualLength(double[] a, double[] b) { + checkEqualLength(a, b, true); + } + + /** + * Check that both arrays have the same length. + * + * @param a Array. + * @param b Array. + * @param abort Whether to throw an exception if the check fails. + * @return {@code true} if the arrays have the same length. + * @throws DimensionMismatchException if the lengths differ and {@code abort} is {@code true}. + * @since 3.6 + */ + public static boolean checkEqualLength(int[] a, int[] b, boolean abort) { + if (a.length == b.length) { + return true; + } else { + if (abort) { + throw new DimensionMismatchException(a.length, b.length); + } + return false; + } + } + + /** + * Check that both arrays have the same length. + * + * @param a Array. + * @param b Array. + * @throws DimensionMismatchException if the lengths differ. + * @since 3.6 + */ + public static void checkEqualLength(int[] a, int[] b) { + checkEqualLength(a, b, true); + } + + /** + * Check that the given array is sorted. + * + * @param val Values. + * @param dir Ordering direction. + * @param strict Whether the order should be strict. + * @param abort Whether to throw an exception if the check fails. + * @return {@code true} if the array is sorted. + * @throws NonMonotonicSequenceException if the array is not sorted and {@code abort} is {@code + * true}. + */ + public static boolean checkOrder( + double[] val, OrderDirection dir, boolean strict, boolean abort) + throws NonMonotonicSequenceException { + double previous = val[0]; + final int max = val.length; + + int index; + ITEM: + for (index = 1; index < max; index++) { + switch (dir) { + case INCREASING: + if (strict) { + if (val[index] <= previous) { + break ITEM; + } + } else { + if (val[index] < previous) { + break ITEM; + } + } + break; + case DECREASING: + if (strict) { + if (val[index] >= previous) { + break ITEM; + } + } else { + if (val[index] > previous) { + break ITEM; + } + } + break; + default: + // Should never happen. + throw new MathInternalError(); + } + + previous = val[index]; + } + + if (index == max) { + // Loop completed. + return true; + } + + // Loop early exit means wrong ordering. + if (abort) { + throw new NonMonotonicSequenceException(val[index], previous, index, dir, strict); + } else { + return false; + } + } + + /** + * Check that the given array is sorted. + * + * @param val Values. + * @param dir Ordering direction. + * @param strict Whether the order should be strict. + * @throws NonMonotonicSequenceException if the array is not sorted. + * @since 2.2 + */ + public static void checkOrder(double[] val, OrderDirection dir, boolean strict) + throws NonMonotonicSequenceException { + checkOrder(val, dir, strict, true); + } + + /** + * Check that the given array is sorted in strictly increasing order. + * + * @param val Values. + * @throws NonMonotonicSequenceException if the array is not sorted. + * @since 2.2 + */ + public static void checkOrder(double[] val) throws NonMonotonicSequenceException { + checkOrder(val, OrderDirection.INCREASING, true); + } + + /** + * Throws DimensionMismatchException if the input array is not rectangular. + * + * @param in array to be tested + * @throws NullArgumentException if input array is null + * @throws DimensionMismatchException if input array is not rectangular + * @since 3.1 + */ + public static void checkRectangular(final long[][] in) + throws NullArgumentException, DimensionMismatchException { + MathUtils.checkNotNull(in); + for (int i = 1; i < in.length; i++) { + if (in[i].length != in[0].length) { + throw new DimensionMismatchException( + LocalizedFormats.DIFFERENT_ROWS_LENGTHS, in[i].length, in[0].length); + } + } + } + + /** + * Check that all entries of the input array are strictly positive. + * + * @param in Array to be tested + * @throws NotStrictlyPositiveException if any entries of the array are not strictly positive. + * @since 3.1 + */ + public static void checkPositive(final double[] in) throws NotStrictlyPositiveException { + for (int i = 0; i < in.length; i++) { + if (in[i] <= 0) { + throw new NotStrictlyPositiveException(in[i]); + } + } + } + + /** + * Check that no entry of the input array is {@code NaN}. + * + * @param in Array to be tested. + * @throws NotANumberException if an entry is {@code NaN}. + * @since 3.4 + */ + public static void checkNotNaN(final double[] in) throws NotANumberException { + for (int i = 0; i < in.length; i++) { + if (Double.isNaN(in[i])) { + throw new NotANumberException(); + } + } + } + + /** + * Check that all entries of the input array are >= 0. + * + * @param in Array to be tested + * @throws NotPositiveException if any array entries are less than 0. + * @since 3.1 + */ + public static void checkNonNegative(final long[] in) throws NotPositiveException { + for (int i = 0; i < in.length; i++) { + if (in[i] < 0) { + throw new NotPositiveException(in[i]); + } + } + } + + /** + * Check all entries of the input array are >= 0. + * + * @param in Array to be tested + * @throws NotPositiveException if any array entries are less than 0. + * @since 3.1 + */ + public static void checkNonNegative(final long[][] in) throws NotPositiveException { + for (int i = 0; i < in.length; i++) { + for (int j = 0; j < in[i].length; j++) { + if (in[i][j] < 0) { + throw new NotPositiveException(in[i][j]); + } + } + } + } + + /** + * Returns the Cartesian norm (2-norm), handling both overflow and underflow. Translation of the + * minpack enorm subroutine. + * + * <p>The redistribution policy for MINPACK is available <a + * href="http://www.netlib.org/minpack/disclaimer">here</a>, for convenience, it is reproduced + * below. + * + * <table border="0" width="80%" cellpadding="10" align="center" bgcolor="#E0E0E0"> + * <tr><td> + * Minpack Copyright Notice (1999) University of Chicago. + * All rights reserved + * </td></tr> + * <tr><td> + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * <ol> + * <li>Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer.</li> + * <li>Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution.</li> + * <li>The end-user documentation included with the redistribution, if any, + * must include the following acknowledgment: + * {@code This product includes software developed by the University of + * Chicago, as Operator of Argonne National Laboratory.} + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear.</li> + * <li><strong>WARRANTY DISCLAIMER. THE SOFTWARE IS SUPPLIED "AS IS" + * WITHOUT WARRANTY OF ANY KIND. THE COPYRIGHT HOLDER, THE + * UNITED STATES, THE UNITED STATES DEPARTMENT OF ENERGY, AND + * THEIR EMPLOYEES: (1) DISCLAIM ANY WARRANTIES, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO ANY IMPLIED WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE + * OR NON-INFRINGEMENT, (2) DO NOT ASSUME ANY LEGAL LIABILITY + * OR RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR + * USEFULNESS OF THE SOFTWARE, (3) DO NOT REPRESENT THAT USE OF + * THE SOFTWARE WOULD NOT INFRINGE PRIVATELY OWNED RIGHTS, (4) + * DO NOT WARRANT THAT THE SOFTWARE WILL FUNCTION + * UNINTERRUPTED, THAT IT IS ERROR-FREE OR THAT ANY ERRORS WILL + * BE CORRECTED.</strong></li> + * <li><strong>LIMITATION OF LIABILITY. IN NO EVENT WILL THE COPYRIGHT + * HOLDER, THE UNITED STATES, THE UNITED STATES DEPARTMENT OF + * ENERGY, OR THEIR EMPLOYEES: BE LIABLE FOR ANY INDIRECT, + * INCIDENTAL, CONSEQUENTIAL, SPECIAL OR PUNITIVE DAMAGES OF + * ANY KIND OR NATURE, INCLUDING BUT NOT LIMITED TO LOSS OF + * PROFITS OR LOSS OF DATA, FOR ANY REASON WHATSOEVER, WHETHER + * SUCH LIABILITY IS ASSERTED ON THE BASIS OF CONTRACT, TORT + * (INCLUDING NEGLIGENCE OR STRICT LIABILITY), OR OTHERWISE, + * EVEN IF ANY OF SAID PARTIES HAS BEEN WARNED OF THE + * POSSIBILITY OF SUCH LOSS OR DAMAGES.</strong></li> + * <ol></td></tr> + * </table> + * + * @param v Vector of doubles. + * @return the 2-norm of the vector. + * @since 2.2 + */ + public static double safeNorm(double[] v) { + double rdwarf = 3.834e-20; + double rgiant = 1.304e+19; + double s1 = 0; + double s2 = 0; + double s3 = 0; + double x1max = 0; + double x3max = 0; + double floatn = v.length; + double agiant = rgiant / floatn; + for (int i = 0; i < v.length; i++) { + double xabs = FastMath.abs(v[i]); + if (xabs < rdwarf || xabs > agiant) { + if (xabs > rdwarf) { + if (xabs > x1max) { + double r = x1max / xabs; + s1 = 1 + s1 * r * r; + x1max = xabs; + } else { + double r = xabs / x1max; + s1 += r * r; + } + } else { + if (xabs > x3max) { + double r = x3max / xabs; + s3 = 1 + s3 * r * r; + x3max = xabs; + } else { + if (xabs != 0) { + double r = xabs / x3max; + s3 += r * r; + } + } + } + } else { + s2 += xabs * xabs; + } + } + double norm; + if (s1 != 0) { + norm = x1max * Math.sqrt(s1 + (s2 / x1max) / x1max); + } else { + if (s2 == 0) { + norm = x3max * Math.sqrt(s3); + } else { + if (s2 >= x3max) { + norm = Math.sqrt(s2 * (1 + (x3max / s2) * (x3max * s3))); + } else { + norm = Math.sqrt(x3max * ((s2 / x3max) + (x3max * s3))); + } + } + } + return norm; + } + + /** A helper data structure holding a double and an integer value. */ + private static class PairDoubleInteger { + /** Key */ + private final double key; + + /** Value */ + private final int value; + + /** + * @param key Key. + * @param value Value. + */ + PairDoubleInteger(double key, int value) { + this.key = key; + this.value = value; + } + + /** + * @return the key. + */ + public double getKey() { + return key; + } + + /** + * @return the value. + */ + public int getValue() { + return value; + } + } + + /** + * Sort an array in ascending order in place and perform the same reordering of entries on other + * arrays. For example, if {@code x = [3, 1, 2], y = [1, 2, 3]} and {@code z = [0, 5, 7]}, then + * {@code sortInPlace(x, y, z)} will update {@code x} to {@code [1, 2, 3]}, {@code y} to {@code + * [2, 3, 1]} and {@code z} to {@code [5, 7, 0]}. + * + * @param x Array to be sorted and used as a pattern for permutation of the other arrays. + * @param yList Set of arrays whose permutations of entries will follow those performed on + * {@code x}. + * @throws DimensionMismatchException if any {@code y} is not the same size as {@code x}. + * @throws NullArgumentException if {@code x} or any {@code y} is null. + * @since 3.0 + */ + public static void sortInPlace(double[] x, double[]... yList) + throws DimensionMismatchException, NullArgumentException { + sortInPlace(x, OrderDirection.INCREASING, yList); + } + + /** + * Sort an array in place and perform the same reordering of entries on other arrays. This + * method works the same as the other {@link #sortInPlace(double[], double[][]) sortInPlace} + * method, but allows the order of the sort to be provided in the {@code dir} parameter. + * + * @param x Array to be sorted and used as a pattern for permutation of the other arrays. + * @param dir Order direction. + * @param yList Set of arrays whose permutations of entries will follow those performed on + * {@code x}. + * @throws DimensionMismatchException if any {@code y} is not the same size as {@code x}. + * @throws NullArgumentException if {@code x} or any {@code y} is null + * @since 3.0 + */ + public static void sortInPlace(double[] x, final OrderDirection dir, double[]... yList) + throws NullArgumentException, DimensionMismatchException { + + // Consistency checks. + if (x == null) { + throw new NullArgumentException(); + } + + final int yListLen = yList.length; + final int len = x.length; + + for (int j = 0; j < yListLen; j++) { + final double[] y = yList[j]; + if (y == null) { + throw new NullArgumentException(); + } + if (y.length != len) { + throw new DimensionMismatchException(y.length, len); + } + } + + // Associate each abscissa "x[i]" with its index "i". + final List<PairDoubleInteger> list = new ArrayList<PairDoubleInteger>(len); + for (int i = 0; i < len; i++) { + list.add(new PairDoubleInteger(x[i], i)); + } + + // Create comparators for increasing and decreasing orders. + final Comparator<PairDoubleInteger> comp = + dir == MathArrays.OrderDirection.INCREASING + ? new Comparator<PairDoubleInteger>() { + /** {@inheritDoc} */ + public int compare(PairDoubleInteger o1, PairDoubleInteger o2) { + return Double.compare(o1.getKey(), o2.getKey()); + } + } + : new Comparator<PairDoubleInteger>() { + /** {@inheritDoc} */ + public int compare(PairDoubleInteger o1, PairDoubleInteger o2) { + return Double.compare(o2.getKey(), o1.getKey()); + } + }; + + // Sort. + Collections.sort(list, comp); + + // Modify the original array so that its elements are in + // the prescribed order. + // Retrieve indices of original locations. + final int[] indices = new int[len]; + for (int i = 0; i < len; i++) { + final PairDoubleInteger e = list.get(i); + x[i] = e.getKey(); + indices[i] = e.getValue(); + } + + // In each of the associated arrays, move the + // elements to their new location. + for (int j = 0; j < yListLen; j++) { + // Input array will be modified in place. + final double[] yInPlace = yList[j]; + final double[] yOrig = yInPlace.clone(); + + for (int i = 0; i < len; i++) { + yInPlace[i] = yOrig[indices[i]]; + } + } + } + + /** + * Creates a copy of the {@code source} array. + * + * @param source Array to be copied. + * @return the copied array. + */ + public static int[] copyOf(int[] source) { + return copyOf(source, source.length); + } + + /** + * Creates a copy of the {@code source} array. + * + * @param source Array to be copied. + * @return the copied array. + */ + public static double[] copyOf(double[] source) { + return copyOf(source, source.length); + } + + /** + * Creates a copy of the {@code source} array. + * + * @param source Array to be copied. + * @param len Number of entries to copy. If smaller then the source length, the copy will be + * truncated, if larger it will padded with zeroes. + * @return the copied array. + */ + public static int[] copyOf(int[] source, int len) { + final int[] output = new int[len]; + System.arraycopy(source, 0, output, 0, FastMath.min(len, source.length)); + return output; + } + + /** + * Creates a copy of the {@code source} array. + * + * @param source Array to be copied. + * @param len Number of entries to copy. If smaller then the source length, the copy will be + * truncated, if larger it will padded with zeroes. + * @return the copied array. + */ + public static double[] copyOf(double[] source, int len) { + final double[] output = new double[len]; + System.arraycopy(source, 0, output, 0, FastMath.min(len, source.length)); + return output; + } + + /** + * Creates a copy of the {@code source} array. + * + * @param source Array to be copied. + * @param from Initial index of the range to be copied, inclusive. + * @param to Final index of the range to be copied, exclusive. (This index may lie outside the + * array.) + * @return the copied array. + */ + public static double[] copyOfRange(double[] source, int from, int to) { + final int len = to - from; + final double[] output = new double[len]; + System.arraycopy(source, from, output, 0, FastMath.min(len, source.length - from)); + return output; + } + + /** + * Compute a linear combination accurately. This method computes the sum of the products <code> + * a<sub>i</sub> b<sub>i</sub></code> to high accuracy. It does so by using specific + * multiplication and addition algorithms to preserve accuracy and reduce cancellation effects. + * <br> + * It is based on the 2005 paper <a + * href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.2.1547">Accurate Sum and Dot + * Product</a> by Takeshi Ogita, Siegfried M. Rump, and Shin'ichi Oishi published in SIAM J. + * Sci. Comput. + * + * @param a Factors. + * @param b Factors. + * @return <code>Σ<sub>i</sub> a<sub>i</sub> b<sub>i</sub></code>. + * @throws DimensionMismatchException if arrays dimensions don't match + */ + public static double linearCombination(final double[] a, final double[] b) + throws DimensionMismatchException { + checkEqualLength(a, b); + final int len = a.length; + + if (len == 1) { + // Revert to scalar multiplication. + return a[0] * b[0]; + } + + final double[] prodHigh = new double[len]; + double prodLowSum = 0; + + for (int i = 0; i < len; i++) { + final double ai = a[i]; + final double aHigh = + Double.longBitsToDouble(Double.doubleToRawLongBits(ai) & ((-1L) << 27)); + final double aLow = ai - aHigh; + + final double bi = b[i]; + final double bHigh = + Double.longBitsToDouble(Double.doubleToRawLongBits(bi) & ((-1L) << 27)); + final double bLow = bi - bHigh; + prodHigh[i] = ai * bi; + final double prodLow = + aLow * bLow - (((prodHigh[i] - aHigh * bHigh) - aLow * bHigh) - aHigh * bLow); + prodLowSum += prodLow; + } + + final double prodHighCur = prodHigh[0]; + double prodHighNext = prodHigh[1]; + double sHighPrev = prodHighCur + prodHighNext; + double sPrime = sHighPrev - prodHighNext; + double sLowSum = (prodHighNext - (sHighPrev - sPrime)) + (prodHighCur - sPrime); + + final int lenMinusOne = len - 1; + for (int i = 1; i < lenMinusOne; i++) { + prodHighNext = prodHigh[i + 1]; + final double sHighCur = sHighPrev + prodHighNext; + sPrime = sHighCur - prodHighNext; + sLowSum += (prodHighNext - (sHighCur - sPrime)) + (sHighPrev - sPrime); + sHighPrev = sHighCur; + } + + double result = sHighPrev + (prodLowSum + sLowSum); + + if (Double.isNaN(result)) { + // either we have split infinite numbers or some coefficients were NaNs, + // just rely on the naive implementation and let IEEE754 handle this + result = 0; + for (int i = 0; i < len; ++i) { + result += a[i] * b[i]; + } + } + + return result; + } + + /** + * Compute a linear combination accurately. + * + * <p>This method computes a<sub>1</sub>×b<sub>1</sub> + a<sub>2</sub>×b<sub>2</sub> + * to high accuracy. It does so by using specific multiplication and addition algorithms to + * preserve accuracy and reduce cancellation effects. It is based on the 2005 paper <a + * href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.2.1547">Accurate Sum and Dot + * Product</a> by Takeshi Ogita, Siegfried M. Rump, and Shin'ichi Oishi published in SIAM J. + * Sci. Comput. + * + * @param a1 first factor of the first term + * @param b1 second factor of the first term + * @param a2 first factor of the second term + * @param b2 second factor of the second term + * @return a<sub>1</sub>×b<sub>1</sub> + a<sub>2</sub>×b<sub>2</sub> + * @see #linearCombination(double, double, double, double, double, double) + * @see #linearCombination(double, double, double, double, double, double, double, double) + */ + public static double linearCombination( + final double a1, final double b1, final double a2, final double b2) { + + // the code below is split in many additions/subtractions that may + // appear redundant. However, they should NOT be simplified, as they + // use IEEE754 floating point arithmetic rounding properties. + // The variable naming conventions are that xyzHigh contains the most significant + // bits of xyz and xyzLow contains its least significant bits. So theoretically + // xyz is the sum xyzHigh + xyzLow, but in many cases below, this sum cannot + // be represented in only one double precision number so we preserve two numbers + // to hold it as long as we can, combining the high and low order bits together + // only at the end, after cancellation may have occurred on high order bits + + // split a1 and b1 as one 26 bits number and one 27 bits number + final double a1High = + Double.longBitsToDouble(Double.doubleToRawLongBits(a1) & ((-1L) << 27)); + final double a1Low = a1 - a1High; + final double b1High = + Double.longBitsToDouble(Double.doubleToRawLongBits(b1) & ((-1L) << 27)); + final double b1Low = b1 - b1High; + + // accurate multiplication a1 * b1 + final double prod1High = a1 * b1; + final double prod1Low = + a1Low * b1Low - (((prod1High - a1High * b1High) - a1Low * b1High) - a1High * b1Low); + + // split a2 and b2 as one 26 bits number and one 27 bits number + final double a2High = + Double.longBitsToDouble(Double.doubleToRawLongBits(a2) & ((-1L) << 27)); + final double a2Low = a2 - a2High; + final double b2High = + Double.longBitsToDouble(Double.doubleToRawLongBits(b2) & ((-1L) << 27)); + final double b2Low = b2 - b2High; + + // accurate multiplication a2 * b2 + final double prod2High = a2 * b2; + final double prod2Low = + a2Low * b2Low - (((prod2High - a2High * b2High) - a2Low * b2High) - a2High * b2Low); + + // accurate addition a1 * b1 + a2 * b2 + final double s12High = prod1High + prod2High; + final double s12Prime = s12High - prod2High; + final double s12Low = (prod2High - (s12High - s12Prime)) + (prod1High - s12Prime); + + // final rounding, s12 may have suffered many cancellations, we try + // to recover some bits from the extra words we have saved up to now + double result = s12High + (prod1Low + prod2Low + s12Low); + + if (Double.isNaN(result)) { + // either we have split infinite numbers or some coefficients were NaNs, + // just rely on the naive implementation and let IEEE754 handle this + result = a1 * b1 + a2 * b2; + } + + return result; + } + + /** + * Compute a linear combination accurately. + * + * <p>This method computes a<sub>1</sub>×b<sub>1</sub> + a<sub>2</sub>×b<sub>2</sub> + * + a<sub>3</sub>×b<sub>3</sub> to high accuracy. It does so by using specific + * multiplication and addition algorithms to preserve accuracy and reduce cancellation effects. + * It is based on the 2005 paper <a + * href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.2.1547">Accurate Sum and Dot + * Product</a> by Takeshi Ogita, Siegfried M. Rump, and Shin'ichi Oishi published in SIAM J. + * Sci. Comput. + * + * @param a1 first factor of the first term + * @param b1 second factor of the first term + * @param a2 first factor of the second term + * @param b2 second factor of the second term + * @param a3 first factor of the third term + * @param b3 second factor of the third term + * @return a<sub>1</sub>×b<sub>1</sub> + a<sub>2</sub>×b<sub>2</sub> + + * a<sub>3</sub>×b<sub>3</sub> + * @see #linearCombination(double, double, double, double) + * @see #linearCombination(double, double, double, double, double, double, double, double) + */ + public static double linearCombination( + final double a1, + final double b1, + final double a2, + final double b2, + final double a3, + final double b3) { + + // the code below is split in many additions/subtractions that may + // appear redundant. However, they should NOT be simplified, as they + // do use IEEE754 floating point arithmetic rounding properties. + // The variables naming conventions are that xyzHigh contains the most significant + // bits of xyz and xyzLow contains its least significant bits. So theoretically + // xyz is the sum xyzHigh + xyzLow, but in many cases below, this sum cannot + // be represented in only one double precision number so we preserve two numbers + // to hold it as long as we can, combining the high and low order bits together + // only at the end, after cancellation may have occurred on high order bits + + // split a1 and b1 as one 26 bits number and one 27 bits number + final double a1High = + Double.longBitsToDouble(Double.doubleToRawLongBits(a1) & ((-1L) << 27)); + final double a1Low = a1 - a1High; + final double b1High = + Double.longBitsToDouble(Double.doubleToRawLongBits(b1) & ((-1L) << 27)); + final double b1Low = b1 - b1High; + + // accurate multiplication a1 * b1 + final double prod1High = a1 * b1; + final double prod1Low = + a1Low * b1Low - (((prod1High - a1High * b1High) - a1Low * b1High) - a1High * b1Low); + + // split a2 and b2 as one 26 bits number and one 27 bits number + final double a2High = + Double.longBitsToDouble(Double.doubleToRawLongBits(a2) & ((-1L) << 27)); + final double a2Low = a2 - a2High; + final double b2High = + Double.longBitsToDouble(Double.doubleToRawLongBits(b2) & ((-1L) << 27)); + final double b2Low = b2 - b2High; + + // accurate multiplication a2 * b2 + final double prod2High = a2 * b2; + final double prod2Low = + a2Low * b2Low - (((prod2High - a2High * b2High) - a2Low * b2High) - a2High * b2Low); + + // split a3 and b3 as one 26 bits number and one 27 bits number + final double a3High = + Double.longBitsToDouble(Double.doubleToRawLongBits(a3) & ((-1L) << 27)); + final double a3Low = a3 - a3High; + final double b3High = + Double.longBitsToDouble(Double.doubleToRawLongBits(b3) & ((-1L) << 27)); + final double b3Low = b3 - b3High; + + // accurate multiplication a3 * b3 + final double prod3High = a3 * b3; + final double prod3Low = + a3Low * b3Low - (((prod3High - a3High * b3High) - a3Low * b3High) - a3High * b3Low); + + // accurate addition a1 * b1 + a2 * b2 + final double s12High = prod1High + prod2High; + final double s12Prime = s12High - prod2High; + final double s12Low = (prod2High - (s12High - s12Prime)) + (prod1High - s12Prime); + + // accurate addition a1 * b1 + a2 * b2 + a3 * b3 + final double s123High = s12High + prod3High; + final double s123Prime = s123High - prod3High; + final double s123Low = (prod3High - (s123High - s123Prime)) + (s12High - s123Prime); + + // final rounding, s123 may have suffered many cancellations, we try + // to recover some bits from the extra words we have saved up to now + double result = s123High + (prod1Low + prod2Low + prod3Low + s12Low + s123Low); + + if (Double.isNaN(result)) { + // either we have split infinite numbers or some coefficients were NaNs, + // just rely on the naive implementation and let IEEE754 handle this + result = a1 * b1 + a2 * b2 + a3 * b3; + } + + return result; + } + + /** + * Compute a linear combination accurately. + * + * <p>This method computes a<sub>1</sub>×b<sub>1</sub> + a<sub>2</sub>×b<sub>2</sub> + * + a<sub>3</sub>×b<sub>3</sub> + a<sub>4</sub>×b<sub>4</sub> to high accuracy. It + * does so by using specific multiplication and addition algorithms to preserve accuracy and + * reduce cancellation effects. It is based on the 2005 paper <a + * href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.2.1547">Accurate Sum and Dot + * Product</a> by Takeshi Ogita, Siegfried M. Rump, and Shin'ichi Oishi published in SIAM J. + * Sci. Comput. + * + * @param a1 first factor of the first term + * @param b1 second factor of the first term + * @param a2 first factor of the second term + * @param b2 second factor of the second term + * @param a3 first factor of the third term + * @param b3 second factor of the third term + * @param a4 first factor of the third term + * @param b4 second factor of the third term + * @return a<sub>1</sub>×b<sub>1</sub> + a<sub>2</sub>×b<sub>2</sub> + + * a<sub>3</sub>×b<sub>3</sub> + a<sub>4</sub>×b<sub>4</sub> + * @see #linearCombination(double, double, double, double) + * @see #linearCombination(double, double, double, double, double, double) + */ + public static double linearCombination( + final double a1, + final double b1, + final double a2, + final double b2, + final double a3, + final double b3, + final double a4, + final double b4) { + + // the code below is split in many additions/subtractions that may + // appear redundant. However, they should NOT be simplified, as they + // do use IEEE754 floating point arithmetic rounding properties. + // The variables naming conventions are that xyzHigh contains the most significant + // bits of xyz and xyzLow contains its least significant bits. So theoretically + // xyz is the sum xyzHigh + xyzLow, but in many cases below, this sum cannot + // be represented in only one double precision number so we preserve two numbers + // to hold it as long as we can, combining the high and low order bits together + // only at the end, after cancellation may have occurred on high order bits + + // split a1 and b1 as one 26 bits number and one 27 bits number + final double a1High = + Double.longBitsToDouble(Double.doubleToRawLongBits(a1) & ((-1L) << 27)); + final double a1Low = a1 - a1High; + final double b1High = + Double.longBitsToDouble(Double.doubleToRawLongBits(b1) & ((-1L) << 27)); + final double b1Low = b1 - b1High; + + // accurate multiplication a1 * b1 + final double prod1High = a1 * b1; + final double prod1Low = + a1Low * b1Low - (((prod1High - a1High * b1High) - a1Low * b1High) - a1High * b1Low); + + // split a2 and b2 as one 26 bits number and one 27 bits number + final double a2High = + Double.longBitsToDouble(Double.doubleToRawLongBits(a2) & ((-1L) << 27)); + final double a2Low = a2 - a2High; + final double b2High = + Double.longBitsToDouble(Double.doubleToRawLongBits(b2) & ((-1L) << 27)); + final double b2Low = b2 - b2High; + + // accurate multiplication a2 * b2 + final double prod2High = a2 * b2; + final double prod2Low = + a2Low * b2Low - (((prod2High - a2High * b2High) - a2Low * b2High) - a2High * b2Low); + + // split a3 and b3 as one 26 bits number and one 27 bits number + final double a3High = + Double.longBitsToDouble(Double.doubleToRawLongBits(a3) & ((-1L) << 27)); + final double a3Low = a3 - a3High; + final double b3High = + Double.longBitsToDouble(Double.doubleToRawLongBits(b3) & ((-1L) << 27)); + final double b3Low = b3 - b3High; + + // accurate multiplication a3 * b3 + final double prod3High = a3 * b3; + final double prod3Low = + a3Low * b3Low - (((prod3High - a3High * b3High) - a3Low * b3High) - a3High * b3Low); + + // split a4 and b4 as one 26 bits number and one 27 bits number + final double a4High = + Double.longBitsToDouble(Double.doubleToRawLongBits(a4) & ((-1L) << 27)); + final double a4Low = a4 - a4High; + final double b4High = + Double.longBitsToDouble(Double.doubleToRawLongBits(b4) & ((-1L) << 27)); + final double b4Low = b4 - b4High; + + // accurate multiplication a4 * b4 + final double prod4High = a4 * b4; + final double prod4Low = + a4Low * b4Low - (((prod4High - a4High * b4High) - a4Low * b4High) - a4High * b4Low); + + // accurate addition a1 * b1 + a2 * b2 + final double s12High = prod1High + prod2High; + final double s12Prime = s12High - prod2High; + final double s12Low = (prod2High - (s12High - s12Prime)) + (prod1High - s12Prime); + + // accurate addition a1 * b1 + a2 * b2 + a3 * b3 + final double s123High = s12High + prod3High; + final double s123Prime = s123High - prod3High; + final double s123Low = (prod3High - (s123High - s123Prime)) + (s12High - s123Prime); + + // accurate addition a1 * b1 + a2 * b2 + a3 * b3 + a4 * b4 + final double s1234High = s123High + prod4High; + final double s1234Prime = s1234High - prod4High; + final double s1234Low = (prod4High - (s1234High - s1234Prime)) + (s123High - s1234Prime); + + // final rounding, s1234 may have suffered many cancellations, we try + // to recover some bits from the extra words we have saved up to now + double result = + s1234High + + (prod1Low + prod2Low + prod3Low + prod4Low + s12Low + s123Low + s1234Low); + + if (Double.isNaN(result)) { + // either we have split infinite numbers or some coefficients were NaNs, + // just rely on the naive implementation and let IEEE754 handle this + result = a1 * b1 + a2 * b2 + a3 * b3 + a4 * b4; + } + + return result; + } + + /** + * Returns true iff both arguments are null or have same dimensions and all their elements are + * equal as defined by {@link Precision#equals(float,float)}. + * + * @param x first array + * @param y second array + * @return true if the values are both null or have same dimension and equal elements. + */ + public static boolean equals(float[] x, float[] y) { + if ((x == null) || (y == null)) { + return !((x == null) ^ (y == null)); + } + if (x.length != y.length) { + return false; + } + for (int i = 0; i < x.length; ++i) { + if (!Precision.equals(x[i], y[i])) { + return false; + } + } + return true; + } + + /** + * Returns true iff both arguments are null or have same dimensions and all their elements are + * equal as defined by {@link Precision#equalsIncludingNaN(double,double) this method}. + * + * @param x first array + * @param y second array + * @return true if the values are both null or have same dimension and equal elements + * @since 2.2 + */ + public static boolean equalsIncludingNaN(float[] x, float[] y) { + if ((x == null) || (y == null)) { + return !((x == null) ^ (y == null)); + } + if (x.length != y.length) { + return false; + } + for (int i = 0; i < x.length; ++i) { + if (!Precision.equalsIncludingNaN(x[i], y[i])) { + return false; + } + } + return true; + } + + /** + * Returns {@code true} iff both arguments are {@code null} or have same dimensions and all + * their elements are equal as defined by {@link Precision#equals(double,double)}. + * + * @param x First array. + * @param y Second array. + * @return {@code true} if the values are both {@code null} or have same dimension and equal + * elements. + */ + public static boolean equals(double[] x, double[] y) { + if ((x == null) || (y == null)) { + return !((x == null) ^ (y == null)); + } + if (x.length != y.length) { + return false; + } + for (int i = 0; i < x.length; ++i) { + if (!Precision.equals(x[i], y[i])) { + return false; + } + } + return true; + } + + /** + * Returns {@code true} iff both arguments are {@code null} or have same dimensions and all + * their elements are equal as defined by {@link Precision#equalsIncludingNaN(double,double) + * this method}. + * + * @param x First array. + * @param y Second array. + * @return {@code true} if the values are both {@code null} or have same dimension and equal + * elements. + * @since 2.2 + */ + public static boolean equalsIncludingNaN(double[] x, double[] y) { + if ((x == null) || (y == null)) { + return !((x == null) ^ (y == null)); + } + if (x.length != y.length) { + return false; + } + for (int i = 0; i < x.length; ++i) { + if (!Precision.equalsIncludingNaN(x[i], y[i])) { + return false; + } + } + return true; + } + + /** + * Normalizes an array to make it sum to a specified value. Returns the result of the + * transformation + * + * <pre> + * x |-> x * normalizedSum / sum + * </pre> + * + * applied to each non-NaN element x of the input array, where sum is the sum of the non-NaN + * entries in the input array. + * + * <p>Throws IllegalArgumentException if {@code normalizedSum} is infinite or NaN and + * ArithmeticException if the input array contains any infinite elements or sums to 0. + * + * <p>Ignores (i.e., copies unchanged to the output array) NaNs in the input array. + * + * @param values Input array to be normalized + * @param normalizedSum Target sum for the normalized array + * @return the normalized array. + * @throws MathArithmeticException if the input array contains infinite elements or sums to + * zero. + * @throws MathIllegalArgumentException if the target sum is infinite or {@code NaN}. + * @since 2.1 + */ + public static double[] normalizeArray(double[] values, double normalizedSum) + throws MathIllegalArgumentException, MathArithmeticException { + if (Double.isInfinite(normalizedSum)) { + throw new MathIllegalArgumentException(LocalizedFormats.NORMALIZE_INFINITE); + } + if (Double.isNaN(normalizedSum)) { + throw new MathIllegalArgumentException(LocalizedFormats.NORMALIZE_NAN); + } + double sum = 0d; + final int len = values.length; + double[] out = new double[len]; + for (int i = 0; i < len; i++) { + if (Double.isInfinite(values[i])) { + throw new MathIllegalArgumentException( + LocalizedFormats.INFINITE_ARRAY_ELEMENT, values[i], i); + } + if (!Double.isNaN(values[i])) { + sum += values[i]; + } + } + if (sum == 0) { + throw new MathArithmeticException(LocalizedFormats.ARRAY_SUMS_TO_ZERO); + } + for (int i = 0; i < len; i++) { + if (Double.isNaN(values[i])) { + out[i] = Double.NaN; + } else { + out[i] = values[i] * normalizedSum / sum; + } + } + return out; + } + + /** + * Build an array of elements. + * + * <p>Arrays are filled with field.getZero() + * + * @param <T> the type of the field elements + * @param field field to which array elements belong + * @param length of the array + * @return a new array + * @since 3.2 + */ + public static <T> T[] buildArray(final Field<T> field, final int length) { + @SuppressWarnings("unchecked") // OK because field must be correct class + T[] array = (T[]) Array.newInstance(field.getRuntimeClass(), length); + Arrays.fill(array, field.getZero()); + return array; + } + + /** + * Build a double dimension array of elements. + * + * <p>Arrays are filled with field.getZero() + * + * @param <T> the type of the field elements + * @param field field to which array elements belong + * @param rows number of rows in the array + * @param columns number of columns (may be negative to build partial arrays in the same way + * <code>new Field[rows][]</code> works) + * @return a new array + * @since 3.2 + */ + @SuppressWarnings("unchecked") + public static <T> T[][] buildArray(final Field<T> field, final int rows, final int columns) { + final T[][] array; + if (columns < 0) { + T[] dummyRow = buildArray(field, 0); + array = (T[][]) Array.newInstance(dummyRow.getClass(), rows); + } else { + array = (T[][]) Array.newInstance(field.getRuntimeClass(), new int[] {rows, columns}); + for (int i = 0; i < rows; ++i) { + Arrays.fill(array[i], field.getZero()); + } + } + return array; + } + + /** + * Calculates the <a href="http://en.wikipedia.org/wiki/Convolution">convolution</a> between two + * sequences. + * + * <p>The solution is obtained via straightforward computation of the convolution sum (and not + * via FFT). Whenever the computation needs an element that would be located at an index outside + * the input arrays, the value is assumed to be zero. + * + * @param x First sequence. Typically, this sequence will represent an input signal to a system. + * @param h Second sequence. Typically, this sequence will represent the impulse response of the + * system. + * @return the convolution of {@code x} and {@code h}. This array's length will be {@code + * x.length + h.length - 1}. + * @throws NullArgumentException if either {@code x} or {@code h} is {@code null}. + * @throws NoDataException if either {@code x} or {@code h} is empty. + * @since 3.3 + */ + public static double[] convolve(double[] x, double[] h) + throws NullArgumentException, NoDataException { + MathUtils.checkNotNull(x); + MathUtils.checkNotNull(h); + + final int xLen = x.length; + final int hLen = h.length; + + if (xLen == 0 || hLen == 0) { + throw new NoDataException(); + } + + // initialize the output array + final int totalLength = xLen + hLen - 1; + final double[] y = new double[totalLength]; + + // straightforward implementation of the convolution sum + for (int n = 0; n < totalLength; n++) { + double yn = 0; + int k = FastMath.max(0, n + 1 - xLen); + int j = n - k; + while (k < hLen && j >= 0) { + yn += x[j--] * h[k++]; + } + y[n] = yn; + } + + return y; + } + + /** Specification for indicating that some operation applies before or after a given index. */ + public enum Position { + /** Designates the beginning of the array (near index 0). */ + HEAD, + /** Designates the end of the array. */ + TAIL + } + + /** + * Shuffle the entries of the given array. The {@code start} and {@code pos} parameters select + * which portion of the array is randomized and which is left untouched. + * + * @see #shuffle(int[],int,Position,RandomGenerator) + * @param list Array whose entries will be shuffled (in-place). + * @param start Index at which shuffling begins. + * @param pos Shuffling is performed for index positions between {@code start} and either the + * end (if {@link Position#TAIL}) or the beginning (if {@link Position#HEAD}) of the array. + */ + public static void shuffle(int[] list, int start, Position pos) { + shuffle(list, start, pos, new Well19937c()); + } + + /** + * Shuffle the entries of the given array, using the <a + * href="http://en.wikipedia.org/wiki/Fisher–Yates_shuffle#The_modern_algorithm"> + * Fisher–Yates</a> algorithm. The {@code start} and {@code pos} parameters select which portion + * of the array is randomized and which is left untouched. + * + * @param list Array whose entries will be shuffled (in-place). + * @param start Index at which shuffling begins. + * @param pos Shuffling is performed for index positions between {@code start} and either the + * end (if {@link Position#TAIL}) or the beginning (if {@link Position#HEAD}) of the array. + * @param rng Random number generator. + */ + public static void shuffle(int[] list, int start, Position pos, RandomGenerator rng) { + switch (pos) { + case TAIL: + { + for (int i = list.length - 1; i >= start; i--) { + final int target; + if (i == start) { + target = start; + } else { + // NumberIsTooLargeException cannot occur. + target = new UniformIntegerDistribution(rng, start, i).sample(); + } + final int temp = list[target]; + list[target] = list[i]; + list[i] = temp; + } + } + break; + case HEAD: + { + for (int i = 0; i <= start; i++) { + final int target; + if (i == start) { + target = start; + } else { + // NumberIsTooLargeException cannot occur. + target = new UniformIntegerDistribution(rng, i, start).sample(); + } + final int temp = list[target]; + list[target] = list[i]; + list[i] = temp; + } + } + break; + default: + throw new MathInternalError(); // Should never happen. + } + } + + /** + * Shuffle the entries of the given array. + * + * @see #shuffle(int[],int,Position,RandomGenerator) + * @param list Array whose entries will be shuffled (in-place). + * @param rng Random number generator. + */ + public static void shuffle(int[] list, RandomGenerator rng) { + shuffle(list, 0, Position.TAIL, rng); + } + + /** + * Shuffle the entries of the given array. + * + * @see #shuffle(int[],int,Position,RandomGenerator) + * @param list Array whose entries will be shuffled (in-place). + */ + public static void shuffle(int[] list) { + shuffle(list, new Well19937c()); + } + + /** + * Returns an array representing the natural number {@code n}. + * + * @param n Natural number. + * @return an array whose entries are the numbers 0, 1, ..., {@code n}-1. If {@code n == 0}, the + * returned array is empty. + */ + public static int[] natural(int n) { + return sequence(n, 0, 1); + } + + /** + * Returns an array of {@code size} integers starting at {@code start}, skipping {@code stride} + * numbers. + * + * @param size Natural number. + * @param start Natural number. + * @param stride Natural number. + * @return an array whose entries are the numbers {@code start, start + stride, ..., start + + * (size - 1) * stride}. If {@code size == 0}, the returned array is empty. + * @since 3.4 + */ + public static int[] sequence(int size, int start, int stride) { + final int[] a = new int[size]; + for (int i = 0; i < size; i++) { + a[i] = start + i * stride; + } + return a; + } + + /** + * This method is used + * to verify that the input parameters designate a subarray of positive length. + * <p> + * <ul> + * <li>returns <code>true</code> iff the parameters designate a subarray of + * positive length</li> + * <li>throws <code>MathIllegalArgumentException</code> if the array is null or + * or the indices are invalid</li> + * <li>returns <code>false</li> if the array is non-null, but + * <code>length</code> is 0. + * </ul></p> + * + * @param values the input array + * @param begin index of the first array element to include + * @param length the number of elements to include + * @return true if the parameters are valid and designate a subarray of positive length + * @throws MathIllegalArgumentException if the indices are invalid or the array is null + * @since 3.3 + */ + public static boolean verifyValues(final double[] values, final int begin, final int length) + throws MathIllegalArgumentException { + return verifyValues(values, begin, length, false); + } + + /** + * This method is used + * to verify that the input parameters designate a subarray of positive length. + * <p> + * <ul> + * <li>returns <code>true</code> iff the parameters designate a subarray of + * non-negative length</li> + * <li>throws <code>IllegalArgumentException</code> if the array is null or + * or the indices are invalid</li> + * <li>returns <code>false</li> if the array is non-null, but + * <code>length</code> is 0 unless <code>allowEmpty</code> is <code>true</code> + * </ul></p> + * + * @param values the input array + * @param begin index of the first array element to include + * @param length the number of elements to include + * @param allowEmpty if <code>true</code> then zero length arrays are allowed + * @return true if the parameters are valid + * @throws MathIllegalArgumentException if the indices are invalid or the array is null + * @since 3.3 + */ + public static boolean verifyValues( + final double[] values, final int begin, final int length, final boolean allowEmpty) + throws MathIllegalArgumentException { + + if (values == null) { + throw new NullArgumentException(LocalizedFormats.INPUT_ARRAY); + } + + if (begin < 0) { + throw new NotPositiveException(LocalizedFormats.START_POSITION, Integer.valueOf(begin)); + } + + if (length < 0) { + throw new NotPositiveException(LocalizedFormats.LENGTH, Integer.valueOf(length)); + } + + if (begin + length > values.length) { + throw new NumberIsTooLargeException( + LocalizedFormats.SUBARRAY_ENDS_AFTER_ARRAY_END, + Integer.valueOf(begin + length), + Integer.valueOf(values.length), + true); + } + + if (length == 0 && !allowEmpty) { + return false; + } + + return true; + } + + /** + * This method is used + * to verify that the begin and length parameters designate a subarray of positive length + * and the weights are all non-negative, non-NaN, finite, and not all zero. + * <p> + * <ul> + * <li>returns <code>true</code> iff the parameters designate a subarray of + * positive length and the weights array contains legitimate values.</li> + * <li>throws <code>IllegalArgumentException</code> if any of the following are true: + * <ul><li>the values array is null</li> + * <li>the weights array is null</li> + * <li>the weights array does not have the same length as the values array</li> + * <li>the weights array contains one or more infinite values</li> + * <li>the weights array contains one or more NaN values</li> + * <li>the weights array contains negative values</li> + * <li>the start and length arguments do not determine a valid array</li></ul> + * </li> + * <li>returns <code>false</li> if the array is non-null, but + * <code>length</code> is 0. + * </ul></p> + * + * @param values the input array + * @param weights the weights array + * @param begin index of the first array element to include + * @param length the number of elements to include + * @return true if the parameters are valid and designate a subarray of positive length + * @throws MathIllegalArgumentException if the indices are invalid or the array is null + * @since 3.3 + */ + public static boolean verifyValues( + final double[] values, final double[] weights, final int begin, final int length) + throws MathIllegalArgumentException { + return verifyValues(values, weights, begin, length, false); + } + + /** + * This method is used + * to verify that the begin and length parameters designate a subarray of positive length + * and the weights are all non-negative, non-NaN, finite, and not all zero. + * <p> + * <ul> + * <li>returns <code>true</code> iff the parameters designate a subarray of + * non-negative length and the weights array contains legitimate values.</li> + * <li>throws <code>MathIllegalArgumentException</code> if any of the following are true: + * <ul><li>the values array is null</li> + * <li>the weights array is null</li> + * <li>the weights array does not have the same length as the values array</li> + * <li>the weights array contains one or more infinite values</li> + * <li>the weights array contains one or more NaN values</li> + * <li>the weights array contains negative values</li> + * <li>the start and length arguments do not determine a valid array</li></ul> + * </li> + * <li>returns <code>false</li> if the array is non-null, but + * <code>length</code> is 0 unless <code>allowEmpty</code> is <code>true</code>. + * </ul></p> + * + * @param values the input array. + * @param weights the weights array. + * @param begin index of the first array element to include. + * @param length the number of elements to include. + * @param allowEmpty if {@code true} than allow zero length arrays to pass. + * @return {@code true} if the parameters are valid. + * @throws NullArgumentException if either of the arrays are null + * @throws MathIllegalArgumentException if the array indices are not valid, + * the weights array contains NaN, infinite or negative elements, or there + * are no positive weights. + * @since 3.3 + */ + public static boolean verifyValues( + final double[] values, + final double[] weights, + final int begin, + final int length, + final boolean allowEmpty) + throws MathIllegalArgumentException { + + if (weights == null || values == null) { + throw new NullArgumentException(LocalizedFormats.INPUT_ARRAY); + } + + checkEqualLength(weights, values); + + boolean containsPositiveWeight = false; + for (int i = begin; i < begin + length; i++) { + final double weight = weights[i]; + if (Double.isNaN(weight)) { + throw new MathIllegalArgumentException( + LocalizedFormats.NAN_ELEMENT_AT_INDEX, Integer.valueOf(i)); + } + if (Double.isInfinite(weight)) { + throw new MathIllegalArgumentException( + LocalizedFormats.INFINITE_ARRAY_ELEMENT, + Double.valueOf(weight), + Integer.valueOf(i)); + } + if (weight < 0) { + throw new MathIllegalArgumentException( + LocalizedFormats.NEGATIVE_ELEMENT_AT_INDEX, + Integer.valueOf(i), + Double.valueOf(weight)); + } + if (!containsPositiveWeight && weight > 0.0) { + containsPositiveWeight = true; + } + } + + if (!containsPositiveWeight) { + throw new MathIllegalArgumentException(LocalizedFormats.WEIGHT_AT_LEAST_ONE_NON_ZERO); + } + + return verifyValues(values, begin, length, allowEmpty); + } + + /** + * Concatenates a sequence of arrays. The return array consists of the entries of the input + * arrays concatenated in the order they appear in the argument list. Null arrays cause + * NullPointerExceptions; zero length arrays are allowed (contributing nothing to the output + * array). + * + * @param x list of double[] arrays to concatenate + * @return a new array consisting of the entries of the argument arrays + * @throws NullPointerException if any of the arrays are null + * @since 3.6 + */ + public static double[] concatenate(double[]... x) { + int combinedLength = 0; + for (double[] a : x) { + combinedLength += a.length; + } + int offset = 0; + int curLength = 0; + final double[] combined = new double[combinedLength]; + for (int i = 0; i < x.length; i++) { + curLength = x[i].length; + System.arraycopy(x[i], 0, combined, offset, curLength); + offset += curLength; + } + return combined; + } + + /** + * Returns an array consisting of the unique values in {@code data}. The return array is sorted + * in descending order. Empty arrays are allowed, but null arrays result in + * NullPointerException. Infinities are allowed. NaN values are allowed with maximum sort order + * - i.e., if there are NaN values in {@code data}, {@code Double.NaN} will be the first element + * of the output array, even if the array also contains {@code Double.POSITIVE_INFINITY}. + * + * @param data array to scan + * @return descending list of values included in the input array + * @throws NullPointerException if data is null + * @since 3.6 + */ + public static double[] unique(double[] data) { + TreeSet<Double> values = new TreeSet<Double>(); + for (int i = 0; i < data.length; i++) { + values.add(data[i]); + } + final int count = values.size(); + final double[] out = new double[count]; + Iterator<Double> iterator = values.iterator(); + int i = 0; + while (iterator.hasNext()) { + out[count - ++i] = iterator.next(); + } + return out; + } +} diff --git a/src/main/java/org/apache/commons/math3/util/MathUtils.java b/src/main/java/org/apache/commons/math3/util/MathUtils.java new file mode 100644 index 0000000..2f376d7 --- /dev/null +++ b/src/main/java/org/apache/commons/math3/util/MathUtils.java @@ -0,0 +1,289 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.math3.util; + +import org.apache.commons.math3.RealFieldElement; +import org.apache.commons.math3.exception.MathArithmeticException; +import org.apache.commons.math3.exception.NotFiniteNumberException; +import org.apache.commons.math3.exception.NullArgumentException; +import org.apache.commons.math3.exception.util.Localizable; +import org.apache.commons.math3.exception.util.LocalizedFormats; + +import java.util.Arrays; + +/** + * Miscellaneous utility functions. + * + * @see ArithmeticUtils + * @see Precision + * @see MathArrays + */ +public final class MathUtils { + /** + * \(2\pi\) + * + * @since 2.1 + */ + public static final double TWO_PI = 2 * FastMath.PI; + + /** + * \(\pi^2\) + * + * @since 3.4 + */ + public static final double PI_SQUARED = FastMath.PI * FastMath.PI; + + /** Class contains only static methods. */ + private MathUtils() {} + + /** + * Returns an integer hash code representing the given double value. + * + * @param value the value to be hashed + * @return the hash code + */ + public static int hash(double value) { + return new Double(value).hashCode(); + } + + /** + * Returns {@code true} if the values are equal according to semantics of {@link + * Double#equals(Object)}. + * + * @param x Value + * @param y Value + * @return {@code new Double(x).equals(new Double(y))} + */ + public static boolean equals(double x, double y) { + return new Double(x).equals(new Double(y)); + } + + /** + * Returns an integer hash code representing the given double array. + * + * @param value the value to be hashed (may be null) + * @return the hash code + * @since 1.2 + */ + public static int hash(double[] value) { + return Arrays.hashCode(value); + } + + /** + * Normalize an angle in a 2π wide interval around a center value. + * + * <p>This method has three main uses: + * + * <ul> + * <li>normalize an angle between 0 and 2π:<br> + * {@code a = MathUtils.normalizeAngle(a, FastMath.PI);} + * <li>normalize an angle between -π and +π<br> + * {@code a = MathUtils.normalizeAngle(a, 0.0);} + * <li>compute the angle between two defining angular positions:<br> + * {@code angle = MathUtils.normalizeAngle(end, start) - start;} + * </ul> + * + * <p>Note that due to numerical accuracy and since π cannot be represented exactly, the + * result interval is <em>closed</em>, it cannot be half-closed as would be more satisfactory in + * a purely mathematical view. + * + * @param a angle to normalize + * @param center center of the desired 2π interval for the result + * @return a-2kπ with integer k and center-π <= a-2kπ <= center+π + * @since 1.2 + */ + public static double normalizeAngle(double a, double center) { + return a - TWO_PI * FastMath.floor((a + FastMath.PI - center) / TWO_PI); + } + + /** + * Find the maximum of two field elements. + * + * @param <T> the type of the field elements + * @param e1 first element + * @param e2 second element + * @return max(a1, e2) + * @since 3.6 + */ + public static <T extends RealFieldElement<T>> T max(final T e1, final T e2) { + return e1.subtract(e2).getReal() >= 0 ? e1 : e2; + } + + /** + * Find the minimum of two field elements. + * + * @param <T> the type of the field elements + * @param e1 first element + * @param e2 second element + * @return min(a1, e2) + * @since 3.6 + */ + public static <T extends RealFieldElement<T>> T min(final T e1, final T e2) { + return e1.subtract(e2).getReal() >= 0 ? e2 : e1; + } + + /** + * Reduce {@code |a - offset|} to the primary interval {@code [0, |period|)}. + * + * <p>Specifically, the value returned is <br> + * {@code a - |period| * floor((a - offset) / |period|) - offset}. + * + * <p>If any of the parameters are {@code NaN} or infinite, the result is {@code NaN}. + * + * @param a Value to reduce. + * @param period Period. + * @param offset Value that will be mapped to {@code 0}. + * @return the value, within the interval {@code [0 |period|)}, that corresponds to {@code a}. + */ + public static double reduce(double a, double period, double offset) { + final double p = FastMath.abs(period); + return a - p * FastMath.floor((a - offset) / p) - offset; + } + + /** + * Returns the first argument with the sign of the second argument. + * + * @param magnitude Magnitude of the returned value. + * @param sign Sign of the returned value. + * @return a value with magnitude equal to {@code magnitude} and with the same sign as the + * {@code sign} argument. + * @throws MathArithmeticException if {@code magnitude == Byte.MIN_VALUE} and {@code sign >= 0}. + */ + public static byte copySign(byte magnitude, byte sign) throws MathArithmeticException { + if ((magnitude >= 0 && sign >= 0) || (magnitude < 0 && sign < 0)) { // Sign is OK. + return magnitude; + } else if (sign >= 0 && magnitude == Byte.MIN_VALUE) { + throw new MathArithmeticException(LocalizedFormats.OVERFLOW); + } else { + return (byte) -magnitude; // Flip sign. + } + } + + /** + * Returns the first argument with the sign of the second argument. + * + * @param magnitude Magnitude of the returned value. + * @param sign Sign of the returned value. + * @return a value with magnitude equal to {@code magnitude} and with the same sign as the + * {@code sign} argument. + * @throws MathArithmeticException if {@code magnitude == Short.MIN_VALUE} and {@code sign >= + * 0}. + */ + public static short copySign(short magnitude, short sign) throws MathArithmeticException { + if ((magnitude >= 0 && sign >= 0) || (magnitude < 0 && sign < 0)) { // Sign is OK. + return magnitude; + } else if (sign >= 0 && magnitude == Short.MIN_VALUE) { + throw new MathArithmeticException(LocalizedFormats.OVERFLOW); + } else { + return (short) -magnitude; // Flip sign. + } + } + + /** + * Returns the first argument with the sign of the second argument. + * + * @param magnitude Magnitude of the returned value. + * @param sign Sign of the returned value. + * @return a value with magnitude equal to {@code magnitude} and with the same sign as the + * {@code sign} argument. + * @throws MathArithmeticException if {@code magnitude == Integer.MIN_VALUE} and {@code sign >= + * 0}. + */ + public static int copySign(int magnitude, int sign) throws MathArithmeticException { + if ((magnitude >= 0 && sign >= 0) || (magnitude < 0 && sign < 0)) { // Sign is OK. + return magnitude; + } else if (sign >= 0 && magnitude == Integer.MIN_VALUE) { + throw new MathArithmeticException(LocalizedFormats.OVERFLOW); + } else { + return -magnitude; // Flip sign. + } + } + + /** + * Returns the first argument with the sign of the second argument. + * + * @param magnitude Magnitude of the returned value. + * @param sign Sign of the returned value. + * @return a value with magnitude equal to {@code magnitude} and with the same sign as the + * {@code sign} argument. + * @throws MathArithmeticException if {@code magnitude == Long.MIN_VALUE} and {@code sign >= 0}. + */ + public static long copySign(long magnitude, long sign) throws MathArithmeticException { + if ((magnitude >= 0 && sign >= 0) || (magnitude < 0 && sign < 0)) { // Sign is OK. + return magnitude; + } else if (sign >= 0 && magnitude == Long.MIN_VALUE) { + throw new MathArithmeticException(LocalizedFormats.OVERFLOW); + } else { + return -magnitude; // Flip sign. + } + } + + /** + * Check that the argument is a real number. + * + * @param x Argument. + * @throws NotFiniteNumberException if {@code x} is not a finite real number. + */ + public static void checkFinite(final double x) throws NotFiniteNumberException { + if (Double.isInfinite(x) || Double.isNaN(x)) { + throw new NotFiniteNumberException(x); + } + } + + /** + * Check that all the elements are real numbers. + * + * @param val Arguments. + * @throws NotFiniteNumberException if any values of the array is not a finite real number. + */ + public static void checkFinite(final double[] val) throws NotFiniteNumberException { + for (int i = 0; i < val.length; i++) { + final double x = val[i]; + if (Double.isInfinite(x) || Double.isNaN(x)) { + throw new NotFiniteNumberException(LocalizedFormats.ARRAY_ELEMENT, x, i); + } + } + } + + /** + * Checks that an object is not null. + * + * @param o Object to be checked. + * @param pattern Message pattern. + * @param args Arguments to replace the placeholders in {@code pattern}. + * @throws NullArgumentException if {@code o} is {@code null}. + */ + public static void checkNotNull(Object o, Localizable pattern, Object... args) + throws NullArgumentException { + if (o == null) { + throw new NullArgumentException(pattern, args); + } + } + + /** + * Checks that an object is not null. + * + * @param o Object to be checked. + * @throws NullArgumentException if {@code o} is {@code null}. + */ + public static void checkNotNull(Object o) throws NullArgumentException { + if (o == null) { + throw new NullArgumentException(); + } + } +} diff --git a/src/main/java/org/apache/commons/math3/util/MedianOf3PivotingStrategy.java b/src/main/java/org/apache/commons/math3/util/MedianOf3PivotingStrategy.java new file mode 100644 index 0000000..205f114 --- /dev/null +++ b/src/main/java/org/apache/commons/math3/util/MedianOf3PivotingStrategy.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math3.util; + +import org.apache.commons.math3.exception.MathIllegalArgumentException; + +import java.io.Serializable; + +/** + * Classic median of 3 strategy given begin and end indices. + * + * @since 3.4 + */ +public class MedianOf3PivotingStrategy implements PivotingStrategyInterface, Serializable { + + /** Serializable UID. */ + private static final long serialVersionUID = 20140713L; + + /** + * {@inheritDoc} This in specific makes use of median of 3 pivoting. + * + * @return The index corresponding to a pivot chosen between the first, middle and the last + * indices of the array slice + * @throws MathIllegalArgumentException when indices exceeds range + */ + public int pivotIndex(final double[] work, final int begin, final int end) + throws MathIllegalArgumentException { + MathArrays.verifyValues(work, begin, end - begin); + final int inclusiveEnd = end - 1; + final int middle = begin + (inclusiveEnd - begin) / 2; + final double wBegin = work[begin]; + final double wMiddle = work[middle]; + final double wEnd = work[inclusiveEnd]; + + if (wBegin < wMiddle) { + if (wMiddle < wEnd) { + return middle; + } else { + return wBegin < wEnd ? inclusiveEnd : begin; + } + } else { + if (wBegin < wEnd) { + return begin; + } else { + return wMiddle < wEnd ? inclusiveEnd : middle; + } + } + } +} diff --git a/src/main/java/org/apache/commons/math3/util/MultidimensionalCounter.java b/src/main/java/org/apache/commons/math3/util/MultidimensionalCounter.java new file mode 100644 index 0000000..5e239e9 --- /dev/null +++ b/src/main/java/org/apache/commons/math3/util/MultidimensionalCounter.java @@ -0,0 +1,283 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.math3.util; + +import org.apache.commons.math3.exception.DimensionMismatchException; +import org.apache.commons.math3.exception.NotStrictlyPositiveException; +import org.apache.commons.math3.exception.OutOfRangeException; + +import java.util.NoSuchElementException; + +/** + * Converter between unidimensional storage structure and multidimensional conceptual structure. + * This utility will convert from indices in a multidimensional structure to the corresponding index + * in a one-dimensional array. For example, assuming that the ranges (in 3 dimensions) of indices + * are 2, 4 and 3, the following correspondences, between 3-tuples indices and unidimensional + * indices, will hold: + * + * <ul> + * <li>(0, 0, 0) corresponds to 0 + * <li>(0, 0, 1) corresponds to 1 + * <li>(0, 0, 2) corresponds to 2 + * <li>(0, 1, 0) corresponds to 3 + * <li>... + * <li>(1, 0, 0) corresponds to 12 + * <li>... + * <li>(1, 3, 2) corresponds to 23 + * </ul> + * + * @since 2.2 + */ +public class MultidimensionalCounter implements Iterable<Integer> { + /** Number of dimensions. */ + private final int dimension; + + /** Offset for each dimension. */ + private final int[] uniCounterOffset; + + /** Counter sizes. */ + private final int[] size; + + /** Total number of (one-dimensional) slots. */ + private final int totalSize; + + /** Index of last dimension. */ + private final int last; + + /** Perform iteration over the multidimensional counter. */ + public class Iterator implements java.util.Iterator<Integer> { + /** Multidimensional counter. */ + private final int[] counter = new int[dimension]; + + /** Unidimensional counter. */ + private int count = -1; + + /** Maximum value for {@link #count}. */ + private final int maxCount = totalSize - 1; + + /** + * Create an iterator + * + * @see #iterator() + */ + Iterator() { + counter[last] = -1; + } + + /** {@inheritDoc} */ + public boolean hasNext() { + return count < maxCount; + } + + /** + * @return the unidimensional count after the counter has been incremented by {@code 1}. + * @throws NoSuchElementException if {@link #hasNext()} would have returned {@code false}. + */ + public Integer next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + + for (int i = last; i >= 0; i--) { + if (counter[i] == size[i] - 1) { + counter[i] = 0; + } else { + ++counter[i]; + break; + } + } + + return ++count; + } + + /** + * Get the current unidimensional counter slot. + * + * @return the index within the unidimensionl counter. + */ + public int getCount() { + return count; + } + + /** + * Get the current multidimensional counter slots. + * + * @return the indices within the multidimensional counter. + */ + public int[] getCounts() { + return MathArrays.copyOf(counter); + } + + /** + * Get the current count in the selected dimension. + * + * @param dim Dimension index. + * @return the count at the corresponding index for the current state of the iterator. + * @throws IndexOutOfBoundsException if {@code index} is not in the correct interval (as + * defined by the length of the argument in the {@link + * MultidimensionalCounter#MultidimensionalCounter(int[]) constructor of the enclosing + * class}). + */ + public int getCount(int dim) { + return counter[dim]; + } + + /** + * @throws UnsupportedOperationException + */ + public void remove() { + throw new UnsupportedOperationException(); + } + } + + /** + * Create a counter. + * + * @param size Counter sizes (number of slots in each dimension). + * @throws NotStrictlyPositiveException if one of the sizes is negative or zero. + */ + public MultidimensionalCounter(int... size) throws NotStrictlyPositiveException { + dimension = size.length; + this.size = MathArrays.copyOf(size); + + uniCounterOffset = new int[dimension]; + + last = dimension - 1; + int tS = size[last]; + for (int i = 0; i < last; i++) { + int count = 1; + for (int j = i + 1; j < dimension; j++) { + count *= size[j]; + } + uniCounterOffset[i] = count; + tS *= size[i]; + } + uniCounterOffset[last] = 0; + + if (tS <= 0) { + throw new NotStrictlyPositiveException(tS); + } + + totalSize = tS; + } + + /** + * Create an iterator over this counter. + * + * @return the iterator. + */ + public Iterator iterator() { + return new Iterator(); + } + + /** + * Get the number of dimensions of the multidimensional counter. + * + * @return the number of dimensions. + */ + public int getDimension() { + return dimension; + } + + /** + * Convert to multidimensional counter. + * + * @param index Index in unidimensional counter. + * @return the multidimensional counts. + * @throws OutOfRangeException if {@code index} is not between {@code 0} and the value returned + * by {@link #getSize()} (excluded). + */ + public int[] getCounts(int index) throws OutOfRangeException { + if (index < 0 || index >= totalSize) { + throw new OutOfRangeException(index, 0, totalSize); + } + + final int[] indices = new int[dimension]; + + int count = 0; + for (int i = 0; i < last; i++) { + int idx = 0; + final int offset = uniCounterOffset[i]; + while (count <= index) { + count += offset; + ++idx; + } + --idx; + count -= offset; + indices[i] = idx; + } + + indices[last] = index - count; + + return indices; + } + + /** + * Convert to unidimensional counter. + * + * @param c Indices in multidimensional counter. + * @return the index within the unidimensionl counter. + * @throws DimensionMismatchException if the size of {@code c} does not match the size of the + * array given in the constructor. + * @throws OutOfRangeException if a value of {@code c} is not in the range of the corresponding + * dimension, as defined in the {@link + * MultidimensionalCounter#MultidimensionalCounter(int...) constructor}. + */ + public int getCount(int... c) throws OutOfRangeException, DimensionMismatchException { + if (c.length != dimension) { + throw new DimensionMismatchException(c.length, dimension); + } + int count = 0; + for (int i = 0; i < dimension; i++) { + final int index = c[i]; + if (index < 0 || index >= size[i]) { + throw new OutOfRangeException(index, 0, size[i] - 1); + } + count += uniCounterOffset[i] * c[i]; + } + return count + c[last]; + } + + /** + * Get the total number of elements. + * + * @return the total size of the unidimensional counter. + */ + public int getSize() { + return totalSize; + } + + /** + * Get the number of multidimensional counter slots in each dimension. + * + * @return the sizes of the multidimensional counter in each dimension. + */ + public int[] getSizes() { + return MathArrays.copyOf(size); + } + + /** {@inheritDoc} */ + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + for (int i = 0; i < dimension; i++) { + sb.append("[").append(getCount(i)).append("]"); + } + return sb.toString(); + } +} diff --git a/src/main/java/org/apache/commons/math3/util/NumberTransformer.java b/src/main/java/org/apache/commons/math3/util/NumberTransformer.java new file mode 100644 index 0000000..d25ce14 --- /dev/null +++ b/src/main/java/org/apache/commons/math3/util/NumberTransformer.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math3.util; + +import org.apache.commons.math3.exception.MathIllegalArgumentException; + +/** + * Subclasses implementing this interface can transform Objects to doubles. + * + * <p>No longer extends Serializable since 2.0 + */ +public interface NumberTransformer { + + /** + * Implementing this interface provides a facility to transform from Object to Double. + * + * @param o the Object to be transformed. + * @return the double value of the Object. + * @throws MathIllegalArgumentException if the Object can not be transformed into a Double. + */ + double transform(Object o) throws MathIllegalArgumentException; +} diff --git a/src/main/java/org/apache/commons/math3/util/OpenIntToDoubleHashMap.java b/src/main/java/org/apache/commons/math3/util/OpenIntToDoubleHashMap.java new file mode 100644 index 0000000..cb8369d --- /dev/null +++ b/src/main/java/org/apache/commons/math3/util/OpenIntToDoubleHashMap.java @@ -0,0 +1,604 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.math3.util; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.Serializable; +import java.util.ConcurrentModificationException; +import java.util.NoSuchElementException; + +/** + * Open addressed map from int to double. + * + * <p>This class provides a dedicated map from integers to doubles with a much smaller memory + * overhead than standard <code>java.util.Map</code>. + * + * <p>This class is not synchronized. The specialized iterators returned by {@link #iterator()} are + * fail-fast: they throw a <code>ConcurrentModificationException</code> when they detect the map has + * been modified during iteration. + * + * @since 2.0 + */ +public class OpenIntToDoubleHashMap implements Serializable { + + /** Status indicator for free table entries. */ + protected static final byte FREE = 0; + + /** Status indicator for full table entries. */ + protected static final byte FULL = 1; + + /** Status indicator for removed table entries. */ + protected static final byte REMOVED = 2; + + /** Serializable version identifier */ + private static final long serialVersionUID = -3646337053166149105L; + + /** Load factor for the map. */ + private static final float LOAD_FACTOR = 0.5f; + + /** + * Default starting size. + * + * <p>This must be a power of two for bit mask to work properly. + */ + private static final int DEFAULT_EXPECTED_SIZE = 16; + + /** + * Multiplier for size growth when map fills up. + * + * <p>This must be a power of two for bit mask to work properly. + */ + private static final int RESIZE_MULTIPLIER = 2; + + /** Number of bits to perturb the index when probing for collision resolution. */ + private static final int PERTURB_SHIFT = 5; + + /** Keys table. */ + private int[] keys; + + /** Values table. */ + private double[] values; + + /** States table. */ + private byte[] states; + + /** Return value for missing entries. */ + private final double missingEntries; + + /** Current size of the map. */ + private int size; + + /** Bit mask for hash values. */ + private int mask; + + /** Modifications count. */ + private transient int count; + + /** Build an empty map with default size and using NaN for missing entries. */ + public OpenIntToDoubleHashMap() { + this(DEFAULT_EXPECTED_SIZE, Double.NaN); + } + + /** + * Build an empty map with default size + * + * @param missingEntries value to return when a missing entry is fetched + */ + public OpenIntToDoubleHashMap(final double missingEntries) { + this(DEFAULT_EXPECTED_SIZE, missingEntries); + } + + /** + * Build an empty map with specified size and using NaN for missing entries. + * + * @param expectedSize expected number of elements in the map + */ + public OpenIntToDoubleHashMap(final int expectedSize) { + this(expectedSize, Double.NaN); + } + + /** + * Build an empty map with specified size. + * + * @param expectedSize expected number of elements in the map + * @param missingEntries value to return when a missing entry is fetched + */ + public OpenIntToDoubleHashMap(final int expectedSize, final double missingEntries) { + final int capacity = computeCapacity(expectedSize); + keys = new int[capacity]; + values = new double[capacity]; + states = new byte[capacity]; + this.missingEntries = missingEntries; + mask = capacity - 1; + } + + /** + * Copy constructor. + * + * @param source map to copy + */ + public OpenIntToDoubleHashMap(final OpenIntToDoubleHashMap source) { + final int length = source.keys.length; + keys = new int[length]; + System.arraycopy(source.keys, 0, keys, 0, length); + values = new double[length]; + System.arraycopy(source.values, 0, values, 0, length); + states = new byte[length]; + System.arraycopy(source.states, 0, states, 0, length); + missingEntries = source.missingEntries; + size = source.size; + mask = source.mask; + count = source.count; + } + + /** + * Compute the capacity needed for a given size. + * + * @param expectedSize expected size of the map + * @return capacity to use for the specified size + */ + private static int computeCapacity(final int expectedSize) { + if (expectedSize == 0) { + return 1; + } + final int capacity = (int) FastMath.ceil(expectedSize / LOAD_FACTOR); + final int powerOfTwo = Integer.highestOneBit(capacity); + if (powerOfTwo == capacity) { + return capacity; + } + return nextPowerOfTwo(capacity); + } + + /** + * Find the smallest power of two greater than the input value + * + * @param i input value + * @return smallest power of two greater than the input value + */ + private static int nextPowerOfTwo(final int i) { + return Integer.highestOneBit(i) << 1; + } + + /** + * Get the stored value associated with the given key + * + * @param key key associated with the data + * @return data associated with the key + */ + public double get(final int key) { + + final int hash = hashOf(key); + int index = hash & mask; + if (containsKey(key, index)) { + return values[index]; + } + + if (states[index] == FREE) { + return missingEntries; + } + + int j = index; + for (int perturb = perturb(hash); states[index] != FREE; perturb >>= PERTURB_SHIFT) { + j = probe(perturb, j); + index = j & mask; + if (containsKey(key, index)) { + return values[index]; + } + } + + return missingEntries; + } + + /** + * Check if a value is associated with a key. + * + * @param key key to check + * @return true if a value is associated with key + */ + public boolean containsKey(final int key) { + + final int hash = hashOf(key); + int index = hash & mask; + if (containsKey(key, index)) { + return true; + } + + if (states[index] == FREE) { + return false; + } + + int j = index; + for (int perturb = perturb(hash); states[index] != FREE; perturb >>= PERTURB_SHIFT) { + j = probe(perturb, j); + index = j & mask; + if (containsKey(key, index)) { + return true; + } + } + + return false; + } + + /** + * Get an iterator over map elements. + * + * <p>The specialized iterators returned are fail-fast: they throw a <code> + * ConcurrentModificationException</code> when they detect the map has been modified during + * iteration. + * + * @return iterator over the map elements + */ + public Iterator iterator() { + return new Iterator(); + } + + /** + * Perturb the hash for starting probing. + * + * @param hash initial hash + * @return perturbed hash + */ + private static int perturb(final int hash) { + return hash & 0x7fffffff; + } + + /** + * Find the index at which a key should be inserted + * + * @param key key to lookup + * @return index at which key should be inserted + */ + private int findInsertionIndex(final int key) { + return findInsertionIndex(keys, states, key, mask); + } + + /** + * Find the index at which a key should be inserted + * + * @param keys keys table + * @param states states table + * @param key key to lookup + * @param mask bit mask for hash values + * @return index at which key should be inserted + */ + private static int findInsertionIndex( + final int[] keys, final byte[] states, final int key, final int mask) { + final int hash = hashOf(key); + int index = hash & mask; + if (states[index] == FREE) { + return index; + } else if (states[index] == FULL && keys[index] == key) { + return changeIndexSign(index); + } + + int perturb = perturb(hash); + int j = index; + if (states[index] == FULL) { + while (true) { + j = probe(perturb, j); + index = j & mask; + perturb >>= PERTURB_SHIFT; + + if (states[index] != FULL || keys[index] == key) { + break; + } + } + } + + if (states[index] == FREE) { + return index; + } else if (states[index] == FULL) { + // due to the loop exit condition, + // if (states[index] == FULL) then keys[index] == key + return changeIndexSign(index); + } + + final int firstRemoved = index; + while (true) { + j = probe(perturb, j); + index = j & mask; + + if (states[index] == FREE) { + return firstRemoved; + } else if (states[index] == FULL && keys[index] == key) { + return changeIndexSign(index); + } + + perturb >>= PERTURB_SHIFT; + } + } + + /** + * Compute next probe for collision resolution + * + * @param perturb perturbed hash + * @param j previous probe + * @return next probe + */ + private static int probe(final int perturb, final int j) { + return (j << 2) + j + perturb + 1; + } + + /** + * Change the index sign + * + * @param index initial index + * @return changed index + */ + private static int changeIndexSign(final int index) { + return -index - 1; + } + + /** + * Get the number of elements stored in the map. + * + * @return number of elements stored in the map + */ + public int size() { + return size; + } + + /** + * Remove the value associated with a key. + * + * @param key key to which the value is associated + * @return removed value + */ + public double remove(final int key) { + + final int hash = hashOf(key); + int index = hash & mask; + if (containsKey(key, index)) { + return doRemove(index); + } + + if (states[index] == FREE) { + return missingEntries; + } + + int j = index; + for (int perturb = perturb(hash); states[index] != FREE; perturb >>= PERTURB_SHIFT) { + j = probe(perturb, j); + index = j & mask; + if (containsKey(key, index)) { + return doRemove(index); + } + } + + return missingEntries; + } + + /** + * Check if the tables contain an element associated with specified key at specified index. + * + * @param key key to check + * @param index index to check + * @return true if an element is associated with key at index + */ + private boolean containsKey(final int key, final int index) { + return (key != 0 || states[index] == FULL) && keys[index] == key; + } + + /** + * Remove an element at specified index. + * + * @param index index of the element to remove + * @return removed value + */ + private double doRemove(int index) { + keys[index] = 0; + states[index] = REMOVED; + final double previous = values[index]; + values[index] = missingEntries; + --size; + ++count; + return previous; + } + + /** + * Put a value associated with a key in the map. + * + * @param key key to which value is associated + * @param value value to put in the map + * @return previous value associated with the key + */ + public double put(final int key, final double value) { + int index = findInsertionIndex(key); + double previous = missingEntries; + boolean newMapping = true; + if (index < 0) { + index = changeIndexSign(index); + previous = values[index]; + newMapping = false; + } + keys[index] = key; + states[index] = FULL; + values[index] = value; + if (newMapping) { + ++size; + if (shouldGrowTable()) { + growTable(); + } + ++count; + } + return previous; + } + + /** Grow the tables. */ + private void growTable() { + + final int oldLength = states.length; + final int[] oldKeys = keys; + final double[] oldValues = values; + final byte[] oldStates = states; + + final int newLength = RESIZE_MULTIPLIER * oldLength; + final int[] newKeys = new int[newLength]; + final double[] newValues = new double[newLength]; + final byte[] newStates = new byte[newLength]; + final int newMask = newLength - 1; + for (int i = 0; i < oldLength; ++i) { + if (oldStates[i] == FULL) { + final int key = oldKeys[i]; + final int index = findInsertionIndex(newKeys, newStates, key, newMask); + newKeys[index] = key; + newValues[index] = oldValues[i]; + newStates[index] = FULL; + } + } + + mask = newMask; + keys = newKeys; + values = newValues; + states = newStates; + } + + /** + * Check if tables should grow due to increased size. + * + * @return true if tables should grow + */ + private boolean shouldGrowTable() { + return size > (mask + 1) * LOAD_FACTOR; + } + + /** + * Compute the hash value of a key + * + * @param key key to hash + * @return hash value of the key + */ + private static int hashOf(final int key) { + final int h = key ^ ((key >>> 20) ^ (key >>> 12)); + return h ^ (h >>> 7) ^ (h >>> 4); + } + + /** Iterator class for the map. */ + public class Iterator { + + /** Reference modification count. */ + private final int referenceCount; + + /** Index of current element. */ + private int current; + + /** Index of next element. */ + private int next; + + /** Simple constructor. */ + private Iterator() { + + // preserve the modification count of the map to detect concurrent modifications later + referenceCount = count; + + // initialize current index + next = -1; + try { + advance(); + } catch (NoSuchElementException nsee) { // NOPMD + // ignored + } + } + + /** + * Check if there is a next element in the map. + * + * @return true if there is a next element + */ + public boolean hasNext() { + return next >= 0; + } + + /** + * Get the key of current entry. + * + * @return key of current entry + * @exception ConcurrentModificationException if the map is modified during iteration + * @exception NoSuchElementException if there is no element left in the map + */ + public int key() throws ConcurrentModificationException, NoSuchElementException { + if (referenceCount != count) { + throw new ConcurrentModificationException(); + } + if (current < 0) { + throw new NoSuchElementException(); + } + return keys[current]; + } + + /** + * Get the value of current entry. + * + * @return value of current entry + * @exception ConcurrentModificationException if the map is modified during iteration + * @exception NoSuchElementException if there is no element left in the map + */ + public double value() throws ConcurrentModificationException, NoSuchElementException { + if (referenceCount != count) { + throw new ConcurrentModificationException(); + } + if (current < 0) { + throw new NoSuchElementException(); + } + return values[current]; + } + + /** + * Advance iterator one step further. + * + * @exception ConcurrentModificationException if the map is modified during iteration + * @exception NoSuchElementException if there is no element left in the map + */ + public void advance() throws ConcurrentModificationException, NoSuchElementException { + + if (referenceCount != count) { + throw new ConcurrentModificationException(); + } + + // advance on step + current = next; + + // prepare next step + try { + while (states[++next] != FULL) { // NOPMD + // nothing to do + } + } catch (ArrayIndexOutOfBoundsException e) { + next = -2; + if (current < 0) { + throw new NoSuchElementException(); + } + } + } + } + + /** + * Read a serialized object. + * + * @param stream input stream + * @throws IOException if object cannot be read + * @throws ClassNotFoundException if the class corresponding to the serialized object cannot be + * found + */ + private void readObject(final ObjectInputStream stream) + throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + count = 0; + } +} diff --git a/src/main/java/org/apache/commons/math3/util/OpenIntToFieldHashMap.java b/src/main/java/org/apache/commons/math3/util/OpenIntToFieldHashMap.java new file mode 100644 index 0000000..0f4212f --- /dev/null +++ b/src/main/java/org/apache/commons/math3/util/OpenIntToFieldHashMap.java @@ -0,0 +1,632 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math3.util; + +import org.apache.commons.math3.Field; +import org.apache.commons.math3.FieldElement; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.Serializable; +import java.lang.reflect.Array; +import java.util.ConcurrentModificationException; +import java.util.NoSuchElementException; + +/** + * Open addressed map from int to FieldElement. + * + * <p>This class provides a dedicated map from integers to FieldElements with a much smaller memory + * overhead than standard <code>java.util.Map</code>. + * + * <p>This class is not synchronized. The specialized iterators returned by {@link #iterator()} are + * fail-fast: they throw a <code>ConcurrentModificationException</code> when they detect the map has + * been modified during iteration. + * + * @param <T> the type of the field elements + * @since 2.0 + */ +public class OpenIntToFieldHashMap<T extends FieldElement<T>> implements Serializable { + + /** Status indicator for free table entries. */ + protected static final byte FREE = 0; + + /** Status indicator for full table entries. */ + protected static final byte FULL = 1; + + /** Status indicator for removed table entries. */ + protected static final byte REMOVED = 2; + + /** Serializable version identifier. */ + private static final long serialVersionUID = -9179080286849120720L; + + /** Load factor for the map. */ + private static final float LOAD_FACTOR = 0.5f; + + /** + * Default starting size. + * + * <p>This must be a power of two for bit mask to work properly. + */ + private static final int DEFAULT_EXPECTED_SIZE = 16; + + /** + * Multiplier for size growth when map fills up. + * + * <p>This must be a power of two for bit mask to work properly. + */ + private static final int RESIZE_MULTIPLIER = 2; + + /** Number of bits to perturb the index when probing for collision resolution. */ + private static final int PERTURB_SHIFT = 5; + + /** Field to which the elements belong. */ + private final Field<T> field; + + /** Keys table. */ + private int[] keys; + + /** Values table. */ + private T[] values; + + /** States table. */ + private byte[] states; + + /** Return value for missing entries. */ + private final T missingEntries; + + /** Current size of the map. */ + private int size; + + /** Bit mask for hash values. */ + private int mask; + + /** Modifications count. */ + private transient int count; + + /** + * Build an empty map with default size and using zero for missing entries. + * + * @param field field to which the elements belong + */ + public OpenIntToFieldHashMap(final Field<T> field) { + this(field, DEFAULT_EXPECTED_SIZE, field.getZero()); + } + + /** + * Build an empty map with default size + * + * @param field field to which the elements belong + * @param missingEntries value to return when a missing entry is fetched + */ + public OpenIntToFieldHashMap(final Field<T> field, final T missingEntries) { + this(field, DEFAULT_EXPECTED_SIZE, missingEntries); + } + + /** + * Build an empty map with specified size and using zero for missing entries. + * + * @param field field to which the elements belong + * @param expectedSize expected number of elements in the map + */ + public OpenIntToFieldHashMap(final Field<T> field, final int expectedSize) { + this(field, expectedSize, field.getZero()); + } + + /** + * Build an empty map with specified size. + * + * @param field field to which the elements belong + * @param expectedSize expected number of elements in the map + * @param missingEntries value to return when a missing entry is fetched + */ + public OpenIntToFieldHashMap( + final Field<T> field, final int expectedSize, final T missingEntries) { + this.field = field; + final int capacity = computeCapacity(expectedSize); + keys = new int[capacity]; + values = buildArray(capacity); + states = new byte[capacity]; + this.missingEntries = missingEntries; + mask = capacity - 1; + } + + /** + * Copy constructor. + * + * @param source map to copy + */ + public OpenIntToFieldHashMap(final OpenIntToFieldHashMap<T> source) { + field = source.field; + final int length = source.keys.length; + keys = new int[length]; + System.arraycopy(source.keys, 0, keys, 0, length); + values = buildArray(length); + System.arraycopy(source.values, 0, values, 0, length); + states = new byte[length]; + System.arraycopy(source.states, 0, states, 0, length); + missingEntries = source.missingEntries; + size = source.size; + mask = source.mask; + count = source.count; + } + + /** + * Compute the capacity needed for a given size. + * + * @param expectedSize expected size of the map + * @return capacity to use for the specified size + */ + private static int computeCapacity(final int expectedSize) { + if (expectedSize == 0) { + return 1; + } + final int capacity = (int) FastMath.ceil(expectedSize / LOAD_FACTOR); + final int powerOfTwo = Integer.highestOneBit(capacity); + if (powerOfTwo == capacity) { + return capacity; + } + return nextPowerOfTwo(capacity); + } + + /** + * Find the smallest power of two greater than the input value + * + * @param i input value + * @return smallest power of two greater than the input value + */ + private static int nextPowerOfTwo(final int i) { + return Integer.highestOneBit(i) << 1; + } + + /** + * Get the stored value associated with the given key + * + * @param key key associated with the data + * @return data associated with the key + */ + public T get(final int key) { + + final int hash = hashOf(key); + int index = hash & mask; + if (containsKey(key, index)) { + return values[index]; + } + + if (states[index] == FREE) { + return missingEntries; + } + + int j = index; + for (int perturb = perturb(hash); states[index] != FREE; perturb >>= PERTURB_SHIFT) { + j = probe(perturb, j); + index = j & mask; + if (containsKey(key, index)) { + return values[index]; + } + } + + return missingEntries; + } + + /** + * Check if a value is associated with a key. + * + * @param key key to check + * @return true if a value is associated with key + */ + public boolean containsKey(final int key) { + + final int hash = hashOf(key); + int index = hash & mask; + if (containsKey(key, index)) { + return true; + } + + if (states[index] == FREE) { + return false; + } + + int j = index; + for (int perturb = perturb(hash); states[index] != FREE; perturb >>= PERTURB_SHIFT) { + j = probe(perturb, j); + index = j & mask; + if (containsKey(key, index)) { + return true; + } + } + + return false; + } + + /** + * Get an iterator over map elements. + * + * <p>The specialized iterators returned are fail-fast: they throw a <code> + * ConcurrentModificationException</code> when they detect the map has been modified during + * iteration. + * + * @return iterator over the map elements + */ + public Iterator iterator() { + return new Iterator(); + } + + /** + * Perturb the hash for starting probing. + * + * @param hash initial hash + * @return perturbed hash + */ + private static int perturb(final int hash) { + return hash & 0x7fffffff; + } + + /** + * Find the index at which a key should be inserted + * + * @param key key to lookup + * @return index at which key should be inserted + */ + private int findInsertionIndex(final int key) { + return findInsertionIndex(keys, states, key, mask); + } + + /** + * Find the index at which a key should be inserted + * + * @param keys keys table + * @param states states table + * @param key key to lookup + * @param mask bit mask for hash values + * @return index at which key should be inserted + */ + private static int findInsertionIndex( + final int[] keys, final byte[] states, final int key, final int mask) { + final int hash = hashOf(key); + int index = hash & mask; + if (states[index] == FREE) { + return index; + } else if (states[index] == FULL && keys[index] == key) { + return changeIndexSign(index); + } + + int perturb = perturb(hash); + int j = index; + if (states[index] == FULL) { + while (true) { + j = probe(perturb, j); + index = j & mask; + perturb >>= PERTURB_SHIFT; + + if (states[index] != FULL || keys[index] == key) { + break; + } + } + } + + if (states[index] == FREE) { + return index; + } else if (states[index] == FULL) { + // due to the loop exit condition, + // if (states[index] == FULL) then keys[index] == key + return changeIndexSign(index); + } + + final int firstRemoved = index; + while (true) { + j = probe(perturb, j); + index = j & mask; + + if (states[index] == FREE) { + return firstRemoved; + } else if (states[index] == FULL && keys[index] == key) { + return changeIndexSign(index); + } + + perturb >>= PERTURB_SHIFT; + } + } + + /** + * Compute next probe for collision resolution + * + * @param perturb perturbed hash + * @param j previous probe + * @return next probe + */ + private static int probe(final int perturb, final int j) { + return (j << 2) + j + perturb + 1; + } + + /** + * Change the index sign + * + * @param index initial index + * @return changed index + */ + private static int changeIndexSign(final int index) { + return -index - 1; + } + + /** + * Get the number of elements stored in the map. + * + * @return number of elements stored in the map + */ + public int size() { + return size; + } + + /** + * Remove the value associated with a key. + * + * @param key key to which the value is associated + * @return removed value + */ + public T remove(final int key) { + + final int hash = hashOf(key); + int index = hash & mask; + if (containsKey(key, index)) { + return doRemove(index); + } + + if (states[index] == FREE) { + return missingEntries; + } + + int j = index; + for (int perturb = perturb(hash); states[index] != FREE; perturb >>= PERTURB_SHIFT) { + j = probe(perturb, j); + index = j & mask; + if (containsKey(key, index)) { + return doRemove(index); + } + } + + return missingEntries; + } + + /** + * Check if the tables contain an element associated with specified key at specified index. + * + * @param key key to check + * @param index index to check + * @return true if an element is associated with key at index + */ + private boolean containsKey(final int key, final int index) { + return (key != 0 || states[index] == FULL) && keys[index] == key; + } + + /** + * Remove an element at specified index. + * + * @param index index of the element to remove + * @return removed value + */ + private T doRemove(int index) { + keys[index] = 0; + states[index] = REMOVED; + final T previous = values[index]; + values[index] = missingEntries; + --size; + ++count; + return previous; + } + + /** + * Put a value associated with a key in the map. + * + * @param key key to which value is associated + * @param value value to put in the map + * @return previous value associated with the key + */ + public T put(final int key, final T value) { + int index = findInsertionIndex(key); + T previous = missingEntries; + boolean newMapping = true; + if (index < 0) { + index = changeIndexSign(index); + previous = values[index]; + newMapping = false; + } + keys[index] = key; + states[index] = FULL; + values[index] = value; + if (newMapping) { + ++size; + if (shouldGrowTable()) { + growTable(); + } + ++count; + } + return previous; + } + + /** Grow the tables. */ + private void growTable() { + + final int oldLength = states.length; + final int[] oldKeys = keys; + final T[] oldValues = values; + final byte[] oldStates = states; + + final int newLength = RESIZE_MULTIPLIER * oldLength; + final int[] newKeys = new int[newLength]; + final T[] newValues = buildArray(newLength); + final byte[] newStates = new byte[newLength]; + final int newMask = newLength - 1; + for (int i = 0; i < oldLength; ++i) { + if (oldStates[i] == FULL) { + final int key = oldKeys[i]; + final int index = findInsertionIndex(newKeys, newStates, key, newMask); + newKeys[index] = key; + newValues[index] = oldValues[i]; + newStates[index] = FULL; + } + } + + mask = newMask; + keys = newKeys; + values = newValues; + states = newStates; + } + + /** + * Check if tables should grow due to increased size. + * + * @return true if tables should grow + */ + private boolean shouldGrowTable() { + return size > (mask + 1) * LOAD_FACTOR; + } + + /** + * Compute the hash value of a key + * + * @param key key to hash + * @return hash value of the key + */ + private static int hashOf(final int key) { + final int h = key ^ ((key >>> 20) ^ (key >>> 12)); + return h ^ (h >>> 7) ^ (h >>> 4); + } + + /** Iterator class for the map. */ + public class Iterator { + + /** Reference modification count. */ + private final int referenceCount; + + /** Index of current element. */ + private int current; + + /** Index of next element. */ + private int next; + + /** Simple constructor. */ + private Iterator() { + + // preserve the modification count of the map to detect concurrent modifications later + referenceCount = count; + + // initialize current index + next = -1; + try { + advance(); + } catch (NoSuchElementException nsee) { // NOPMD + // ignored + } + } + + /** + * Check if there is a next element in the map. + * + * @return true if there is a next element + */ + public boolean hasNext() { + return next >= 0; + } + + /** + * Get the key of current entry. + * + * @return key of current entry + * @exception ConcurrentModificationException if the map is modified during iteration + * @exception NoSuchElementException if there is no element left in the map + */ + public int key() throws ConcurrentModificationException, NoSuchElementException { + if (referenceCount != count) { + throw new ConcurrentModificationException(); + } + if (current < 0) { + throw new NoSuchElementException(); + } + return keys[current]; + } + + /** + * Get the value of current entry. + * + * @return value of current entry + * @exception ConcurrentModificationException if the map is modified during iteration + * @exception NoSuchElementException if there is no element left in the map + */ + public T value() throws ConcurrentModificationException, NoSuchElementException { + if (referenceCount != count) { + throw new ConcurrentModificationException(); + } + if (current < 0) { + throw new NoSuchElementException(); + } + return values[current]; + } + + /** + * Advance iterator one step further. + * + * @exception ConcurrentModificationException if the map is modified during iteration + * @exception NoSuchElementException if there is no element left in the map + */ + public void advance() throws ConcurrentModificationException, NoSuchElementException { + + if (referenceCount != count) { + throw new ConcurrentModificationException(); + } + + // advance on step + current = next; + + // prepare next step + try { + while (states[++next] != FULL) { // NOPMD + // nothing to do + } + } catch (ArrayIndexOutOfBoundsException e) { + next = -2; + if (current < 0) { + throw new NoSuchElementException(); + } + } + } + } + + /** + * Read a serialized object. + * + * @param stream input stream + * @throws IOException if object cannot be read + * @throws ClassNotFoundException if the class corresponding to the serialized object cannot be + * found + */ + private void readObject(final ObjectInputStream stream) + throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + count = 0; + } + + /** + * Build an array of elements. + * + * @param length size of the array to build + * @return a new array + */ + @SuppressWarnings("unchecked") // field is of type T + private T[] buildArray(final int length) { + return (T[]) Array.newInstance(field.getRuntimeClass(), length); + } +} diff --git a/src/main/java/org/apache/commons/math3/util/Pair.java b/src/main/java/org/apache/commons/math3/util/Pair.java new file mode 100644 index 0000000..95fbb2b --- /dev/null +++ b/src/main/java/org/apache/commons/math3/util/Pair.java @@ -0,0 +1,148 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math3.util; + +/** + * Generic pair. <br> + * Although the instances of this class are immutable, it is impossible to ensure that the + * references passed to the constructor will not be modified by the caller. + * + * @param <K> Key type. + * @param <V> Value type. + * @since 3.0 + */ +public class Pair<K, V> { + /** Key. */ + private final K key; + + /** Value. */ + private final V value; + + /** + * Create an entry representing a mapping from the specified key to the specified value. + * + * @param k Key (first element of the pair). + * @param v Value (second element of the pair). + */ + public Pair(K k, V v) { + key = k; + value = v; + } + + /** + * Create an entry representing the same mapping as the specified entry. + * + * @param entry Entry to copy. + */ + public Pair(Pair<? extends K, ? extends V> entry) { + this(entry.getKey(), entry.getValue()); + } + + /** + * Get the key. + * + * @return the key (first element of the pair). + */ + public K getKey() { + return key; + } + + /** + * Get the value. + * + * @return the value (second element of the pair). + */ + public V getValue() { + return value; + } + + /** + * Get the first element of the pair. + * + * @return the first element of the pair. + * @since 3.1 + */ + public K getFirst() { + return key; + } + + /** + * Get the second element of the pair. + * + * @return the second element of the pair. + * @since 3.1 + */ + public V getSecond() { + return value; + } + + /** + * Compare the specified object with this entry for equality. + * + * @param o Object. + * @return {@code true} if the given object is also a map entry and the two entries represent + * the same mapping. + */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof Pair)) { + return false; + } else { + Pair<?, ?> oP = (Pair<?, ?>) o; + return (key == null ? oP.key == null : key.equals(oP.key)) + && (value == null ? oP.value == null : value.equals(oP.value)); + } + } + + /** + * Compute a hash code. + * + * @return the hash code value. + */ + @Override + public int hashCode() { + int result = key == null ? 0 : key.hashCode(); + + final int h = value == null ? 0 : value.hashCode(); + result = 37 * result + h ^ (h >>> 16); + + return result; + } + + /** {@inheritDoc} */ + @Override + public String toString() { + return "[" + getKey() + ", " + getValue() + "]"; + } + + /** + * Convenience factory method that calls the {@link #Pair(Object, Object) constructor}. + * + * @param <K> the key type + * @param <V> the value type + * @param k First element of the pair. + * @param v Second element of the pair. + * @return a new {@code Pair} containing {@code k} and {@code v}. + * @since 3.3 + */ + public static <K, V> Pair<K, V> create(K k, V v) { + return new Pair<K, V>(k, v); + } +} diff --git a/src/main/java/org/apache/commons/math3/util/PivotingStrategyInterface.java b/src/main/java/org/apache/commons/math3/util/PivotingStrategyInterface.java new file mode 100644 index 0000000..0e2b175 --- /dev/null +++ b/src/main/java/org/apache/commons/math3/util/PivotingStrategyInterface.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math3.util; + +import org.apache.commons.math3.exception.MathIllegalArgumentException; + +/** + * A strategy to pick a pivoting index of an array for doing partitioning. + * + * @see MedianOf3PivotingStrategy + * @see RandomPivotingStrategy + * @see CentralPivotingStrategy + * @since 3.4 + */ +public interface PivotingStrategyInterface { + + /** + * Find pivot index of the array so that partition and K<sup>th</sup> element selection can be + * made + * + * @param work data array + * @param begin index of the first element of the slice + * @param end index after the last element of the slice + * @return the index of the pivot element chosen between the first and the last element of the + * array slice + * @throws MathIllegalArgumentException when indices exceeds range + */ + int pivotIndex(double[] work, int begin, int end) throws MathIllegalArgumentException; +} diff --git a/src/main/java/org/apache/commons/math3/util/Precision.java b/src/main/java/org/apache/commons/math3/util/Precision.java new file mode 100644 index 0000000..fe93003 --- /dev/null +++ b/src/main/java/org/apache/commons/math3/util/Precision.java @@ -0,0 +1,613 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.math3.util; + +import org.apache.commons.math3.exception.MathArithmeticException; +import org.apache.commons.math3.exception.MathIllegalArgumentException; +import org.apache.commons.math3.exception.util.LocalizedFormats; + +import java.math.BigDecimal; + +/** + * Utilities for comparing numbers. + * + * @since 3.0 + */ +public class Precision { + /** + * Largest double-precision floating-point number such that {@code 1 + EPSILON} is numerically + * equal to 1. This value is an upper bound on the relative error due to rounding real numbers + * to double precision floating-point numbers. + * + * <p>In IEEE 754 arithmetic, this is 2<sup>-53</sup>. + * + * @see <a href="http://en.wikipedia.org/wiki/Machine_epsilon">Machine epsilon</a> + */ + public static final double EPSILON; + + /** + * Safe minimum, such that {@code 1 / SAFE_MIN} does not overflow. <br> + * In IEEE 754 arithmetic, this is also the smallest normalized number 2<sup>-1022</sup>. + */ + public static final double SAFE_MIN; + + /** Exponent offset in IEEE754 representation. */ + private static final long EXPONENT_OFFSET = 1023l; + + /** Offset to order signed double numbers lexicographically. */ + private static final long SGN_MASK = 0x8000000000000000L; + + /** Offset to order signed double numbers lexicographically. */ + private static final int SGN_MASK_FLOAT = 0x80000000; + + /** Positive zero. */ + private static final double POSITIVE_ZERO = 0d; + + /** Positive zero bits. */ + private static final long POSITIVE_ZERO_DOUBLE_BITS = Double.doubleToRawLongBits(+0.0); + + /** Negative zero bits. */ + private static final long NEGATIVE_ZERO_DOUBLE_BITS = Double.doubleToRawLongBits(-0.0); + + /** Positive zero bits. */ + private static final int POSITIVE_ZERO_FLOAT_BITS = Float.floatToRawIntBits(+0.0f); + + /** Negative zero bits. */ + private static final int NEGATIVE_ZERO_FLOAT_BITS = Float.floatToRawIntBits(-0.0f); + + static { + /* + * This was previously expressed as = 0x1.0p-53; + * However, OpenJDK (Sparc Solaris) cannot handle such small + * constants: MATH-721 + */ + EPSILON = Double.longBitsToDouble((EXPONENT_OFFSET - 53l) << 52); + + /* + * This was previously expressed as = 0x1.0p-1022; + * However, OpenJDK (Sparc Solaris) cannot handle such small + * constants: MATH-721 + */ + SAFE_MIN = Double.longBitsToDouble((EXPONENT_OFFSET - 1022l) << 52); + } + + /** Private constructor. */ + private Precision() {} + + /** + * Compares two numbers given some amount of allowed error. + * + * @param x the first number + * @param y the second number + * @param eps the amount of error to allow when checking for equality + * @return + * <ul> + * <li>0 if {@link #equals(double, double, double) equals(x, y, eps)} + * <li>< 0 if !{@link #equals(double, double, double) equals(x, y, eps)} && x + * < y + * <li>> 0 if !{@link #equals(double, double, double) equals(x, y, eps)} && x > y + * or either argument is NaN + * </ul> + */ + public static int compareTo(double x, double y, double eps) { + if (equals(x, y, eps)) { + return 0; + } else if (x < y) { + return -1; + } + return 1; + } + + /** + * Compares two numbers given some amount of allowed error. Two float numbers are considered + * equal if there are {@code (maxUlps - 1)} (or fewer) floating point numbers between them, i.e. + * two adjacent floating point numbers are considered equal. Adapted from <a + * href="http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/"> + * Bruce Dawson</a>. Returns {@code false} if either of the arguments is NaN. + * + * @param x first value + * @param y second value + * @param maxUlps {@code (maxUlps - 1)} is the number of floating point values between {@code x} + * and {@code y}. + * @return + * <ul> + * <li>0 if {@link #equals(double, double, int) equals(x, y, maxUlps)} + * <li>< 0 if !{@link #equals(double, double, int) equals(x, y, maxUlps)} && x + * < y + * <li>> 0 if !{@link #equals(double, double, int) equals(x, y, maxUlps)} && x + * > y or either argument is NaN + * </ul> + */ + public static int compareTo(final double x, final double y, final int maxUlps) { + if (equals(x, y, maxUlps)) { + return 0; + } else if (x < y) { + return -1; + } + return 1; + } + + /** + * Returns true iff they are equal as defined by {@link #equals(float,float,int) equals(x, y, + * 1)}. + * + * @param x first value + * @param y second value + * @return {@code true} if the values are equal. + */ + public static boolean equals(float x, float y) { + return equals(x, y, 1); + } + + /** + * Returns true if both arguments are NaN or they are equal as defined by {@link + * #equals(float,float) equals(x, y, 1)}. + * + * @param x first value + * @param y second value + * @return {@code true} if the values are equal or both are NaN. + * @since 2.2 + */ + public static boolean equalsIncludingNaN(float x, float y) { + return (x != x || y != y) ? !(x != x ^ y != y) : equals(x, y, 1); + } + + /** + * Returns true if the arguments are equal or within the range of allowed error (inclusive). + * Returns {@code false} if either of the arguments is NaN. + * + * @param x first value + * @param y second value + * @param eps the amount of absolute error to allow. + * @return {@code true} if the values are equal or within range of each other. + * @since 2.2 + */ + public static boolean equals(float x, float y, float eps) { + return equals(x, y, 1) || FastMath.abs(y - x) <= eps; + } + + /** + * Returns true if the arguments are both NaN, are equal, or are within the range of allowed + * error (inclusive). + * + * @param x first value + * @param y second value + * @param eps the amount of absolute error to allow. + * @return {@code true} if the values are equal or within range of each other, or both are NaN. + * @since 2.2 + */ + public static boolean equalsIncludingNaN(float x, float y, float eps) { + return equalsIncludingNaN(x, y) || (FastMath.abs(y - x) <= eps); + } + + /** + * Returns true if the arguments are equal or within the range of allowed error (inclusive). Two + * float numbers are considered equal if there are {@code (maxUlps - 1)} (or fewer) floating + * point numbers between them, i.e. two adjacent floating point numbers are considered equal. + * Adapted from <a + * href="http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/"> + * Bruce Dawson</a>. Returns {@code false} if either of the arguments is NaN. + * + * @param x first value + * @param y second value + * @param maxUlps {@code (maxUlps - 1)} is the number of floating point values between {@code x} + * and {@code y}. + * @return {@code true} if there are fewer than {@code maxUlps} floating point values between + * {@code x} and {@code y}. + * @since 2.2 + */ + public static boolean equals(final float x, final float y, final int maxUlps) { + + final int xInt = Float.floatToRawIntBits(x); + final int yInt = Float.floatToRawIntBits(y); + + final boolean isEqual; + if (((xInt ^ yInt) & SGN_MASK_FLOAT) == 0) { + // number have same sign, there is no risk of overflow + isEqual = FastMath.abs(xInt - yInt) <= maxUlps; + } else { + // number have opposite signs, take care of overflow + final int deltaPlus; + final int deltaMinus; + if (xInt < yInt) { + deltaPlus = yInt - POSITIVE_ZERO_FLOAT_BITS; + deltaMinus = xInt - NEGATIVE_ZERO_FLOAT_BITS; + } else { + deltaPlus = xInt - POSITIVE_ZERO_FLOAT_BITS; + deltaMinus = yInt - NEGATIVE_ZERO_FLOAT_BITS; + } + + if (deltaPlus > maxUlps) { + isEqual = false; + } else { + isEqual = deltaMinus <= (maxUlps - deltaPlus); + } + } + + return isEqual && !Float.isNaN(x) && !Float.isNaN(y); + } + + /** + * Returns true if the arguments are both NaN or if they are equal as defined by {@link + * #equals(float,float,int) equals(x, y, maxUlps)}. + * + * @param x first value + * @param y second value + * @param maxUlps {@code (maxUlps - 1)} is the number of floating point values between {@code x} + * and {@code y}. + * @return {@code true} if both arguments are NaN or if there are less than {@code maxUlps} + * floating point values between {@code x} and {@code y}. + * @since 2.2 + */ + public static boolean equalsIncludingNaN(float x, float y, int maxUlps) { + return (x != x || y != y) ? !(x != x ^ y != y) : equals(x, y, maxUlps); + } + + /** + * Returns true iff they are equal as defined by {@link #equals(double,double,int) equals(x, y, + * 1)}. + * + * @param x first value + * @param y second value + * @return {@code true} if the values are equal. + */ + public static boolean equals(double x, double y) { + return equals(x, y, 1); + } + + /** + * Returns true if the arguments are both NaN or they are equal as defined by {@link + * #equals(double,double) equals(x, y, 1)}. + * + * @param x first value + * @param y second value + * @return {@code true} if the values are equal or both are NaN. + * @since 2.2 + */ + public static boolean equalsIncludingNaN(double x, double y) { + return (x != x || y != y) ? !(x != x ^ y != y) : equals(x, y, 1); + } + + /** + * Returns {@code true} if there is no double value strictly between the arguments or the + * difference between them is within the range of allowed error (inclusive). Returns {@code + * false} if either of the arguments is NaN. + * + * @param x First value. + * @param y Second value. + * @param eps Amount of allowed absolute error. + * @return {@code true} if the values are two adjacent floating point numbers or they are within + * range of each other. + */ + public static boolean equals(double x, double y, double eps) { + return equals(x, y, 1) || FastMath.abs(y - x) <= eps; + } + + /** + * Returns {@code true} if there is no double value strictly between the arguments or the + * relative difference between them is less than or equal to the given tolerance. Returns {@code + * false} if either of the arguments is NaN. + * + * @param x First value. + * @param y Second value. + * @param eps Amount of allowed relative error. + * @return {@code true} if the values are two adjacent floating point numbers or they are within + * range of each other. + * @since 3.1 + */ + public static boolean equalsWithRelativeTolerance(double x, double y, double eps) { + if (equals(x, y, 1)) { + return true; + } + + final double absoluteMax = FastMath.max(FastMath.abs(x), FastMath.abs(y)); + final double relativeDifference = FastMath.abs((x - y) / absoluteMax); + + return relativeDifference <= eps; + } + + /** + * Returns true if the arguments are both NaN, are equal or are within the range of allowed + * error (inclusive). + * + * @param x first value + * @param y second value + * @param eps the amount of absolute error to allow. + * @return {@code true} if the values are equal or within range of each other, or both are NaN. + * @since 2.2 + */ + public static boolean equalsIncludingNaN(double x, double y, double eps) { + return equalsIncludingNaN(x, y) || (FastMath.abs(y - x) <= eps); + } + + /** + * Returns true if the arguments are equal or within the range of allowed error (inclusive). + * + * <p>Two float numbers are considered equal if there are {@code (maxUlps - 1)} (or fewer) + * floating point numbers between them, i.e. two adjacent floating point numbers are considered + * equal. + * + * <p>Adapted from <a + * href="http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/"> + * Bruce Dawson</a>. Returns {@code false} if either of the arguments is NaN. + * + * @param x first value + * @param y second value + * @param maxUlps {@code (maxUlps - 1)} is the number of floating point values between {@code x} + * and {@code y}. + * @return {@code true} if there are fewer than {@code maxUlps} floating point values between + * {@code x} and {@code y}. + */ + public static boolean equals(final double x, final double y, final int maxUlps) { + + final long xInt = Double.doubleToRawLongBits(x); + final long yInt = Double.doubleToRawLongBits(y); + + final boolean isEqual; + if (((xInt ^ yInt) & SGN_MASK) == 0l) { + // number have same sign, there is no risk of overflow + isEqual = FastMath.abs(xInt - yInt) <= maxUlps; + } else { + // number have opposite signs, take care of overflow + final long deltaPlus; + final long deltaMinus; + if (xInt < yInt) { + deltaPlus = yInt - POSITIVE_ZERO_DOUBLE_BITS; + deltaMinus = xInt - NEGATIVE_ZERO_DOUBLE_BITS; + } else { + deltaPlus = xInt - POSITIVE_ZERO_DOUBLE_BITS; + deltaMinus = yInt - NEGATIVE_ZERO_DOUBLE_BITS; + } + + if (deltaPlus > maxUlps) { + isEqual = false; + } else { + isEqual = deltaMinus <= (maxUlps - deltaPlus); + } + } + + return isEqual && !Double.isNaN(x) && !Double.isNaN(y); + } + + /** + * Returns true if both arguments are NaN or if they are equal as defined by {@link + * #equals(double,double,int) equals(x, y, maxUlps)}. + * + * @param x first value + * @param y second value + * @param maxUlps {@code (maxUlps - 1)} is the number of floating point values between {@code x} + * and {@code y}. + * @return {@code true} if both arguments are NaN or if there are less than {@code maxUlps} + * floating point values between {@code x} and {@code y}. + * @since 2.2 + */ + public static boolean equalsIncludingNaN(double x, double y, int maxUlps) { + return (x != x || y != y) ? !(x != x ^ y != y) : equals(x, y, maxUlps); + } + + /** + * Rounds the given value to the specified number of decimal places. The value is rounded using + * the {@link BigDecimal#ROUND_HALF_UP} method. + * + * @param x Value to round. + * @param scale Number of digits to the right of the decimal point. + * @return the rounded value. + * @since 1.1 (previously in {@code MathUtils}, moved as of version 3.0) + */ + public static double round(double x, int scale) { + return round(x, scale, BigDecimal.ROUND_HALF_UP); + } + + /** + * Rounds the given value to the specified number of decimal places. The value is rounded using + * the given method which is any method defined in {@link BigDecimal}. If {@code x} is infinite + * or {@code NaN}, then the value of {@code x} is returned unchanged, regardless of the other + * parameters. + * + * @param x Value to round. + * @param scale Number of digits to the right of the decimal point. + * @param roundingMethod Rounding method as defined in {@link BigDecimal}. + * @return the rounded value. + * @throws ArithmeticException if {@code roundingMethod == ROUND_UNNECESSARY} and the specified + * scaling operation would require rounding. + * @throws IllegalArgumentException if {@code roundingMethod} does not represent a valid + * rounding mode. + * @since 1.1 (previously in {@code MathUtils}, moved as of version 3.0) + */ + public static double round(double x, int scale, int roundingMethod) { + try { + final double rounded = + (new BigDecimal(Double.toString(x)).setScale(scale, roundingMethod)) + .doubleValue(); + // MATH-1089: negative values rounded to zero should result in negative zero + return rounded == POSITIVE_ZERO ? POSITIVE_ZERO * x : rounded; + } catch (NumberFormatException ex) { + if (Double.isInfinite(x)) { + return x; + } else { + return Double.NaN; + } + } + } + + /** + * Rounds the given value to the specified number of decimal places. The value is rounded using + * the {@link BigDecimal#ROUND_HALF_UP} method. + * + * @param x Value to round. + * @param scale Number of digits to the right of the decimal point. + * @return the rounded value. + * @since 1.1 (previously in {@code MathUtils}, moved as of version 3.0) + */ + public static float round(float x, int scale) { + return round(x, scale, BigDecimal.ROUND_HALF_UP); + } + + /** + * Rounds the given value to the specified number of decimal places. The value is rounded using + * the given method which is any method defined in {@link BigDecimal}. + * + * @param x Value to round. + * @param scale Number of digits to the right of the decimal point. + * @param roundingMethod Rounding method as defined in {@link BigDecimal}. + * @return the rounded value. + * @since 1.1 (previously in {@code MathUtils}, moved as of version 3.0) + * @throws MathArithmeticException if an exact operation is required but result is not exact + * @throws MathIllegalArgumentException if {@code roundingMethod} is not a valid rounding + * method. + */ + public static float round(float x, int scale, int roundingMethod) + throws MathArithmeticException, MathIllegalArgumentException { + final float sign = FastMath.copySign(1f, x); + final float factor = (float) FastMath.pow(10.0f, scale) * sign; + return (float) roundUnscaled(x * factor, sign, roundingMethod) / factor; + } + + /** + * Rounds the given non-negative value to the "nearest" integer. Nearest is determined by the + * rounding method specified. Rounding methods are defined in {@link BigDecimal}. + * + * @param unscaled Value to round. + * @param sign Sign of the original, scaled value. + * @param roundingMethod Rounding method, as defined in {@link BigDecimal}. + * @return the rounded value. + * @throws MathArithmeticException if an exact operation is required but result is not exact + * @throws MathIllegalArgumentException if {@code roundingMethod} is not a valid rounding + * method. + * @since 1.1 (previously in {@code MathUtils}, moved as of version 3.0) + */ + private static double roundUnscaled(double unscaled, double sign, int roundingMethod) + throws MathArithmeticException, MathIllegalArgumentException { + switch (roundingMethod) { + case BigDecimal.ROUND_CEILING: + if (sign == -1) { + unscaled = + FastMath.floor(FastMath.nextAfter(unscaled, Double.NEGATIVE_INFINITY)); + } else { + unscaled = + FastMath.ceil(FastMath.nextAfter(unscaled, Double.POSITIVE_INFINITY)); + } + break; + case BigDecimal.ROUND_DOWN: + unscaled = FastMath.floor(FastMath.nextAfter(unscaled, Double.NEGATIVE_INFINITY)); + break; + case BigDecimal.ROUND_FLOOR: + if (sign == -1) { + unscaled = + FastMath.ceil(FastMath.nextAfter(unscaled, Double.POSITIVE_INFINITY)); + } else { + unscaled = + FastMath.floor(FastMath.nextAfter(unscaled, Double.NEGATIVE_INFINITY)); + } + break; + case BigDecimal.ROUND_HALF_DOWN: + { + unscaled = FastMath.nextAfter(unscaled, Double.NEGATIVE_INFINITY); + double fraction = unscaled - FastMath.floor(unscaled); + if (fraction > 0.5) { + unscaled = FastMath.ceil(unscaled); + } else { + unscaled = FastMath.floor(unscaled); + } + break; + } + case BigDecimal.ROUND_HALF_EVEN: + { + double fraction = unscaled - FastMath.floor(unscaled); + if (fraction > 0.5) { + unscaled = FastMath.ceil(unscaled); + } else if (fraction < 0.5) { + unscaled = FastMath.floor(unscaled); + } else { + // The following equality test is intentional and needed for rounding + // purposes + if (FastMath.floor(unscaled) / 2.0 + == FastMath.floor(FastMath.floor(unscaled) / 2.0)) { // even + unscaled = FastMath.floor(unscaled); + } else { // odd + unscaled = FastMath.ceil(unscaled); + } + } + break; + } + case BigDecimal.ROUND_HALF_UP: + { + unscaled = FastMath.nextAfter(unscaled, Double.POSITIVE_INFINITY); + double fraction = unscaled - FastMath.floor(unscaled); + if (fraction >= 0.5) { + unscaled = FastMath.ceil(unscaled); + } else { + unscaled = FastMath.floor(unscaled); + } + break; + } + case BigDecimal.ROUND_UNNECESSARY: + if (unscaled != FastMath.floor(unscaled)) { + throw new MathArithmeticException(); + } + break; + case BigDecimal.ROUND_UP: + // do not round if the discarded fraction is equal to zero + if (unscaled != FastMath.floor(unscaled)) { + unscaled = + FastMath.ceil(FastMath.nextAfter(unscaled, Double.POSITIVE_INFINITY)); + } + break; + default: + throw new MathIllegalArgumentException( + LocalizedFormats.INVALID_ROUNDING_METHOD, + roundingMethod, + "ROUND_CEILING", + BigDecimal.ROUND_CEILING, + "ROUND_DOWN", + BigDecimal.ROUND_DOWN, + "ROUND_FLOOR", + BigDecimal.ROUND_FLOOR, + "ROUND_HALF_DOWN", + BigDecimal.ROUND_HALF_DOWN, + "ROUND_HALF_EVEN", + BigDecimal.ROUND_HALF_EVEN, + "ROUND_HALF_UP", + BigDecimal.ROUND_HALF_UP, + "ROUND_UNNECESSARY", + BigDecimal.ROUND_UNNECESSARY, + "ROUND_UP", + BigDecimal.ROUND_UP); + } + return unscaled; + } + + /** + * Computes a number {@code delta} close to {@code originalDelta} with the property that + * + * <pre><code> + * x + delta - x + * </code></pre> + * + * is exactly machine-representable. This is useful when computing numerical derivatives, in + * order to reduce roundoff errors. + * + * @param x Value. + * @param originalDelta Offset value. + * @return a number {@code delta} so that {@code x + delta} and {@code x} differ by a + * representable floating number. + */ + public static double representableDelta(double x, double originalDelta) { + return x + originalDelta - x; + } +} diff --git a/src/main/java/org/apache/commons/math3/util/RandomPivotingStrategy.java b/src/main/java/org/apache/commons/math3/util/RandomPivotingStrategy.java new file mode 100644 index 0000000..f2fc28b --- /dev/null +++ b/src/main/java/org/apache/commons/math3/util/RandomPivotingStrategy.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math3.util; + +import org.apache.commons.math3.exception.MathIllegalArgumentException; +import org.apache.commons.math3.random.RandomGenerator; + +import java.io.Serializable; + +/** + * A strategy of selecting random index between begin and end indices. + * + * @since 3.4 + */ +public class RandomPivotingStrategy implements PivotingStrategyInterface, Serializable { + + /** Serializable UID. */ + private static final long serialVersionUID = 20140713L; + + /** Random generator to use for selecting pivot. */ + private final RandomGenerator random; + + /** + * Simple constructor. + * + * @param random random generator to use for selecting pivot + */ + public RandomPivotingStrategy(final RandomGenerator random) { + this.random = random; + } + + /** + * {@inheritDoc} A uniform random pivot selection between begin and end indices + * + * @return The index corresponding to a random uniformly selected value between first and the + * last indices of the array slice + * @throws MathIllegalArgumentException when indices exceeds range + */ + public int pivotIndex(final double[] work, final int begin, final int end) + throws MathIllegalArgumentException { + MathArrays.verifyValues(work, begin, end - begin); + return begin + random.nextInt(end - begin - 1); + } +} diff --git a/src/main/java/org/apache/commons/math3/util/ResizableDoubleArray.java b/src/main/java/org/apache/commons/math3/util/ResizableDoubleArray.java new file mode 100644 index 0000000..f0963ef --- /dev/null +++ b/src/main/java/org/apache/commons/math3/util/ResizableDoubleArray.java @@ -0,0 +1,1130 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math3.util; + +import org.apache.commons.math3.exception.MathIllegalArgumentException; +import org.apache.commons.math3.exception.MathIllegalStateException; +import org.apache.commons.math3.exception.MathInternalError; +import org.apache.commons.math3.exception.NotStrictlyPositiveException; +import org.apache.commons.math3.exception.NullArgumentException; +import org.apache.commons.math3.exception.NumberIsTooSmallException; +import org.apache.commons.math3.exception.util.LocalizedFormats; + +import java.io.Serializable; +import java.util.Arrays; + +/** + * A variable length {@link DoubleArray} implementation that automatically handles expanding and + * contracting its internal storage array as elements are added and removed. + * + * <h3>Important note: Usage should not assume that this class is thread-safe even though some of + * the methods are {@code synchronized}. This qualifier will be dropped in the next major release + * (4.0).</h3> + * + * <p>The internal storage array starts with capacity determined by the {@code initialCapacity} + * property, which can be set by the constructor. The default initial capacity is 16. Adding + * elements using {@link #addElement(double)} appends elements to the end of the array. When there + * are no open entries at the end of the internal storage array, the array is expanded. The size of + * the expanded array depends on the {@code expansionMode} and {@code expansionFactor} properties. + * The {@code expansionMode} determines whether the size of the array is multiplied by the {@code + * expansionFactor} ({@link ExpansionMode#MULTIPLICATIVE}) or if the expansion is additive ({@link + * ExpansionMode#ADDITIVE} -- {@code expansionFactor} storage locations added). The default {@code + * expansionMode} is {@code MULTIPLICATIVE} and the default {@code expansionFactor} is 2. + * + * <p>The {@link #addElementRolling(double)} method adds a new element to the end of the internal + * storage array and adjusts the "usable window" of the internal array forward by one position + * (effectively making what was the second element the first, and so on). Repeated activations of + * this method (or activation of {@link #discardFrontElements(int)}) will effectively orphan the + * storage locations at the beginning of the internal storage array. To reclaim this storage, each + * time one of these methods is activated, the size of the internal storage array is compared to the + * number of addressable elements (the {@code numElements} property) and if the difference is too + * large, the internal array is contracted to size {@code numElements + 1}. The determination of + * when the internal storage array is "too large" depends on the {@code expansionMode} and {@code + * contractionFactor} properties. If the {@code expansionMode} is {@code MULTIPLICATIVE}, + * contraction is triggered when the ratio between storage array length and {@code numElements} + * exceeds {@code contractionFactor.} If the {@code expansionMode} is {@code ADDITIVE}, the number + * of excess storage locations is compared to {@code contractionFactor}. + * + * <p>To avoid cycles of expansions and contractions, the {@code expansionFactor} must not exceed + * the {@code contractionFactor}. Constructors and mutators for both of these properties enforce + * this requirement, throwing a {@code MathIllegalArgumentException} if it is violated. + */ +public class ResizableDoubleArray implements DoubleArray, Serializable { + /** + * Additive expansion mode. + * + * @deprecated As of 3.1. Please use {@link ExpansionMode#ADDITIVE} instead. + */ + @Deprecated public static final int ADDITIVE_MODE = 1; + + /** + * Multiplicative expansion mode. + * + * @deprecated As of 3.1. Please use {@link ExpansionMode#MULTIPLICATIVE} instead. + */ + @Deprecated public static final int MULTIPLICATIVE_MODE = 0; + + /** Serializable version identifier. */ + private static final long serialVersionUID = -3485529955529426875L; + + /** Default value for initial capacity. */ + private static final int DEFAULT_INITIAL_CAPACITY = 16; + + /** Default value for array size modifier. */ + private static final double DEFAULT_EXPANSION_FACTOR = 2.0; + + /** + * Default value for the difference between {@link #contractionCriterion} and {@link + * #expansionFactor}. + */ + private static final double DEFAULT_CONTRACTION_DELTA = 0.5; + + /** + * The contraction criteria determines when the internal array will be contracted to fit the + * number of elements contained in the element array + 1. + */ + private double contractionCriterion = 2.5; + + /** + * The expansion factor of the array. When the array needs to be expanded, the new array size + * will be {@code internalArray.length * expansionFactor} if {@code expansionMode} is set to + * MULTIPLICATIVE_MODE, or {@code internalArray.length + expansionFactor} if {@code + * expansionMode} is set to ADDITIVE_MODE. + */ + private double expansionFactor = 2.0; + + /** + * Determines whether array expansion by {@code expansionFactor} is additive or multiplicative. + */ + private ExpansionMode expansionMode = ExpansionMode.MULTIPLICATIVE; + + /** The internal storage array. */ + private double[] internalArray; + + /** + * The number of addressable elements in the array. Note that this has nothing to do with the + * length of the internal storage array. + */ + private int numElements = 0; + + /** + * The position of the first addressable element in the internal storage array. The addressable + * elements in the array are {@code internalArray[startIndex],...,internalArray[startIndex + + * numElements - 1]}. + */ + private int startIndex = 0; + + /** + * Specification of expansion algorithm. + * + * @since 3.1 + */ + public enum ExpansionMode { + /** Multiplicative expansion mode. */ + MULTIPLICATIVE, + /** Additive expansion mode. */ + ADDITIVE + } + + /** + * Creates an instance with default properties. + * + * <ul> + * <li>{@code initialCapacity = 16} + * <li>{@code expansionMode = MULTIPLICATIVE} + * <li>{@code expansionFactor = 2.0} + * <li>{@code contractionCriterion = 2.5} + * </ul> + */ + public ResizableDoubleArray() { + this(DEFAULT_INITIAL_CAPACITY); + } + + /** + * Creates an instance with the specified initial capacity. Other properties take default + * values: + * + * <ul> + * <li>{@code expansionMode = MULTIPLICATIVE} + * <li>{@code expansionFactor = 2.0} + * <li>{@code contractionCriterion = 2.5} + * </ul> + * + * @param initialCapacity Initial size of the internal storage array. + * @throws MathIllegalArgumentException if {@code initialCapacity <= 0}. + */ + public ResizableDoubleArray(int initialCapacity) throws MathIllegalArgumentException { + this(initialCapacity, DEFAULT_EXPANSION_FACTOR); + } + + /** + * Creates an instance from an existing {@code double[]} with the initial capacity and + * numElements corresponding to the size of the supplied {@code double[]} array. If the supplied + * array is null, a new empty array with the default initial capacity will be created. The input + * array is copied, not referenced. Other properties take default values: + * + * <ul> + * <li>{@code initialCapacity = 16} + * <li>{@code expansionMode = MULTIPLICATIVE} + * <li>{@code expansionFactor = 2.0} + * <li>{@code contractionCriterion = 2.5} + * </ul> + * + * @param initialArray initial array + * @since 2.2 + */ + public ResizableDoubleArray(double[] initialArray) { + this( + DEFAULT_INITIAL_CAPACITY, + DEFAULT_EXPANSION_FACTOR, + DEFAULT_CONTRACTION_DELTA + DEFAULT_EXPANSION_FACTOR, + ExpansionMode.MULTIPLICATIVE, + initialArray); + } + + /** + * Creates an instance with the specified initial capacity and expansion factor. The remaining + * properties take default values: + * + * <ul> + * <li>{@code expansionMode = MULTIPLICATIVE} + * <li>{@code contractionCriterion = 0.5 + expansionFactor} + * </ul> + * + * <br> + * Throws IllegalArgumentException if the following conditions are not met: + * + * <ul> + * <li>{@code initialCapacity > 0} + * <li>{@code expansionFactor > 1} + * </ul> + * + * @param initialCapacity Initial size of the internal storage array. + * @param expansionFactor The array will be expanded based on this parameter. + * @throws MathIllegalArgumentException if parameters are not valid. + * @deprecated As of 3.1. Please use {@link #ResizableDoubleArray(int,double)} instead. + */ + @Deprecated + public ResizableDoubleArray(int initialCapacity, float expansionFactor) + throws MathIllegalArgumentException { + this(initialCapacity, (double) expansionFactor); + } + + /** + * Creates an instance with the specified initial capacity and expansion factor. The remaining + * properties take default values: + * + * <ul> + * <li>{@code expansionMode = MULTIPLICATIVE} + * <li>{@code contractionCriterion = 0.5 + expansionFactor} + * </ul> + * + * <br> + * Throws IllegalArgumentException if the following conditions are not met: + * + * <ul> + * <li>{@code initialCapacity > 0} + * <li>{@code expansionFactor > 1} + * </ul> + * + * @param initialCapacity Initial size of the internal storage array. + * @param expansionFactor The array will be expanded based on this parameter. + * @throws MathIllegalArgumentException if parameters are not valid. + * @since 3.1 + */ + public ResizableDoubleArray(int initialCapacity, double expansionFactor) + throws MathIllegalArgumentException { + this(initialCapacity, expansionFactor, DEFAULT_CONTRACTION_DELTA + expansionFactor); + } + + /** + * Creates an instance with the specified initialCapacity, expansionFactor, and + * contractionCriterion. The expansion mode will default to {@code MULTIPLICATIVE}. <br> + * Throws IllegalArgumentException if the following conditions are not met: + * + * <ul> + * <li>{@code initialCapacity > 0} + * <li>{@code expansionFactor > 1} + * <li>{@code contractionCriterion >= expansionFactor} + * </ul> + * + * @param initialCapacity Initial size of the internal storage array.. + * @param expansionFactor The array will be expanded based on this parameter. + * @param contractionCriteria Contraction criteria. + * @throws MathIllegalArgumentException if parameters are not valid. + * @deprecated As of 3.1. Please use {@link #ResizableDoubleArray(int,double,double)} instead. + */ + @Deprecated + public ResizableDoubleArray( + int initialCapacity, float expansionFactor, float contractionCriteria) + throws MathIllegalArgumentException { + this(initialCapacity, (double) expansionFactor, (double) contractionCriteria); + } + + /** + * Creates an instance with the specified initial capacity, expansion factor, and contraction + * criteria. The expansion mode will default to {@code MULTIPLICATIVE}. <br> + * Throws IllegalArgumentException if the following conditions are not met: + * + * <ul> + * <li>{@code initialCapacity > 0} + * <li>{@code expansionFactor > 1} + * <li>{@code contractionCriterion >= expansionFactor} + * </ul> + * + * @param initialCapacity Initial size of the internal storage array.. + * @param expansionFactor The array will be expanded based on this parameter. + * @param contractionCriterion Contraction criterion. + * @throws MathIllegalArgumentException if the parameters are not valid. + * @since 3.1 + */ + public ResizableDoubleArray( + int initialCapacity, double expansionFactor, double contractionCriterion) + throws MathIllegalArgumentException { + this( + initialCapacity, + expansionFactor, + contractionCriterion, + ExpansionMode.MULTIPLICATIVE, + null); + } + + /** + * Create a ResizableArray with the specified properties. + * + * <p>Throws IllegalArgumentException if the following conditions are not met: + * + * <ul> + * <li><code>initialCapacity > 0</code> + * <li><code>expansionFactor > 1</code> + * <li><code>contractionFactor >= expansionFactor</code> + * <li><code>expansionMode in {MULTIPLICATIVE_MODE, ADDITIVE_MODE}</code> + * </ul> + * + * @param initialCapacity the initial size of the internal storage array + * @param expansionFactor the array will be expanded based on this parameter + * @param contractionCriteria the contraction Criteria + * @param expansionMode the expansion mode + * @throws MathIllegalArgumentException if parameters are not valid + * @deprecated As of 3.1. Please use {@link + * #ResizableDoubleArray(int,double,double,ExpansionMode,double[])} instead. + */ + @Deprecated + public ResizableDoubleArray( + int initialCapacity, + float expansionFactor, + float contractionCriteria, + int expansionMode) + throws MathIllegalArgumentException { + this( + initialCapacity, + expansionFactor, + contractionCriteria, + expansionMode == ADDITIVE_MODE + ? ExpansionMode.ADDITIVE + : ExpansionMode.MULTIPLICATIVE, + null); + // XXX Just ot retain the expected failure in a unit test. + // With the new "enum", that test will become obsolete. + setExpansionMode(expansionMode); + } + + /** + * Creates an instance with the specified properties. <br> + * Throws MathIllegalArgumentException if the following conditions are not met: + * + * <ul> + * <li>{@code initialCapacity > 0} + * <li>{@code expansionFactor > 1} + * <li>{@code contractionCriterion >= expansionFactor} + * </ul> + * + * @param initialCapacity Initial size of the internal storage array. + * @param expansionFactor The array will be expanded based on this parameter. + * @param contractionCriterion Contraction criteria. + * @param expansionMode Expansion mode. + * @param data Initial contents of the array. + * @throws MathIllegalArgumentException if the parameters are not valid. + */ + public ResizableDoubleArray( + int initialCapacity, + double expansionFactor, + double contractionCriterion, + ExpansionMode expansionMode, + double... data) + throws MathIllegalArgumentException { + if (initialCapacity <= 0) { + throw new NotStrictlyPositiveException( + LocalizedFormats.INITIAL_CAPACITY_NOT_POSITIVE, initialCapacity); + } + checkContractExpand(contractionCriterion, expansionFactor); + + this.expansionFactor = expansionFactor; + this.contractionCriterion = contractionCriterion; + this.expansionMode = expansionMode; + internalArray = new double[initialCapacity]; + numElements = 0; + startIndex = 0; + + if (data != null && data.length > 0) { + addElements(data); + } + } + + /** + * Copy constructor. Creates a new ResizableDoubleArray that is a deep, fresh copy of the + * original. Needs to acquire synchronization lock on original. Original may not be null; + * otherwise a {@link NullArgumentException} is thrown. + * + * @param original array to copy + * @exception NullArgumentException if original is null + * @since 2.0 + */ + public ResizableDoubleArray(ResizableDoubleArray original) throws NullArgumentException { + MathUtils.checkNotNull(original); + copy(original, this); + } + + /** + * Adds an element to the end of this expandable array. + * + * @param value Value to be added to end of array. + */ + public synchronized void addElement(double value) { + if (internalArray.length <= startIndex + numElements) { + expand(); + } + internalArray[startIndex + numElements++] = value; + } + + /** + * Adds several element to the end of this expandable array. + * + * @param values Values to be added to end of array. + * @since 2.2 + */ + public synchronized void addElements(double[] values) { + final double[] tempArray = new double[numElements + values.length + 1]; + System.arraycopy(internalArray, startIndex, tempArray, 0, numElements); + System.arraycopy(values, 0, tempArray, numElements, values.length); + internalArray = tempArray; + startIndex = 0; + numElements += values.length; + } + + /** + * Adds an element to the end of the array and removes the first element in the array. Returns + * the discarded first element. The effect is similar to a push operation in a FIFO queue. + * + * <p>Example: If the array contains the elements 1, 2, 3, 4 (in that order) and + * addElementRolling(5) is invoked, the result is an array containing the entries 2, 3, 4, 5 and + * the value returned is 1. + * + * @param value Value to be added to the array. + * @return the value which has been discarded or "pushed" out of the array by this rolling + * insert. + */ + public synchronized double addElementRolling(double value) { + double discarded = internalArray[startIndex]; + + if ((startIndex + (numElements + 1)) > internalArray.length) { + expand(); + } + // Increment the start index + startIndex += 1; + + // Add the new value + internalArray[startIndex + (numElements - 1)] = value; + + // Check the contraction criterion. + if (shouldContract()) { + contract(); + } + return discarded; + } + + /** + * Substitutes <code>value</code> for the most recently added value. Returns the value that has + * been replaced. If the array is empty (i.e. if {@link #numElements} is zero), an + * IllegalStateException is thrown. + * + * @param value New value to substitute for the most recently added value + * @return the value that has been replaced in the array. + * @throws MathIllegalStateException if the array is empty + * @since 2.0 + */ + public synchronized double substituteMostRecentElement(double value) + throws MathIllegalStateException { + if (numElements < 1) { + throw new MathIllegalStateException( + LocalizedFormats.CANNOT_SUBSTITUTE_ELEMENT_FROM_EMPTY_ARRAY); + } + + final int substIndex = startIndex + (numElements - 1); + final double discarded = internalArray[substIndex]; + + internalArray[substIndex] = value; + + return discarded; + } + + /** + * Checks the expansion factor and the contraction criterion and throws an + * IllegalArgumentException if the contractionCriteria is less than the expansionCriteria + * + * @param expansion factor to be checked + * @param contraction criteria to be checked + * @throws MathIllegalArgumentException if the contractionCriteria is less than the + * expansionCriteria. + * @deprecated As of 3.1. Please use {@link #checkContractExpand(double,double)} instead. + */ + @Deprecated + protected void checkContractExpand(float contraction, float expansion) + throws MathIllegalArgumentException { + checkContractExpand((double) contraction, (double) expansion); + } + + /** + * Checks the expansion factor and the contraction criterion and raises an exception if the + * contraction criterion is smaller than the expansion criterion. + * + * @param contraction Criterion to be checked. + * @param expansion Factor to be checked. + * @throws NumberIsTooSmallException if {@code contraction < expansion}. + * @throws NumberIsTooSmallException if {@code contraction <= 1}. + * @throws NumberIsTooSmallException if {@code expansion <= 1 }. + * @since 3.1 + */ + protected void checkContractExpand(double contraction, double expansion) + throws NumberIsTooSmallException { + if (contraction < expansion) { + final NumberIsTooSmallException e = new NumberIsTooSmallException(contraction, 1, true); + e.getContext() + .addMessage( + LocalizedFormats.CONTRACTION_CRITERIA_SMALLER_THAN_EXPANSION_FACTOR, + contraction, + expansion); + throw e; + } + + if (contraction <= 1) { + final NumberIsTooSmallException e = + new NumberIsTooSmallException(contraction, 1, false); + e.getContext() + .addMessage( + LocalizedFormats.CONTRACTION_CRITERIA_SMALLER_THAN_ONE, contraction); + throw e; + } + + if (expansion <= 1) { + final NumberIsTooSmallException e = + new NumberIsTooSmallException(contraction, 1, false); + e.getContext() + .addMessage(LocalizedFormats.EXPANSION_FACTOR_SMALLER_THAN_ONE, expansion); + throw e; + } + } + + /** Clear the array contents, resetting the number of elements to zero. */ + public synchronized void clear() { + numElements = 0; + startIndex = 0; + } + + /** + * Contracts the storage array to the (size of the element set) + 1 - to avoid a zero length + * array. This function also resets the startIndex to zero. + */ + public synchronized void contract() { + final double[] tempArray = new double[numElements + 1]; + + // Copy and swap - copy only the element array from the src array. + System.arraycopy(internalArray, startIndex, tempArray, 0, numElements); + internalArray = tempArray; + + // Reset the start index to zero + startIndex = 0; + } + + /** + * Discards the <code>i</code> initial elements of the array. For example, if the array contains + * the elements 1,2,3,4, invoking <code>discardFrontElements(2)</code> will cause the first two + * elements to be discarded, leaving 3,4 in the array. Throws illegalArgumentException if i + * exceeds numElements. + * + * @param i the number of elements to discard from the front of the array + * @throws MathIllegalArgumentException if i is greater than numElements. + * @since 2.0 + */ + public synchronized void discardFrontElements(int i) throws MathIllegalArgumentException { + discardExtremeElements(i, true); + } + + /** + * Discards the <code>i</code> last elements of the array. For example, if the array contains + * the elements 1,2,3,4, invoking <code>discardMostRecentElements(2)</code> will cause the last + * two elements to be discarded, leaving 1,2 in the array. Throws illegalArgumentException if i + * exceeds numElements. + * + * @param i the number of elements to discard from the end of the array + * @throws MathIllegalArgumentException if i is greater than numElements. + * @since 2.0 + */ + public synchronized void discardMostRecentElements(int i) throws MathIllegalArgumentException { + discardExtremeElements(i, false); + } + + /** + * Discards the <code>i</code> first or last elements of the array, depending on the value of + * <code>front</code>. For example, if the array contains the elements 1,2,3,4, invoking <code> + * discardExtremeElements(2,false)</code> will cause the last two elements to be discarded, + * leaving 1,2 in the array. For example, if the array contains the elements 1,2,3,4, invoking + * <code>discardExtremeElements(2,true)</code> will cause the first two elements to be + * discarded, leaving 3,4 in the array. Throws illegalArgumentException if i exceeds + * numElements. + * + * @param i the number of elements to discard from the front/end of the array + * @param front true if elements are to be discarded from the front of the array, false if + * elements are to be discarded from the end of the array + * @throws MathIllegalArgumentException if i is greater than numElements. + * @since 2.0 + */ + private synchronized void discardExtremeElements(int i, boolean front) + throws MathIllegalArgumentException { + if (i > numElements) { + throw new MathIllegalArgumentException( + LocalizedFormats.TOO_MANY_ELEMENTS_TO_DISCARD_FROM_ARRAY, i, numElements); + } else if (i < 0) { + throw new MathIllegalArgumentException( + LocalizedFormats.CANNOT_DISCARD_NEGATIVE_NUMBER_OF_ELEMENTS, i); + } else { + // "Subtract" this number of discarded from numElements + numElements -= i; + if (front) { + startIndex += i; + } + } + if (shouldContract()) { + contract(); + } + } + + /** + * Expands the internal storage array using the expansion factor. + * + * <p>if <code>expansionMode</code> is set to MULTIPLICATIVE_MODE, the new array size will be + * <code>internalArray.length * expansionFactor.</code> If <code>expansionMode</code> is set to + * ADDITIVE_MODE, the length after expansion will be <code> + * internalArray.length + expansionFactor</code> + */ + protected synchronized void expand() { + // notice the use of FastMath.ceil(), this guarantees that we will always + // have an array of at least currentSize + 1. Assume that the + // current initial capacity is 1 and the expansion factor + // is 1.000000000000000001. The newly calculated size will be + // rounded up to 2 after the multiplication is performed. + int newSize = 0; + if (expansionMode == ExpansionMode.MULTIPLICATIVE) { + newSize = (int) FastMath.ceil(internalArray.length * expansionFactor); + } else { + newSize = (int) (internalArray.length + FastMath.round(expansionFactor)); + } + final double[] tempArray = new double[newSize]; + + // Copy and swap + System.arraycopy(internalArray, 0, tempArray, 0, internalArray.length); + internalArray = tempArray; + } + + /** + * Expands the internal storage array to the specified size. + * + * @param size Size of the new internal storage array. + */ + private synchronized void expandTo(int size) { + final double[] tempArray = new double[size]; + // Copy and swap + System.arraycopy(internalArray, 0, tempArray, 0, internalArray.length); + internalArray = tempArray; + } + + /** + * The contraction criteria defines when the internal array will contract to store only the + * number of elements in the element array. If the <code>expansionMode</code> is <code> + * MULTIPLICATIVE_MODE</code>, contraction is triggered when the ratio between storage array + * length and <code>numElements</code> exceeds <code>contractionFactor</code>. If the <code> + * expansionMode</code> is <code>ADDITIVE_MODE</code>, the number of excess storage locations is + * compared to <code>contractionFactor.</code> + * + * @return the contraction criteria used to reclaim memory. + * @deprecated As of 3.1. Please use {@link #getContractionCriterion()} instead. + */ + @Deprecated + public float getContractionCriteria() { + return (float) getContractionCriterion(); + } + + /** + * The contraction criterion defines when the internal array will contract to store only the + * number of elements in the element array. If the <code>expansionMode</code> is <code> + * MULTIPLICATIVE_MODE</code>, contraction is triggered when the ratio between storage array + * length and <code>numElements</code> exceeds <code>contractionFactor</code>. If the <code> + * expansionMode</code> is <code>ADDITIVE_MODE</code>, the number of excess storage locations is + * compared to <code>contractionFactor.</code> + * + * @return the contraction criterion used to reclaim memory. + * @since 3.1 + */ + public double getContractionCriterion() { + return contractionCriterion; + } + + /** + * Returns the element at the specified index + * + * @param index index to fetch a value from + * @return value stored at the specified index + * @throws ArrayIndexOutOfBoundsException if <code>index</code> is less than zero or is greater + * than <code>getNumElements() - 1</code>. + */ + public synchronized double getElement(int index) { + if (index >= numElements) { + throw new ArrayIndexOutOfBoundsException(index); + } else if (index >= 0) { + return internalArray[startIndex + index]; + } else { + throw new ArrayIndexOutOfBoundsException(index); + } + } + + /** + * Returns a double array containing the elements of this <code>ResizableArray</code>. This + * method returns a copy, not a reference to the underlying array, so that changes made to the + * returned array have no effect on this <code>ResizableArray.</code> + * + * @return the double array. + */ + public synchronized double[] getElements() { + final double[] elementArray = new double[numElements]; + System.arraycopy(internalArray, startIndex, elementArray, 0, numElements); + return elementArray; + } + + /** + * The expansion factor controls the size of a new array when an array needs to be expanded. The + * <code>expansionMode</code> determines whether the size of the array is multiplied by the + * <code>expansionFactor</code> (MULTIPLICATIVE_MODE) or if the expansion is additive + * (ADDITIVE_MODE -- <code>expansionFactor</code> storage locations added). The default <code> + * expansionMode</code> is MULTIPLICATIVE_MODE and the default <code>expansionFactor</code> is + * 2.0. + * + * @return the expansion factor of this expandable double array + * @deprecated As of 3.1. Return type will be changed to "double" in 4.0. + */ + @Deprecated + public float getExpansionFactor() { + return (float) expansionFactor; + } + + /** + * The expansion mode determines whether the internal storage array grows additively or + * multiplicatively when it is expanded. + * + * @return the expansion mode. + * @deprecated As of 3.1. Return value to be changed to {@link ExpansionMode} in 4.0. + */ + @Deprecated + public int getExpansionMode() { + synchronized (this) { + switch (expansionMode) { + case MULTIPLICATIVE: + return MULTIPLICATIVE_MODE; + case ADDITIVE: + return ADDITIVE_MODE; + default: + throw new MathInternalError(); // Should never happen. + } + } + } + + /** + * Notice the package scope on this method. This method is simply here for the JUnit test, it + * allows us check if the expansion is working properly after a number of expansions. This is + * not meant to be a part of the public interface of this class. + * + * @return the length of the internal storage array. + * @deprecated As of 3.1. Please use {@link #getCapacity()} instead. + */ + @Deprecated + synchronized int getInternalLength() { + return internalArray.length; + } + + /** + * Gets the currently allocated size of the internal data structure used for storing elements. + * This is not to be confused with {@link #getNumElements() the number of elements actually + * stored}. + * + * @return the length of the internal array. + * @since 3.1 + */ + public int getCapacity() { + return internalArray.length; + } + + /** + * Returns the number of elements currently in the array. Please note that this is different + * from the length of the internal storage array. + * + * @return the number of elements. + */ + public synchronized int getNumElements() { + return numElements; + } + + /** + * Returns the internal storage array. Note that this method returns a reference to the internal + * storage array, not a copy, and to correctly address elements of the array, the <code> + * startIndex</code> is required (available via the {@link #start} method). This method should + * only be used in cases where copying the internal array is not practical. The {@link + * #getElements} method should be used in all other cases. + * + * @return the internal storage array used by this object + * @since 2.0 + * @deprecated As of 3.1. + */ + @Deprecated + public synchronized double[] getInternalValues() { + return internalArray; + } + + /** + * Provides <em>direct</em> access to the internal storage array. Please note that this method + * returns a reference to this object's storage array, not a copy. <br> + * To correctly address elements of the array, the "start index" is required (available via the + * {@link #getStartIndex() getStartIndex} method. <br> + * This method should only be used to avoid copying the internal array. The returned value + * <em>must</em> be used for reading only; other uses could lead to this object becoming + * inconsistent. <br> + * The {@link #getElements} method has no such limitation since it returns a copy of this + * array's addressable elements. + * + * @return the internal storage array used by this object. + * @since 3.1 + */ + protected double[] getArrayRef() { + return internalArray; + } + + /** + * Returns the "start index" of the internal array. This index is the position of the first + * addressable element in the internal storage array. The addressable elements in the array are + * at indices contained in the interval [{@link #getStartIndex()}, {@link #getStartIndex()} + + * {@link #getNumElements()} - 1]. + * + * @return the start index. + * @since 3.1 + */ + protected int getStartIndex() { + return startIndex; + } + + /** + * Sets the contraction criteria. + * + * @param contractionCriteria contraction criteria + * @throws MathIllegalArgumentException if the contractionCriteria is less than the + * expansionCriteria. + * @deprecated As of 3.1 (to be removed in 4.0 as field will become "final"). + */ + @Deprecated + public void setContractionCriteria(float contractionCriteria) + throws MathIllegalArgumentException { + checkContractExpand(contractionCriteria, getExpansionFactor()); + synchronized (this) { + this.contractionCriterion = contractionCriteria; + } + } + + /** + * Performs an operation on the addressable elements of the array. + * + * @param f Function to be applied on this array. + * @return the result. + * @since 3.1 + */ + public double compute(MathArrays.Function f) { + final double[] array; + final int start; + final int num; + synchronized (this) { + array = internalArray; + start = startIndex; + num = numElements; + } + return f.evaluate(array, start, num); + } + + /** + * Sets the element at the specified index. If the specified index is greater than <code> + * getNumElements() - 1</code>, the <code>numElements</code> property is increased to <code> + * index +1</code> and additional storage is allocated (if necessary) for the new element and + * all (uninitialized) elements between the new element and the previous end of the array). + * + * @param index index to store a value in + * @param value value to store at the specified index + * @throws ArrayIndexOutOfBoundsException if {@code index < 0}. + */ + public synchronized void setElement(int index, double value) { + if (index < 0) { + throw new ArrayIndexOutOfBoundsException(index); + } + if (index + 1 > numElements) { + numElements = index + 1; + } + if ((startIndex + index) >= internalArray.length) { + expandTo(startIndex + (index + 1)); + } + internalArray[startIndex + index] = value; + } + + /** + * Sets the expansionFactor. Throws IllegalArgumentException if the the following conditions are + * not met: + * + * <ul> + * <li><code>expansionFactor > 1</code> + * <li><code>contractionFactor >= expansionFactor</code> + * </ul> + * + * @param expansionFactor the new expansion factor value. + * @throws MathIllegalArgumentException if expansionFactor is <= 1 or greater than + * contractionFactor + * @deprecated As of 3.1 (to be removed in 4.0 as field will become "final"). + */ + @Deprecated + public void setExpansionFactor(float expansionFactor) throws MathIllegalArgumentException { + checkContractExpand(getContractionCriterion(), expansionFactor); + // The check above verifies that the expansion factor is > 1.0; + synchronized (this) { + this.expansionFactor = expansionFactor; + } + } + + /** + * Sets the <code>expansionMode</code>. The specified value must be one of ADDITIVE_MODE, + * MULTIPLICATIVE_MODE. + * + * @param expansionMode The expansionMode to set. + * @throws MathIllegalArgumentException if the specified mode value is not valid. + * @deprecated As of 3.1. Please use {@link #setExpansionMode(ExpansionMode)} instead. + */ + @Deprecated + public void setExpansionMode(int expansionMode) throws MathIllegalArgumentException { + if (expansionMode != MULTIPLICATIVE_MODE && expansionMode != ADDITIVE_MODE) { + throw new MathIllegalArgumentException( + LocalizedFormats.UNSUPPORTED_EXPANSION_MODE, + expansionMode, + MULTIPLICATIVE_MODE, + "MULTIPLICATIVE_MODE", + ADDITIVE_MODE, + "ADDITIVE_MODE"); + } + synchronized (this) { + if (expansionMode == MULTIPLICATIVE_MODE) { + setExpansionMode(ExpansionMode.MULTIPLICATIVE); + } else if (expansionMode == ADDITIVE_MODE) { + setExpansionMode(ExpansionMode.ADDITIVE); + } + } + } + + /** + * Sets the {@link ExpansionMode expansion mode}. + * + * @param expansionMode Expansion mode to use for resizing the array. + * @deprecated As of 3.1 (to be removed in 4.0 as field will become "final"). + */ + @Deprecated + public void setExpansionMode(ExpansionMode expansionMode) { + synchronized (this) { + this.expansionMode = expansionMode; + } + } + + /** + * Sets the initial capacity. Should only be invoked by constructors. + * + * @param initialCapacity of the array + * @throws MathIllegalArgumentException if <code>initialCapacity</code> is not positive. + * @deprecated As of 3.1, this is a no-op. + */ + @Deprecated + protected void setInitialCapacity(int initialCapacity) throws MathIllegalArgumentException { + // Body removed in 3.1. + } + + /** + * This function allows you to control the number of elements contained in this array, and can + * be used to "throw out" the last n values in an array. This function will also expand the + * internal array as needed. + * + * @param i a new number of elements + * @throws MathIllegalArgumentException if <code>i</code> is negative. + */ + public synchronized void setNumElements(int i) throws MathIllegalArgumentException { + // If index is negative thrown an error. + if (i < 0) { + throw new MathIllegalArgumentException(LocalizedFormats.INDEX_NOT_POSITIVE, i); + } + + // Test the new num elements, check to see if the array needs to be + // expanded to accommodate this new number of elements. + final int newSize = startIndex + i; + if (newSize > internalArray.length) { + expandTo(newSize); + } + + // Set the new number of elements to new value. + numElements = i; + } + + /** + * Returns true if the internal storage array has too many unused storage positions. + * + * @return true if array satisfies the contraction criteria + */ + private synchronized boolean shouldContract() { + if (expansionMode == ExpansionMode.MULTIPLICATIVE) { + return (internalArray.length / ((float) numElements)) > contractionCriterion; + } else { + return (internalArray.length - numElements) > contractionCriterion; + } + } + + /** + * Returns the starting index of the internal array. The starting index is the position of the + * first addressable element in the internal storage array. The addressable elements in the + * array are <code> + * internalArray[startIndex],...,internalArray[startIndex + numElements -1] + * </code> + * + * @return the starting index. + * @deprecated As of 3.1. + */ + @Deprecated + public synchronized int start() { + return startIndex; + } + + /** + * Copies source to dest, copying the underlying data, so dest is a new, independent copy of + * source. Does not contract before the copy. + * + * <p>Obtains synchronization locks on both source and dest (in that order) before performing + * the copy. + * + * <p>Neither source nor dest may be null; otherwise a {@link NullArgumentException} is thrown + * + * @param source ResizableDoubleArray to copy + * @param dest ResizableArray to replace with a copy of the source array + * @exception NullArgumentException if either source or dest is null + * @since 2.0 + */ + public static void copy(ResizableDoubleArray source, ResizableDoubleArray dest) + throws NullArgumentException { + MathUtils.checkNotNull(source); + MathUtils.checkNotNull(dest); + synchronized (source) { + synchronized (dest) { + dest.contractionCriterion = source.contractionCriterion; + dest.expansionFactor = source.expansionFactor; + dest.expansionMode = source.expansionMode; + dest.internalArray = new double[source.internalArray.length]; + System.arraycopy( + source.internalArray, 0, dest.internalArray, 0, dest.internalArray.length); + dest.numElements = source.numElements; + dest.startIndex = source.startIndex; + } + } + } + + /** + * Returns a copy of the ResizableDoubleArray. Does not contract before the copy, so the + * returned object is an exact copy of this. + * + * @return a new ResizableDoubleArray with the same data and configuration properties as this + * @since 2.0 + */ + public synchronized ResizableDoubleArray copy() { + final ResizableDoubleArray result = new ResizableDoubleArray(); + copy(this, result); + return result; + } + + /** + * Returns true iff object is a ResizableDoubleArray with the same properties as this and an + * identical internal storage array. + * + * @param object object to be compared for equality with this + * @return true iff object is a ResizableDoubleArray with the same data and properties as this + * @since 2.0 + */ + @Override + public boolean equals(Object object) { + if (object == this) { + return true; + } + if (object instanceof ResizableDoubleArray == false) { + return false; + } + synchronized (this) { + synchronized (object) { + boolean result = true; + final ResizableDoubleArray other = (ResizableDoubleArray) object; + result = result && (other.contractionCriterion == contractionCriterion); + result = result && (other.expansionFactor == expansionFactor); + result = result && (other.expansionMode == expansionMode); + result = result && (other.numElements == numElements); + result = result && (other.startIndex == startIndex); + if (!result) { + return false; + } else { + return Arrays.equals(internalArray, other.internalArray); + } + } + } + } + + /** + * Returns a hash code consistent with equals. + * + * @return the hash code representing this {@code ResizableDoubleArray}. + * @since 2.0 + */ + @Override + public synchronized int hashCode() { + final int[] hashData = new int[6]; + hashData[0] = Double.valueOf(expansionFactor).hashCode(); + hashData[1] = Double.valueOf(contractionCriterion).hashCode(); + hashData[2] = expansionMode.hashCode(); + hashData[3] = Arrays.hashCode(internalArray); + hashData[4] = numElements; + hashData[5] = startIndex; + return Arrays.hashCode(hashData); + } +} diff --git a/src/main/java/org/apache/commons/math3/util/TransformerMap.java b/src/main/java/org/apache/commons/math3/util/TransformerMap.java new file mode 100644 index 0000000..404f7db --- /dev/null +++ b/src/main/java/org/apache/commons/math3/util/TransformerMap.java @@ -0,0 +1,182 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math3.util; + +import org.apache.commons.math3.exception.MathIllegalArgumentException; + +import java.io.Serializable; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/** + * This TansformerMap automates the transformation of mixed object types. It provides a means to set + * NumberTransformers that will be selected based on the Class of the object handed to the Maps + * <code>double transform(Object o)</code> method. + */ +public class TransformerMap implements NumberTransformer, Serializable { + + /** Serializable version identifier */ + private static final long serialVersionUID = 4605318041528645258L; + + /** A default Number Transformer for Numbers and numeric Strings. */ + private NumberTransformer defaultTransformer = null; + + /** The internal Map. */ + private Map<Class<?>, NumberTransformer> map = null; + + /** Build a map containing only the default transformer. */ + public TransformerMap() { + map = new HashMap<Class<?>, NumberTransformer>(); + defaultTransformer = new DefaultTransformer(); + } + + /** + * Tests if a Class is present in the TransformerMap. + * + * @param key Class to check + * @return true|false + */ + public boolean containsClass(Class<?> key) { + return map.containsKey(key); + } + + /** + * Tests if a NumberTransformer is present in the TransformerMap. + * + * @param value NumberTransformer to check + * @return true|false + */ + public boolean containsTransformer(NumberTransformer value) { + return map.containsValue(value); + } + + /** + * Returns the Transformer that is mapped to a class if mapping is not present, this returns + * null. + * + * @param key The Class of the object + * @return the mapped NumberTransformer or null. + */ + public NumberTransformer getTransformer(Class<?> key) { + return map.get(key); + } + + /** + * Sets a Class to Transformer Mapping in the Map. If the Class is already present, this + * overwrites that mapping. + * + * @param key The Class + * @param transformer The NumberTransformer + * @return the replaced transformer if one is present + */ + public NumberTransformer putTransformer(Class<?> key, NumberTransformer transformer) { + return map.put(key, transformer); + } + + /** + * Removes a Class to Transformer Mapping in the Map. + * + * @param key The Class + * @return the removed transformer if one is present or null if none was present. + */ + public NumberTransformer removeTransformer(Class<?> key) { + return map.remove(key); + } + + /** Clears all the Class to Transformer mappings. */ + public void clear() { + map.clear(); + } + + /** + * Returns the Set of Classes used as keys in the map. + * + * @return Set of Classes + */ + public Set<Class<?>> classes() { + return map.keySet(); + } + + /** + * Returns the Set of NumberTransformers used as values in the map. + * + * @return Set of NumberTransformers + */ + public Collection<NumberTransformer> transformers() { + return map.values(); + } + + /** + * Attempts to transform the Object against the map of NumberTransformers. Otherwise it returns + * Double.NaN. + * + * @param o the Object to be transformed. + * @return the double value of the Object. + * @throws MathIllegalArgumentException if the Object can not be transformed into a Double. + * @see org.apache.commons.math3.util.NumberTransformer#transform(java.lang.Object) + */ + public double transform(Object o) throws MathIllegalArgumentException { + double value = Double.NaN; + + if (o instanceof Number || o instanceof String) { + value = defaultTransformer.transform(o); + } else { + NumberTransformer trans = getTransformer(o.getClass()); + if (trans != null) { + value = trans.transform(o); + } + } + + return value; + } + + /** {@inheritDoc} */ + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + if (other instanceof TransformerMap) { + TransformerMap rhs = (TransformerMap) other; + if (!defaultTransformer.equals(rhs.defaultTransformer)) { + return false; + } + if (map.size() != rhs.map.size()) { + return false; + } + for (Map.Entry<Class<?>, NumberTransformer> entry : map.entrySet()) { + if (!entry.getValue().equals(rhs.map.get(entry.getKey()))) { + return false; + } + } + return true; + } + return false; + } + + /** {@inheritDoc} */ + @Override + public int hashCode() { + int hash = defaultTransformer.hashCode(); + for (NumberTransformer t : map.values()) { + hash = hash * 31 + t.hashCode(); + } + return hash; + } +} diff --git a/src/main/java/org/apache/commons/math3/util/package-info.java b/src/main/java/org/apache/commons/math3/util/package-info.java new file mode 100644 index 0000000..e2e6451 --- /dev/null +++ b/src/main/java/org/apache/commons/math3/util/package-info.java @@ -0,0 +1,18 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** Convenience routines and common data structures used throughout the commons-math library. */ +package org.apache.commons.math3.util; |