Repository: commons-math Updated Branches: refs/heads/master 809f0f89c -> 540aa2e7e
Added Bessel functions of the first kind, based on NetLib implementation. JIRA: MATH-1066 Based on patch provided by Brian Wignall Project: http://git-wip-us.apache.org/repos/asf/commons-math/repo Commit: http://git-wip-us.apache.org/repos/asf/commons-math/commit/f80f5777 Tree: http://git-wip-us.apache.org/repos/asf/commons-math/tree/f80f5777 Diff: http://git-wip-us.apache.org/repos/asf/commons-math/diff/f80f5777 Branch: refs/heads/master Commit: f80f577748c0dbde45d24654247a82a7121d456c Parents: 59fe593 Author: Phil Steitz <phil.ste...@gmail.com> Authored: Mon Dec 15 13:48:07 2014 -0700 Committer: Phil Steitz <phil.ste...@gmail.com> Committed: Mon Dec 15 13:48:07 2014 -0700 ---------------------------------------------------------------------- findbugs-exclude-filter.xml | 7 + src/changes/changes.xml | 3 + .../apache/commons/math3/special/BesselJ.java | 649 ++++++++++++++++ .../commons/math3/special/BesselJTest.java | 777 +++++++++++++++++++ 4 files changed, 1436 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/commons-math/blob/f80f5777/findbugs-exclude-filter.xml ---------------------------------------------------------------------- diff --git a/findbugs-exclude-filter.xml b/findbugs-exclude-filter.xml index 3745c29..b971772 100644 --- a/findbugs-exclude-filter.xml +++ b/findbugs-exclude-filter.xml @@ -374,5 +374,12 @@ <Method name="createLinks" /> <Bug pattern="SF_SWITCH_FALLTHROUGH" /> </Match> + + <!-- Integer division results cast to double are intentional. --> + <Match> + <Class name="org.apache.commons.math3.special.BesselJ" /> + <Method name="rjBesl" /> + <Bug pattern="ICAST_IDIV_CAST_TO_DOUBLE" /> + </Match> </FindBugsFilter> http://git-wip-us.apache.org/repos/asf/commons-math/blob/f80f5777/src/changes/changes.xml ---------------------------------------------------------------------- diff --git a/src/changes/changes.xml b/src/changes/changes.xml index d9d8cf5..ba61bb4 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -79,6 +79,9 @@ Users are encouraged to upgrade to this version as this release not 2. A few methods in the FastMath class are in fact slower that their counterpart in either Math or StrictMath (cf. MATH-740 and MATH-901). "> + <action dev="psteitz" type="add" issue="MATH-1066" due-to="Brian Wignall"> + Added Bessel functions of the first kind, based on NetLib implementation. + </action> <action dev="tn" type="fix" issue="MATH-1142" due-to="Arne Schwarz"> Improve performance of kalman gain calculation in "KalmanFilter" by directly solving a linear system rather than computing the matrix http://git-wip-us.apache.org/repos/asf/commons-math/blob/f80f5777/src/main/java/org/apache/commons/math3/special/BesselJ.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math3/special/BesselJ.java b/src/main/java/org/apache/commons/math3/special/BesselJ.java new file mode 100644 index 0000000..7cacc2f --- /dev/null +++ b/src/main/java/org/apache/commons/math3/special/BesselJ.java @@ -0,0 +1,649 @@ +/* + * 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.special; + +import java.util.Arrays; + +import org.apache.commons.math3.analysis.UnivariateFunction; +import org.apache.commons.math3.exception.ConvergenceException; +import org.apache.commons.math3.exception.MathIllegalArgumentException; +import org.apache.commons.math3.exception.util.LocalizedFormats; +import org.apache.commons.math3.special.Gamma; +import org.apache.commons.math3.util.FastMath; + +/** + * This class provides computation methods related to Bessel + * functions of the first kind. Detailed descriptions of these functions are + * available in <a + * href="http://en.wikipedia.org/wiki/Bessel_function">Wikipedia</a>, <a + * href="http://en.wikipedia.org/wiki/Abramowitz_and_Stegun">Abrabowitz and + * Stegun</a> (Ch. 9-11), and <a href="http://dlmf.nist.gov/">DLMF</a> (Ch. 10). + * <p> + * This implementation is based on the rjbesl Fortran routine at + * <a href="http://www.netlib.org/specfun/rjbesl">Netlib</a>.</p> + * <p> + * From the Fortran code: </p> + * <p> + * This program is based on a program written by David J. Sookne (2) that + * computes values of the Bessel functions J or I of real argument and integer + * order. Modifications include the restriction of the computation to the J + * Bessel function of non-negative real argument, the extension of the + * computation to arbitrary positive order, and the elimination of most + * underflow.</p> + * <p> + * References:</p> + * <ul> + * <li>"A Note on Backward Recurrence Algorithms," Olver, F. W. J., and Sookne, + * D. J., Math. Comp. 26, 1972, pp 941-947.</li> + * <li>"Bessel Functions of Real Argument and Integer Order," Sookne, D. J., NBS + * Jour. of Res. B. 77B, 1973, pp 125-132.</li> + * </ul> </p> + */ +public class BesselJ + implements UnivariateFunction { + + // --------------------------------------------------------------------- + // Mathematical constants + // --------------------------------------------------------------------- + + /** -2 / pi */ + private static final double PI2 = 0.636619772367581343075535; + + /** first few significant digits of 2pi */ + private static final double TOWPI1 = 6.28125; + + /** 2pi - TWOPI1 to working precision */ + private static final double TWOPI2 = 1.935307179586476925286767e-3; + + /** TOWPI1 + TWOPI2 */ + private static final double TWOPI = TOWPI1 + TWOPI2; + + // --------------------------------------------------------------------- + // Machine-dependent parameters + // --------------------------------------------------------------------- + + /** + * 10.0^K, where K is the largest integer such that ENTEN is + * machine-representable in working precision + */ + private static final double ENTEN = 1.0e308; + + /** + * Decimal significance desired. Should be set to (INT(log_{10}(2) * (it)+1)). + * Setting NSIG lower will result in decreased accuracy while setting + * NSIG higher will increase CPU time without increasing accuracy. + * The truncation error is limited to a relative error of + * T=.5(10^(-NSIG)). + */ + private static final double ENSIG = 1.0e16; + + /** 10.0 ** (-K) for the smallest integer K such that K >= NSIG/4 */ + private static final double RTNSIG = 1.0e-4; + + /** Smallest ABS(X) such that X/4 does not underflow */ + private static final double ENMTEN = 8.90e-308; + + /** Minimum acceptable value for x */ + private static final double X_MIN = 0.0; + + /** + * Upper limit on the magnitude of x. If abs(x) = n, then at least + * n iterations of the backward recursion will be executed. The value of + * 10.0 ** 4 is used on every machine. + */ + private static final double X_MAX = 1.0e4; + + /** First 25 factorials as doubles */ + private static final double[] FACT = { + 1.0, 1.0, 2.0, 6.0, 24.0, 120.0, 720.0, 5040.0, 40320.0, 362880.0, + 3628800.0, 39916800.0, 479001600.0, 6227020800.0, 87178291200.0, + 1.307674368e12, 2.0922789888e13, 3.55687428096e14, 6.402373705728e15, + 1.21645100408832e17, 2.43290200817664e18, 5.109094217170944e19, + 1.12400072777760768e21, 2.585201673888497664e22, + 6.2044840173323943936e23 + }; + + /** Order of the function computed when {@link #value(double)} is used */ + private final double order; + + /** + * Create a new BesselJ with the given order. + * + * @param order order of the function computed when using {@link #value(double)}. + */ + public BesselJ(double order) { + this.order = order; + } + + /** + * Returns the value of the constructed Bessel function of the first kind, + * for the passed argument. + * + * @param x Argument + * @return Value of the Bessel function at x + * @throws MathIllegalArgumentException if {@code x} is too large relative to {@code order} + * @throws ConvergenceException if the algorithm fails to converge + */ + public double value(double x) + throws MathIllegalArgumentException, ConvergenceException { + return BesselJ.value(order, x); + } + + /** + * Returns the first Bessel function, \(J_{order}(x)\). + * + * @param order Order of the Bessel function + * @param x Argument + * @return Value of the Bessel function of the first kind, \(J_{order}(x)\) + * @throws MathIllegalArgumentException if {@code x} is too large relative to {@code order} + * @throws ConvergenceException if the algorithm fails to converge + */ + public static double value(double order, double x) + throws MathIllegalArgumentException, ConvergenceException { + final int n = (int) order; + final double alpha = order - n; + final int nb = n + 1; + final BesselJResult res = rjBesl(x, alpha, nb); + + if (res.nVals >= nb) { + return res.vals[n]; + } else if (res.nVals < 0) { + throw new MathIllegalArgumentException(LocalizedFormats.BESSEL_FUNCTION_BAD_ARGUMENT,order, x); + } else if (FastMath.abs(res.vals[res.nVals - 1]) < 1e-100) { + return res.vals[n]; // underflow; return value (will be zero) + } + throw new ConvergenceException(LocalizedFormats.BESSEL_FUNCTION_FAILED_CONVERGENCE, order, x); + } + + /** + * Encapsulates the results returned by {@link BesselJ#rjBesl(double, double, int)}. + * <p> + * {@link #getVals()} returns the computed function values. + * {@link #getnVals()} is the number of values among those returned by {@link #getnVals()} + * that can be considered accurate. + * </p><p> + * <ul> + * <li>nVals < 0: An argument is out of range. For example, nb <= 0, alpha + * < 0 or > 1, or x is too large. In this case, b(0) is set to zero, the + * remainder of the b-vector is not calculated, and nVals is set to + * MIN(nb,0) - 1 so that nVals != nb.</li> + * <li>nb > nVals > 0: Not all requested function values could be calculated + * accurately. This usually occurs because nb is much larger than abs(x). In + * this case, b(n) is calculated to the desired accuracy for n < nVals, but + * precision is lost for nVals < n <= nb. If b(n) does not vanish for n > + * nVals (because it is too small to be represented), and b(n)/b(nVals) = + * \(10^{-k}\), then only the first NSIG-k significant figures of b(n) can be + * trusted.</li></ul></p> + */ + public static class BesselJResult { + + /** Bessel function values */ + private final double[] vals; + + /** Valid value count */ + private final int nVals; + + /** + * Create a new BesselJResult with the given values and valid value count. + * + * @param b values + * @param n count of valid values + */ + public BesselJResult(double[] b, int n) { + vals = Arrays.copyOf(b, b.length); + nVals = n; + } + + /** + * @return the computed function values + */ + public double[] getVals() { + return Arrays.copyOf(vals, vals.length); + } + + /** + * @return the number of valid function values (normally the same as the + * length of the array returned by {@link #getnVals()}) + */ + public int getnVals() { + return nVals; + } + } + + /** + * Calculates Bessel functions \(J_{n+alpha}(x)\) for + * non-negative argument x, and non-negative order n + alpha. + * <p> + * Before using the output vector, the user should check that + * nVals = nb, i.e., all orders have been calculated to the desired accuracy. + * See BesselResult class javadoc for details on return values. + * </p> + * @param x non-negative real argument for which J's are to be calculated + * @param alpha fractional part of order for which J's or exponentially + * scaled J's (\(J\cdot e^{x}\)) are to be calculated. 0 <= alpha < 1.0. + * @param nb integer number of functions to be calculated, nb > 0. The first + * function calculated is of order alpha, and the last is of order + * nb - 1 + alpha. + * @return BesselJResult a vector of the functions + * \(J_{alpha}(x)\) through \(J_{nb-1+alpha}(x)\), or the corresponding exponentially + * scaled functions and an integer output variable indicating possible errors + */ + public static BesselJResult rjBesl(double x, double alpha, int nb) { + final double[] b = new double[nb]; + + int ncalc = 0; + double alpem = 0; + double alp2em = 0; + + // --------------------------------------------------------------------- + // Check for out of range arguments. + // --------------------------------------------------------------------- + final int magx = (int) x; + if ((nb > 0) && (x >= X_MIN) && (x <= X_MAX) && (alpha >= 0) && + (alpha < 1)) { + // --------------------------------------------------------------------- + // Initialize result array to zero. + // --------------------------------------------------------------------- + ncalc = nb; + for (int i = 0; i < nb; ++i) { + b[i] = 0; + } + + // --------------------------------------------------------------------- + // Branch to use 2-term ascending series for small X and asymptotic + // form for large X when NB is not too large. + // --------------------------------------------------------------------- + double tempa; + double tempb; + double tempc; + double tover; + if (x < RTNSIG) { + // --------------------------------------------------------------------- + // Two-term ascending series for small X. + // --------------------------------------------------------------------- + tempa = 1; + alpem = 1 + alpha; + double halfx = 0; + if (x > ENMTEN) { + halfx = 0.5 * x; + } + if (alpha != 0) { + tempa = FastMath.pow(halfx, alpha) / + (alpha * Gamma.gamma(alpha)); + } + tempb = 0; + if (x + 1 > 1) { + tempb = -halfx * halfx; + } + b[0] = tempa + (tempa * tempb / alpem); + if ((x != 0) && (b[0] == 0)) { + ncalc = 0; + } + if (nb != 1) { + if (x <= 0) { + for (int n = 1; n < nb; ++n) { + b[n] = 0; + } + } else { + // --------------------------------------------------------------------- + // Calculate higher order functions. + // --------------------------------------------------------------------- + tempc = halfx; + tover = tempb != 0 ? ENMTEN / tempb : 2 * ENMTEN / x; + for (int n = 1; n < nb; ++n) { + tempa /= alpem; + alpem += 1; + tempa *= tempc; + if (tempa <= tover * alpem) { + tempa = 0; + } + b[n] = tempa + (tempa * tempb / alpem); + if ((b[n] == 0) && (ncalc > n)) { + ncalc = n; + } + } + } + } + } else if ((x > 25.0) && (nb <= magx + 1)) { + // --------------------------------------------------------------------- + // Asymptotic series for X > 25 + // --------------------------------------------------------------------- + final double xc = FastMath.sqrt(PI2 / x); + final double mul = 0.125 / x; + final double xin = mul * mul; + int m = 0; + if (x >= 130.0) { + m = 4; + } else if (x >= 35.0) { + m = 8; + } else { + m = 11; + } + + final double xm = 4.0 * m; + // --------------------------------------------------------------------- + // Argument reduction for SIN and COS routines. + // --------------------------------------------------------------------- + double t = (double) ((int) ((x / TWOPI) + 0.5)); + final double z = x - t * TOWPI1 - t * TWOPI2 - (alpha + 0.5) / PI2; + double vsin = FastMath.sin(z); + double vcos = FastMath.cos(z); + double gnu = 2 * alpha; + double capq; + double capp; + double s; + double t1; + double xk; + for (int i = 1; i <= 2; i++) { + s = (xm - 1 - gnu) * (xm - 1 + gnu) * xin * 0.5; + t = (gnu - (xm - 3.0)) * (gnu + (xm - 3.0)); + capp = (s * t) / FACT[2 * m]; + t1 = (gnu - (xm + 1)) * (gnu + (xm + 1)); + capq = (s * t1) / FACT[2 * m + 1]; + xk = xm; + int k = 2 * m; + t1 = t; + + for (int j = 2; j <= m; j++) { + xk -= 4.0; + s = (xk - 1 - gnu) * (xk - 1 + gnu); + t = (gnu - (xk - 3.0)) * (gnu + (xk - 3.0)); + capp = (capp + 1 / FACT[k - 2]) * s * t * xin; + capq = (capq + 1 / FACT[k - 1]) * s * t1 * xin; + k -= 2; + t1 = t; + } + + capp += 1; + capq = (capq + 1) * ((gnu * gnu) - 1) * (0.125 / x); + b[i - 1] = xc * (capp * vcos - capq * vsin); + if (nb == 1) { + return new BesselJResult(Arrays.copyOf(b, b.length), + ncalc); + } + t = vsin; + vsin = -vcos; + vcos = t; + gnu += 2.0; + } + + // --------------------------------------------------------------------- + // If NB > 2, compute J(X,ORDER+I) I = 2, NB-1 + // --------------------------------------------------------------------- + if (nb > 2) { + gnu = 2 * alpha + 2.0; + for (int j = 2; j < nb; ++j) { + b[j] = gnu * b[j - 1] / x - b[j - 2]; + gnu += 2.0; + } + } + } else { + // --------------------------------------------------------------------- + // Use recurrence to generate results. First initialize the + // calculation of P*S. + // --------------------------------------------------------------------- + final int nbmx = nb - magx; + int n = magx + 1; + int nstart = 0; + int nend = 0; + double en = 2 * (n + alpha); + double plast = 1; + double p = en / x; + double pold; + // --------------------------------------------------------------------- + // Calculate general significance test. + // --------------------------------------------------------------------- + double test = 2 * ENSIG; + boolean readyToInitialize = false; + if (nbmx >= 3) { + // --------------------------------------------------------------------- + // Calculate P*S until N = NB-1. Check for possible + // overflow. + // --------------------------------------------------------------------- + tover = ENTEN / ENSIG; + nstart = magx + 2; + nend = nb - 1; + en = 2 * (nstart - 1 + alpha); + double psave; + double psavel; + for (int k = nstart; k <= nend; k++) { + n = k; + en += 2.0; + pold = plast; + plast = p; + p = (en * plast / x) - pold; + if (p > tover) { + // --------------------------------------------------------------------- + // To avoid overflow, divide P*S by TOVER. Calculate + // P*S until + // ABS(P) > 1. + // --------------------------------------------------------------------- + tover = ENTEN; + p /= tover; + plast /= tover; + psave = p; + psavel = plast; + nstart = n + 1; + do { + n += 1; + en += 2.0; + pold = plast; + plast = p; + p = (en * plast / x) - pold; + } while (p <= 1); + tempb = en / x; + // --------------------------------------------------------------------- + // Calculate backward test and find NCALC, the + // highest N such that + // the test is passed. + // --------------------------------------------------------------------- + test = pold * plast * (0.5 - 0.5 / (tempb * tempb)); + test /= ENSIG; + p = plast * tover; + n -= 1; + en -= 2.0; + nend = FastMath.min(nb, n); + for (int l = nstart; l <= nend; l++) { + pold = psavel; + psavel = psave; + psave = (en * psavel / x) - pold; + if (psave * psavel > test) { + ncalc = l - 1; + readyToInitialize = true; + break; + } + } + ncalc = nend; + readyToInitialize = true; + break; + } + } + if (!readyToInitialize) { + n = nend; + en = 2 * (n + alpha); + // --------------------------------------------------------------------- + // Calculate special significance test for NBMX > 2. + // --------------------------------------------------------------------- + test = FastMath.max(test, FastMath.sqrt(plast * ENSIG) * + FastMath.sqrt(2 * p)); + } + } + // --------------------------------------------------------------------- + // Calculate P*S until significance test passes. + // --------------------------------------------------------------------- + if (!readyToInitialize) { + do { + n += 1; + en += 2.0; + pold = plast; + plast = p; + p = (en * plast / x) - pold; + } while (p < test); + } + // --------------------------------------------------------------------- + // Initialize the backward recursion and the normalization sum. + // --------------------------------------------------------------------- + n += 1; + en += 2.0; + tempb = 0; + tempa = 1 / p; + int m = (2 * n) - 4 * (n / 2); + double sum = 0; + double em = (double) (n / 2); + alpem = em - 1 + alpha; + alp2em = 2 * em + alpha; + if (m != 0) { + sum = tempa * alpem * alp2em / em; + } + nend = n - nb; + + boolean readyToNormalize = false; + boolean calculatedB0 = false; + + // --------------------------------------------------------------------- + // Recur backward via difference equation, calculating (but not + // storing) B(N), until N = NB. + // --------------------------------------------------------------------- + for (int l = 1; l <= nend; l++) { + n -= 1; + en -= 2.0; + tempc = tempb; + tempb = tempa; + tempa = (en * tempb / x) - tempc; + m = 2 - m; + if (m != 0) { + em -= 1; + alp2em = 2 * em + alpha; + if (n == 1) { + break; + } + alpem = em - 1 + alpha; + if (alpem == 0) { + alpem = 1; + } + sum = (sum + tempa * alp2em) * alpem / em; + } + } + + // --------------------------------------------------------------------- + // Store B(NB). + // --------------------------------------------------------------------- + b[n - 1] = tempa; + if (nend >= 0) { + if (nb <= 1) { + alp2em = alpha; + if (alpha + 1 == 1) { + alp2em = 1; + } + sum += b[0] * alp2em; + readyToNormalize = true; + } else { + // --------------------------------------------------------------------- + // Calculate and store B(NB-1). + // --------------------------------------------------------------------- + n -= 1; + en -= 2.0; + b[n - 1] = (en * tempa / x) - tempb; + if (n == 1) { + calculatedB0 = true; + } else { + m = 2 - m; + if (m != 0) { + em -= 1; + alp2em = 2 * em + alpha; + alpem = em - 1 + alpha; + if (alpem == 0) { + alpem = 1; + } + + sum = (sum + (b[n - 1] * alp2em)) * alpem / em; + } + } + } + } + if (!readyToNormalize && !calculatedB0) { + nend = n - 2; + if (nend != 0) { + // --------------------------------------------------------------------- + // Calculate via difference equation and store B(N), + // until N = 2. + // --------------------------------------------------------------------- + + for (int l = 1; l <= nend; l++) { + n -= 1; + en -= 2.0; + b[n - 1] = (en * b[n] / x) - b[n + 1]; + m = 2 - m; + if (m != 0) { + em -= 1; + alp2em = 2 * em + alpha; + alpem = em - 1 + alpha; + if (alpem == 0) { + alpem = 1; + } + + sum = (sum + b[n - 1] * alp2em) * alpem / em; + } + } + } + } + // --------------------------------------------------------------------- + // Calculate b[0] + // --------------------------------------------------------------------- + if (!readyToNormalize) { + if (!calculatedB0) { + b[0] = 2.0 * (alpha + 1) * b[1] / x - b[2]; + } + em -= 1; + alp2em = 2 * em + alpha; + if (alp2em == 0) { + alp2em = 1; + } + sum += b[0] * alp2em; + } + // --------------------------------------------------------------------- + // Normalize. Divide all B(N) by sum. + // --------------------------------------------------------------------- + + if (FastMath.abs(alpha) > 1e-16) { + sum *= Gamma.gamma(alpha) * FastMath.pow(x * 0.5, -alpha); + } + tempa = ENMTEN; + if (sum > 1) { + tempa *= sum; + } + + for (n = 0; n < nb; n++) { + if (FastMath.abs(b[n]) < tempa) { + b[n] = 0; + } + b[n] /= sum; + } + } + // --------------------------------------------------------------------- + // Error return -- X, NB, or ALPHA is out of range. + // --------------------------------------------------------------------- + } else { + if (b.length > 0) { + b[0] = 0; + } + ncalc = FastMath.min(nb, 0) - 1; + } + return new BesselJResult(Arrays.copyOf(b, b.length), ncalc); + } +} http://git-wip-us.apache.org/repos/asf/commons-math/blob/f80f5777/src/test/java/org/apache/commons/math3/special/BesselJTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/commons/math3/special/BesselJTest.java b/src/test/java/org/apache/commons/math3/special/BesselJTest.java new file mode 100644 index 0000000..b49fd60 --- /dev/null +++ b/src/test/java/org/apache/commons/math3/special/BesselJTest.java @@ -0,0 +1,777 @@ +/* + * 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.special; + +import org.apache.commons.math3.exception.ConvergenceException; +import org.apache.commons.math3.exception.MathIllegalArgumentException; +import org.junit.Assert; +import org.junit.Test; + +/** + * @version $Id$ + */ +public class BesselJTest { + + /** + * Reference data for the {@link BesselJ#value(double, double)} function. This data + * was generated with the following <a href="http://www.r-project.org/">R</a> script. + * + * <pre> + * smallxs = 10 ** (-(seq(0,8,.5))) + * medxs = seq(1,20) + * near.eight = 8 + seq(-.5,.5,.1) + * largexs = c(10,30,100,300,1000) + * xs = unique(sort(c(smallxs, medxs, near.eight,largexs))) + * + * for (n in c(0:15, 30, 100)) { + * for (x in xs) { + * val = format( besselJ(x,n), digits=20 ) + * s = paste("{", n, ",", x, ",", val, "},") + * print(s) + * } + * } + * </pre> + */ + private static final double[][] BESSEL_J_REF = { + { 0 , 1e-08 , 1 }, + { 0 , 3.16227766016838e-08 , 0.99999999999999977796 }, + { 0 , 1e-07 , 0.99999999999999744649 }, + { 0 , 3.16227766016838e-07 , 0.99999999999997501998 }, + { 0 , 1e-06 , 0.99999999999974997777 }, + { 0 , 3.16227766016838e-06 , 0.99999999999749999979 }, + { 0 , 1e-05 , 0.99999999997499999793 }, + { 0 , 3.16227766016838e-05 , 0.99999999974999997931 }, + { 0 , 1e-04 , 0.99999999750000001519 }, + { 0 , 0.000316227766016838 , 0.99999997500000015194 }, + { 0 , 0.001 , 0.9999997500000156192 }, + { 0 , 0.00316227766016838 , 0.99999750000156251151 }, + { 0 , 0.01 , 0.99997500015624951608 }, + { 0 , 0.0316227766016838 , 0.9997500156245660019 }, + { 0 , 0.1 , 0.99750156206604001508 }, + { 0 , 0.316227766016838 , 0.97515581664971295872 }, + { 0 , 1 , 0.76519768655796649437 }, + { 0 , 2 , 0.22389077914123567403 }, + { 0 , 3 , -0.26005195490193344643 }, + { 0 , 4 , -0.39714980986384734729 }, + { 0 , 5 , -0.177596771314338292 }, + { 0 , 6 , 0.15064525725099692233 }, + { 0 , 7 , 0.3000792705195556298 }, + { 0 , 7.5 , 0.26633965788037838873 }, + { 0 , 7.6 , 0.25160183384997636402 }, + { 0 , 7.7 , 0.23455913958646437689 }, + { 0 , 7.8 , 0.21540780774626291927 }, + { 0 , 7.9 , 0.19436184484127824734 }, + { 0 , 8 , 0.17165080713755390129 }, + { 0 , 8.1 , 0.14751745404437766052 }, + { 0 , 8.2 , 0.12221530178413773926 }, + { 0 , 8.3 , 0.09600610089501022959 }, + { 0 , 8.4 , 0.069157261656985186127 }, + { 0 , 8.5 , 0.041939251842934503756 }, + { 0 , 9 , -0.090333611182876139001 }, + { 0 , 10 , -0.24593576445134832098 }, + { 0 , 11 , -0.17119030040719609986 }, + { 0 , 12 , 0.0476893107968335353 }, + { 0 , 13 , 0.20692610237706782206 }, + { 0 , 14 , 0.17107347611045864433 }, + { 0 , 15 , -0.014224472826780772475 }, + { 0 , 16 , -0.17489907398362919411 }, + { 0 , 17 , -0.16985425215118354902 }, + { 0 , 18 , -0.013355805721984111492 }, + { 0 , 19 , 0.14662943965965119508 }, + { 0 , 20 , 0.16702466434058313438 }, + { 0 , 30 , -0.086367983581040239094 }, + { 0 , 100 , 0.019985850304223118368 }, + { 0 , 300 , -0.033298554876305661021 }, + { 0 , 1000 , 0.024786686152420175921 }, + { 1 , 1e-08 , 5.0000000000000001046e-09 }, + { 1 , 3.16227766016838e-08 , 1.5811388300841892647e-08 }, + { 1 , 1e-07 , 4.999999999999993818e-08 }, + { 1 , 3.16227766016838e-07 , 1.5811388300841697432e-07 }, + { 1 , 1e-06 , 4.9999999999993750869e-07 }, + { 1 , 3.16227766016838e-06 , 1.5811388300822132559e-06 }, + { 1 , 1e-05 , 4.9999999999375003889e-06 }, + { 1 , 3.16227766016838e-05 , 1.5811388298865475016e-05 }, + { 1 , 1e-04 , 4.9999999937500002646e-05 }, + { 1 , 0.000316227766016838 , 0.00015811388103199544184 }, + { 1 , 0.001 , 0.00049999993750000253697 }, + { 1 , 0.00316227766016838 , 0.0015811368536614756226 }, + { 1 , 0.01 , 0.0049999375002604158624 }, + { 1 , 0.0316227766016838 , 0.015809411959653556917 }, + { 1 , 0.1 , 0.049937526036241998428 }, + { 1 , 0.316227766016838 , 0.15614567743386048582 }, + { 1 , 1 , 0.44005058574493355339 }, + { 1 , 2 , 0.57672480775687340326 }, + { 1 , 3 , 0.33905895852593642692 }, + { 1 , 4 , -0.066043328023549133232 }, + { 1 , 5 , -0.32757913759146523036 }, + { 1 , 6 , -0.27668385812756562947 }, + { 1 , 7 , -0.0046828234823458325664 }, + { 1 , 7.5 , 0.13524842757970551022 }, + { 1 , 7.6 , 0.15921376839635667522 }, + { 1 , 7.7 , 0.18131271532458800855 }, + { 1 , 7.8 , 0.20135687275589611578 }, + { 1 , 7.9 , 0.21917939992175122788 }, + { 1 , 8 , 0.23463634685391462908 }, + { 1 , 8.1 , 0.2476077669815928417 }, + { 1 , 8.2 , 0.25799859764868082745 }, + { 1 , 8.3 , 0.26573930204186430037 }, + { 1 , 8.4 , 0.27078626827683538458 }, + { 1 , 8.5 , 0.27312196367405372488 }, + { 1 , 9 , 0.24531178657332528004 }, + { 1 , 10 , 0.043472746168861438332 }, + { 1 , 11 , -0.17678529895672151495 }, + { 1 , 12 , -0.2234471044906276016 }, + { 1 , 13 , -0.070318052121778371055 }, + { 1 , 14 , 0.13337515469879324126 }, + { 1 , 15 , 0.20510403861352277666 }, + { 1 , 16 , 0.090397175661304188243 }, + { 1 , 17 , -0.097668492757780639435 }, + { 1 , 18 , -0.18799488548806958521 }, + { 1 , 19 , -0.10570143114240927729 }, + { 1 , 20 , 0.066833124175850036619 }, + { 1 , 30 , -0.1187510626166229516 }, + { 1 , 100 , -0.077145352014112156258 }, + { 1 , 300 , -0.031887431377499955709 }, + { 1 , 1000 , 0.0047283119070895248195 }, + { 2 , 1e-08 , 1.2499999999999999739e-17 }, + { 2 , 3.16227766016838e-08 , 1.2499999999999998506e-16 }, + { 2 , 1e-07 , 1.2499999999999988152e-15 }, + { 2 , 3.16227766016838e-07 , 1.2499999999999894672e-14 }, + { 2 , 1e-06 , 1.249999999999895719e-13 }, + { 2 , 3.16227766016838e-06 , 1.2499999999989582746e-12 }, + { 2 , 1e-05 , 1.2499999999895835475e-11 }, + { 2 , 3.16227766016838e-05 , 1.2499999998958334818e-10 }, + { 2 , 1e-04 , 1.2499999989583335487e-09 }, + { 2 , 0.000316227766016838 , 1.2499999895833333493e-08 }, + { 2 , 0.001 , 1.2499998958333367811e-07 }, + { 2 , 0.00316227766016838 , 1.2499989583336589057e-06 }, + { 2 , 0.01 , 1.2499895833658854395e-05 }, + { 2 , 0.0316227766016838 , 0.00012498958365884872863 }, + { 2 , 0.1 , 0.0012489586587999190141 }, + { 2 , 0.316227766016838 , 0.012396158312196680837 }, + { 2 , 1 , 0.11490348493190047363 }, + { 2 , 2 , 0.35283402861563772923 }, + { 2 , 3 , 0.48609126058589108288 }, + { 2 , 4 , 0.36412814585207281537 }, + { 2 , 5 , 0.046565116277752213736 }, + { 2 , 6 , -0.24287320996018546548 }, + { 2 , 7 , -0.3014172200859401296 }, + { 2 , 7.5 , -0.23027341052579025638 }, + { 2 , 7.6 , -0.20970347374567196996 }, + { 2 , 7.7 , -0.18746492781384410664 }, + { 2 , 7.8 , -0.16377784037295622932 }, + { 2 , 7.9 , -0.13887338916488553564 }, + { 2 , 8 , -0.11299172042407523708 }, + { 2 , 8.1 , -0.086379733802009056598 }, + { 2 , 8.2 , -0.059288814552752158726 }, + { 2 , 8.3 , -0.031972534137934507936 }, + { 2 , 8.4 , -0.0046843406386910518141 }, + { 2 , 8.5 , 0.022324739609784025052 }, + { 2 , 9 , 0.14484734153250397592 }, + { 2 , 10 , 0.25463031368512062391 }, + { 2 , 11 , 0.13904751877870125121 }, + { 2 , 12 , -0.084930494878604809172 }, + { 2 , 13 , -0.21774426424195678087 }, + { 2 , 14 , -0.15201988258205964555 }, + { 2 , 15 , 0.041571677975250471981 }, + { 2 , 16 , 0.18619872094129222284 }, + { 2 , 17 , 0.15836384123850347216 }, + { 2 , 18 , -0.0075325148878013998069 }, + { 2 , 19 , -0.15775590609569428713 }, + { 2 , 20 , -0.16034135192299814321 }, + { 2 , 30 , 0.07845124607326538213 }, + { 2 , 100 , -0.021528757344505360799 }, + { 2 , 300 , 0.033085972000455661501 }, + { 2 , 1000 , -0.024777229528605997089 }, + { 3 , 1e-08 , 2.0833333333333334614e-26 }, + { 3 , 3.16227766016838e-08 , 6.5880784586841223417e-25 }, + { 3 , 1e-07 , 2.0833333333333317693e-23 }, + { 3 , 3.16227766016838e-07 , 6.5880784586840819929e-22 }, + { 3 , 1e-06 , 2.0833333333332027799e-20 }, + { 3 , 3.16227766016838e-06 , 6.5880784586800051603e-19 }, + { 3 , 1e-05 , 2.0833333333203129762e-17 }, + { 3 , 3.16227766016838e-05 , 6.5880784582723696076e-16 }, + { 3 , 1e-04 , 2.083333332031250315e-14 }, + { 3 , 0.000316227766016838 , 6.5880784175086335665e-13 }, + { 3 , 0.001 , 2.0833332031250032117e-11 }, + { 3 , 0.00316227766016838 , 6.5880743411361163135e-10 }, + { 3 , 0.01 , 2.083320312532551971e-08 }, + { 3 , 0.0316227766016838 , 6.5876667140741846331e-07 }, + { 3 , 0.1 , 2.0820315754756265453e-05 }, + { 3 , 0.316227766016838 , 0.00065470057642003857534 }, + { 3 , 1 , 0.019563353982668403586 }, + { 3 , 2 , 0.1289432494744020552 }, + { 3 , 3 , 0.30906272225525166508 }, + { 3 , 4 , 0.43017147387562193472 }, + { 3 , 5 , 0.36483123061366695694 }, + { 3 , 6 , 0.11476838482077529602 }, + { 3 , 7 , -0.16755558799533423753 }, + { 3 , 7.5 , -0.25806091319346030621 }, + { 3 , 7.6 , -0.26958401773618401176 }, + { 3 , 7.7 , -0.27869709340970183487 }, + { 3 , 7.8 , -0.28534550884459158882 }, + { 3 , 7.9 , -0.2894950400052375139 }, + { 3 , 8 , -0.29113220706595221987 }, + { 3 , 8.1 , -0.29026442564925164502 }, + { 3 , 8.2 , -0.28691997060124291297 }, + { 3 , 8.3 , -0.28114775222882071315 }, + { 3 , 8.4 , -0.27301690667621203445 }, + { 3 , 8.5 , -0.26261620385768480457 }, + { 3 , 9 , -0.1809351903366568648 }, + { 3 , 10 , 0.058379379305186815396 }, + { 3 , 11 , 0.22734803305806741691 }, + { 3 , 12 , 0.19513693953109267909 }, + { 3 , 13 , 0.0033198169704070513292 }, + { 3 , 14 , -0.17680940686509599713 }, + { 3 , 15 , -0.19401825782012263599 }, + { 3 , 16 , -0.043847495425981139472 }, + { 3 , 17 , 0.13493057304919323092 }, + { 3 , 18 , 0.18632099329078039007 }, + { 3 , 19 , 0.072489661438052577225 }, + { 3 , 20 , -0.098901394560449676363 }, + { 3 , 30 , 0.12921122875972501642 }, + { 3 , 100 , 0.076284201720331942798 }, + { 3 , 300 , 0.032328577670839367397 }, + { 3 , 1000 , -0.0048274208252039483777 }, + { 4 , 1e-08 , 2.6041666666666666342e-35 }, + { 4 , 3.16227766016838e-08 , 2.6041666666666659714e-33 }, + { 4 , 1e-07 , 2.6041666666666649861e-31 }, + { 4 , 3.16227766016838e-07 , 2.6041666666666531276e-29 }, + { 4 , 1e-06 , 2.6041666666665358894e-27 }, + { 4 , 3.16227766016838e-06 , 2.6041666666653639536e-25 }, + { 4 , 1e-05 , 2.6041666666536465525e-23 }, + { 4 , 3.16227766016838e-05 , 2.604166666536458817e-21 }, + { 4 , 1e-04 , 2.6041666653645840559e-19 }, + { 4 , 0.000316227766016838 , 2.6041666536458338462e-17 }, + { 4 , 0.001 , 2.6041665364583368871e-15 }, + { 4 , 0.00316227766016838 , 2.604165364583604802e-13 }, + { 4 , 0.01 , 2.6041536458604605458e-11 }, + { 4 , 0.0316227766016838 , 2.6040364610459735901e-09 }, + { 4 , 0.1 , 2.6028648545684040871e-07 }, + { 4 , 0.316227766016838 , 2.5911729278009268374e-05 }, + { 4 , 1 , 0.002476638964109955255 }, + { 4 , 2 , 0.033995719807568429427 }, + { 4 , 3 , 0.13203418392461221953 }, + { 4 , 4 , 0.28112906496136008672 }, + { 4 , 5 , 0.39123236045864817623 }, + { 4 , 6 , 0.35764159478096080313 }, + { 4 , 7 , 0.15779814466136793394 }, + { 4 , 7.5 , 0.02382467997102201071 }, + { 4 , 7.6 , -0.0031260139407891210546 }, + { 4 , 7.7 , -0.029701638479430046702 }, + { 4 , 7.8 , -0.055718704892114230554 }, + { 4 , 7.9 , -0.080996261472003727722 }, + { 4 , 8 , -0.10535743487538892782 }, + { 4 , 8.1 , -0.12863095186410331006 }, + { 4 , 8.2 , -0.15065262735059631316 }, + { 4 , 8.3 , -0.17126680482265874139 }, + { 4 , 8.4 , -0.19032773555860327264 }, + { 4 , 8.5 , -0.2077008835093262229 }, + { 4 , 9 , -0.26547080175694187654 }, + { 4 , 10 , -0.21960268610200855965 }, + { 4 , 11 , -0.015039500747028132846 }, + { 4 , 12 , 0.18249896464415113484 }, + { 4 , 13 , 0.21927648745906774819 }, + { 4 , 14 , 0.076244422497018474183 }, + { 4 , 15 , -0.11917898110329952499 }, + { 4 , 16 , -0.20264153172603513453 }, + { 4 , 17 , -0.11074128604467056713 }, + { 4 , 18 , 0.069639512651394869236 }, + { 4 , 19 , 0.18064737812876355272 }, + { 4 , 20 , 0.13067093355486322781 }, + { 4 , 30 , -0.05260900032132037607 }, + { 4 , 100 , 0.026105809447725277644 }, + { 4 , 300 , -0.032439400447038871378 }, + { 4 , 1000 , 0.024748265003654772859 }, + { 5 , 1e-08 , 2.6041666666666666817e-44 }, + { 5 , 3.16227766016838e-08 , 8.2350980733551520153e-42 }, + { 5 , 1e-07 , 2.6041666666666648818e-39 }, + { 5 , 3.16227766016838e-07 , 8.2350980733551185479e-37 }, + { 5 , 1e-06 , 2.6041666666665576923e-34 }, + { 5 , 3.16227766016838e-06 , 8.2350980733517218878e-32 }, + { 5 , 1e-05 , 2.6041666666558171668e-29 }, + { 5 , 3.16227766016838e-05 , 8.2350980730120282499e-27 }, + { 5 , 1e-04 , 2.6041666655815978351e-24 }, + { 5 , 0.000316227766016838 , 8.2350980390422474771e-22 }, + { 5 , 0.001 , 2.6041665581597245947e-19 }, + { 5 , 0.00316227766016838 , 8.2350946420649040367e-17 }, + { 5 , 0.01 , 2.6041558159915982186e-14 }, + { 5 , 0.0316227766016838 , 8.2347549503960048977e-12 }, + { 5 , 0.1 , 2.6030817909644421178e-09 }, + { 5 , 0.316227766016838 , 8.2008463739855235578e-07 }, + { 5 , 1 , 0.00024975773021123438876 }, + { 5 , 2 , 0.0070396297558716850601 }, + { 5 , 3 , 0.043028434877047584683 }, + { 5 , 4 , 0.13208665604709826646 }, + { 5 , 5 , 0.26114054612017006951 }, + { 5 , 6 , 0.36208707488717239986 }, + { 5 , 7 , 0.34789632475118331678 }, + { 5 , 7.5 , 0.28347390516255044357 }, + { 5 , 7.6 , 0.26629347674587972028 }, + { 5 , 7.7 , 0.2478382482362680439 }, + { 5 , 7.8 , 0.22819811921165392143 }, + { 5 , 7.9 , 0.20747350940067682545 }, + { 5 , 8 , 0.18577477219056331981 }, + { 5 , 8.1 , 0.16322151022791506203 }, + { 5 , 8.2 , 0.13994179757627084326 }, + { 5 , 8.3 , 0.11607131384553516507 }, + { 5 , 8.4 , 0.091752396620399440108 }, + { 5 , 8.5 , 0.067133019378318919967 }, + { 5 , 9 , -0.055038855669513706004 }, + { 5 , 10 , -0.23406152818679362704 }, + { 5 , 11 , -0.23828585178317879256 }, + { 5 , 12 , -0.073470963101658584571 }, + { 5 , 13 , 0.13161955992748081146 }, + { 5 , 14 , 0.22037764829196368477 }, + { 5 , 15 , 0.1304561345650295523 }, + { 5 , 16 , -0.057473270437036434732 }, + { 5 , 17 , -0.18704411942315585238 }, + { 5 , 18 , -0.15537009877904933708 }, + { 5 , 19 , 0.0035723925109004857348 }, + { 5 , 20 , 0.15116976798239498136 }, + { 5 , 30 , -0.14324029551207712041 }, + { 5 , 100 , -0.074195736964513925304 }, + { 5 , 300 , -0.03319362834942707341 }, + { 5 , 1000 , 0.0050254069452331864842 }, + { 6 , 1e-08 , 2.170138888888889163e-53 }, + { 6 , 3.16227766016838e-08 , 2.1701388888888880947e-50 }, + { 6 , 1e-07 , 2.1701388888888875174e-47 }, + { 6 , 3.16227766016838e-07 , 2.170138888888880604e-44 }, + { 6 , 1e-06 , 2.1701388888888106952e-41 }, + { 6 , 3.16227766016838e-06 , 2.1701388888881133808e-38 }, + { 6 , 1e-05 , 2.1701388888811393588e-35 }, + { 6 , 3.16227766016838e-05 , 2.1701388888113848269e-32 }, + { 6 , 1e-04 , 2.1701388881138396044e-29 }, + { 6 , 0.000316227766016838 , 2.1701388811383932341e-26 }, + { 6 , 0.001 , 2.1701388113839301844e-23 }, + { 6 , 0.00316227766016838 , 2.1701381138394068717e-20 }, + { 6 , 0.01 , 2.1701311384049674283e-17 }, + { 6 , 0.0316227766016838 , 2.1700613851395740978e-14 }, + { 6 , 0.1 , 2.1693639603760032489e-11 }, + { 6 , 0.316227766016838 , 2.1624004918010960028e-08 }, + { 6 , 1 , 2.0938338002389272967e-05 }, + { 6 , 2 , 0.0012024289717899932714 }, + { 6 , 3 , 0.011393932332213070266 }, + { 6 , 4 , 0.049087575156385579445 }, + { 6 , 5 , 0.13104873178169201831 }, + { 6 , 6 , 0.24583686336432652997 }, + { 6 , 7 , 0.33919660498317966146 }, + { 6 , 7.5 , 0.35414052691237862813 }, + { 6 , 7.6 , 0.35351216755378872536 }, + { 6 , 7.7 , 0.35156949333172621275 }, + { 6 , 7.8 , 0.3482803961891063893 }, + { 6 , 7.9 , 0.34362095691589844559 }, + { 6 , 8 , 0.33757590011359311921 }, + { 6 , 8.1 , 0.33013898918251699532 }, + { 6 , 8.2 , 0.32131335610214611931 }, + { 6 , 8.3 , 0.3111117612630625584 }, + { 6 , 8.4 , 0.29955677915431688785 }, + { 6 , 8.5 , 0.28668090630734854862 }, + { 6 , 9 , 0.20431651767970440692 }, + { 6 , 10 , -0.014458842084785107282 }, + { 6 , 11 , -0.20158400087404348966 }, + { 6 , 12 , -0.24372476722886662892 }, + { 6 , 13 , -0.1180306721302363665 }, + { 6 , 14 , 0.081168183425812737153 }, + { 6 , 15 , 0.20614973747998591169 }, + { 6 , 16 , 0.16672073770288736716 }, + { 6 , 17 , 0.00071533344281418307069 }, + { 6 , 18 , -0.15595623419531115528 }, + { 6 , 19 , -0.17876717154407903432 }, + { 6 , 20 , -0.055086049563665764883 }, + { 6 , 30 , 0.0048622351506280026001 }, + { 6 , 100 , -0.033525383144176669481 }, + { 6 , 300 , 0.031332946168724638836 }, + { 6 , 1000 , -0.024698010934202440508 }, + { 7 , 1e-08 , 1.5500992063492066701e-62 }, + { 7 , 3.16227766016838e-08 , 4.9018440912828279875e-59 }, + { 7 , 1e-07 , 1.5500992063492053031e-55 }, + { 7 , 3.16227766016838e-07 , 4.9018440912828133382e-52 }, + { 7 , 1e-06 , 1.55009920634915736e-48 }, + { 7 , 3.16227766016838e-06 , 4.9018440912812964979e-45 }, + { 7 , 1e-05 , 1.550099206344363137e-41 }, + { 7 , 3.16227766016838e-05 , 4.9018440911296494971e-38 }, + { 7 , 1e-04 , 1.5500992058648010339e-34 }, + { 7 , 0.000316227766016838 , 4.9018440759645687969e-31 }, + { 7 , 0.001 , 1.5500991579086071003e-27 }, + { 7 , 0.00316227766016838 , 4.9018425594567649302e-24 }, + { 7 , 0.01 , 1.550094362295914728e-20 }, + { 7 , 0.0316227766016838 , 4.9016909107824929132e-17 }, + { 7 , 0.1 , 1.5496148676202282287e-13 }, + { 7 , 0.316227766016838 , 4.8865470861431505644e-10 }, + { 7 , 1 , 1.5023258174368078499e-06 }, + { 7 , 2 , 0.00017494407486827416175 }, + { 7 , 3 , 0.0025472944518046929108 }, + { 7 , 4 , 0.015176069422058449318 }, + { 7 , 5 , 0.053376410155890716136 }, + { 7 , 6 , 0.12958665184148068783 }, + { 7 , 7 , 0.23358356950569605925 }, + { 7 , 7.5 , 0.28315093789725531703 }, + { 7 , 7.6 , 0.29188362991799726709 }, + { 7 , 7.7 , 0.30006226085213638655 }, + { 7 , 7.8 , 0.30761787492543296585 }, + { 7 , 7.9 , 0.31448237452220684229 }, + { 7 , 8 , 0.32058907797982633125 }, + { 7 , 8.1 , 0.3258732885609990082 }, + { 7 , 8.2 , 0.33027286989028453723 }, + { 7 , 8.3 , 0.33372882292033839713 }, + { 7 , 8.4 , 0.33618585931433897507 }, + { 7 , 8.5 , 0.33759296599676130723 }, + { 7 , 9 , 0.32746087924245292911 }, + { 7 , 10 , 0.21671091768505151842 }, + { 7 , 11 , 0.018376032647858614455 }, + { 7 , 12 , -0.17025380412720803047 }, + { 7 , 13 , -0.24057094958616048741 }, + { 7 , 14 , -0.15080491964126707671 }, + { 7 , 15 , 0.034463655418959161791 }, + { 7 , 16 , 0.18251382371420196704 }, + { 7 , 17 , 0.1875490606769070201 }, + { 7 , 18 , 0.051399275982175231248 }, + { 7 , 19 , -0.11647797453873988405 }, + { 7 , 20 , -0.18422139772059445417 }, + { 7 , 30 , 0.1451851895723283159 }, + { 7 , 100 , 0.070172690987212724134 }, + { 7 , 300 , 0.034446946196176060628 }, + { 7 , 1000 , -0.0053217830764436153956 }, + { 8 , 1e-08 , 9.6881200396825412359e-72 }, + { 8 , 3.16227766016838e-08 , 9.6881200396825359082e-68 }, + { 8 , 1e-07 , 9.6881200396825335915e-64 }, + { 8 , 3.16227766016838e-07 , 9.6881200396825091166e-60 }, + { 8 , 1e-06 , 9.6881200396822669073e-56 }, + { 8 , 3.16227766016838e-06 , 9.6881200396798449492e-52 }, + { 8 , 1e-05 , 9.6881200396556345156e-48 }, + { 8 , 3.16227766016838e-05 , 9.6881200394134308774e-44 }, + { 8 , 1e-04 , 9.6881200369913995322e-40 }, + { 8 , 0.000316227766016838 , 9.688120012771098157e-36 }, + { 8 , 0.001 , 9.6881197705681010442e-32 }, + { 8 , 0.00316227766016838 , 9.688117348538421731e-28 }, + { 8 , 0.01 , 9.6880931282716245736e-24 }, + { 8 , 0.0316227766016838 , 9.6878509286008909493e-20 }, + { 8 , 0.1 , 9.6854292315946525669e-16 }, + { 8 , 0.316227766016838 , 9.6612422089625085973e-12 }, + { 8 , 1 , 9.4223441726045005392e-08 }, + { 8 , 2 , 2.2179552287925904881e-05 }, + { 8 , 3 , 0.00049344177620883479096 }, + { 8 , 4 , 0.0040286678208190035769 }, + { 8 , 5 , 0.018405216654802002835 }, + { 8 , 6 , 0.056531990932461785582 }, + { 8 , 7 , 0.12797053402821254031 }, + { 8 , 7.5 , 0.17440789049583127479 }, + { 8 , 7.6 , 0.18416820334778524759 }, + { 8 , 7.7 , 0.19399825367215817185 }, + { 8 , 7.8 , 0.20385425111295268907 }, + { 8 , 7.9 , 0.21368958021206302389 }, + { 8 , 8 , 0.22345498635110294661 }, + { 8 , 8.1 , 0.23309879351550599758 }, + { 8 , 8.2 , 0.24256715346663235144 }, + { 8 , 8.3 , 0.25180432559052018382 }, + { 8 , 8.4 , 0.26075298636958132992 }, + { 8 , 8.5 , 0.26935456709908189854 }, + { 8 , 9 , 0.30506707225300011554 }, + { 8 , 10 , 0.31785412684385727644 }, + { 8 , 11 , 0.22497167878949989039 }, + { 8 , 12 , 0.045095329080457241533 }, + { 8 , 13 , -0.14104573511639803551 }, + { 8 , 14 , -0.23197310306707982774 }, + { 8 , 15 , -0.17398365908895732646 }, + { 8 , 16 , -0.0070211419529606520704 }, + { 8 , 17 , 0.1537368341734622057 }, + { 8 , 18 , 0.19593344884811411677 }, + { 8 , 19 , 0.092941295568165452345 }, + { 8 , 20 , -0.073868928840750344711 }, + { 8 , 30 , 0.062890853316458550371 }, + { 8 , 100 , 0.043349559882386451415 }, + { 8 , 300 , -0.029725422012903089664 }, + { 8 , 1000 , 0.02462350597113223058 } , + { 9 , 1e-08 , 5.382288910934745386e-81 }, + { 9 , 3.16227766016838e-08 , 1.702029198362092975e-76 }, + { 9 , 1e-07 , 5.3822889109347404393e-72 }, + { 9 , 3.16227766016838e-07 , 1.7020291983620889989e-67 }, + { 9 , 1e-06 , 5.3822889109346077433e-63 }, + { 9 , 3.16227766016838e-06 , 1.7020291983616675345e-58 }, + { 9 , 1e-05 , 5.3822889109212923968e-54 }, + { 9 , 3.16227766016838e-05 , 1.7020291983195439884e-49 }, + { 9 , 1e-04 , 5.3822889095891748719e-45 }, + { 9 , 0.000316227766016838 , 1.7020291941070210695e-40 }, + { 9 , 0.001 , 5.382288776377523226e-36 }, + { 9 , 0.00316227766016838 , 1.7020287728548427703e-31 }, + { 9 , 0.01 , 5.3822754552277587118e-27 }, + { 9 , 0.0316227766016838 , 1.7019866481156611902e-22 }, + { 9 , 0.1 , 5.3809434916023306372e-18 }, + { 9 , 0.316227766016838 , 1.6977789573201714453e-13 }, + { 9 , 1 , 5.2492501799118757129e-09 }, + { 9 , 2 , 2.492343435133064173e-06 }, + { 9 , 3 , 8.4395021309091773631e-05 }, + { 9 , 4 , 0.00093860186121756401367 }, + { 9 , 5 , 0.005520283139475687037 }, + { 9 , 6 , 0.021165323978417364265 }, + { 9 , 7 , 0.058920508273075426764 }, + { 9 , 7.5 , 0.088919228493851462658 }, + { 9 , 7.6 , 0.095838903445761125521 }, + { 9 , 7.7 , 0.10305099353156887965 }, + { 9 , 7.8 , 0.11054469146011103309 }, + { 9 , 7.9 , 0.11830664869209804591 }, + { 9 , 8 , 0.12632089472237958971 }, + { 9 , 8.1 , 0.13456877270419806414 }, + { 9 , 8.2 , 0.14302889297143717151 }, + { 9 , 8.3 , 0.15167710592885710885 }, + { 9 , 8.4 , 0.16048649567533976312 }, + { 9 , 8.5 , 0.16942739560151048872 }, + { 9 , 9 , 0.2148805825406584491 }, + { 9 , 10 , 0.29185568526512006837 }, + { 9 , 11 , 0.30885550013686852155 }, + { 9 , 12 , 0.23038090956781773211 }, + { 9 , 13 , 0.066976198673670619965 }, + { 9 , 14 , -0.11430719814968128001 }, + { 9 , 15 , -0.22004622511384699934 }, + { 9 , 16 , -0.18953496566716260263 }, + { 9 , 17 , -0.042855569690119083015 }, + { 9 , 18 , 0.12276378966059287023 }, + { 9 , 19 , 0.19474432870140553908 }, + { 9 , 20 , 0.12512625464799415065 }, + { 9 , 30 , -0.11164340113688375755 }, + { 9 , 100 , -0.063236761406030891908 }, + { 9 , 300 , -0.036032302036864222172 }, + { 9 , 1000 , 0.0057157591719817308837 }, + { 10 , 1e-08 , 2.6911444554673727331e-90 }, + { 10 , 3.16227766016838e-08 , 2.6911444554673710334e-85 }, + { 10 , 1e-07 , 2.6911444554673703522e-80 }, + { 10 , 3.16227766016838e-07 , 2.6911444554673646193e-75 }, + { 10 , 1e-06 , 2.6911444554673096152e-70 }, + { 10 , 3.16227766016838e-06 , 2.6911444554667591352e-65 }, + { 10 , 1e-05 , 2.6911444554612582946e-60 }, + { 10 , 3.16227766016838e-05 , 2.6911444554062112799e-55 }, + { 10 , 1e-04 , 2.6911444548557502587e-50 }, + { 10 , 0.000316227766016838 , 2.691144449351135505e-45 }, + { 10 , 0.001 , 2.6911443943049990395e-40 }, + { 10 , 0.00316227766016838 , 2.6911438438436965201e-35 }, + { 10 , 0.01 , 2.6911383392363445476e-30 }, + { 10 , 0.0316227766016838 , 2.691083293730485964e-25 }, + { 10 , 0.1 , 2.6905328954342172306e-20 }, + { 10 , 0.316227766016838 , 2.6850345850670040022e-15 }, + { 10 , 1 , 2.630615123687452921e-10 }, + { 10 , 2 , 2.5153862827167368199e-07 }, + { 10 , 3 , 1.292835164571588302e-05 }, + { 10 , 4 , 0.00019504055466003448463 }, + { 10 , 5 , 0.0014678026473104743583 }, + { 10 , 6 , 0.0069639810027903158857 }, + { 10 , 7 , 0.023539344388267140901 }, + { 10 , 7.5 , 0.038998257889412211996 }, + { 10 , 7.6 , 0.042818673234280582585 }, + { 10 , 7.7 , 0.04690017276527555512 }, + { 10 , 7.8 , 0.051248883025765065713 }, + { 10 , 7.9 , 0.055869872504109699407 }, + { 10 , 8 , 0.060767026774251164944 }, + { 10 , 8.1 , 0.065942923604934144954 }, + { 10 , 8.2 , 0.071398709153595626975 }, + { 10 , 8.3 , 0.077133976423868738648 }, + { 10 , 8.4 , 0.083146647220432454151 }, + { 10 , 8.5 , 0.089432858880587384753 }, + { 10 , 9 , 0.12469409282831672714 }, + { 10 , 10 , 0.20748610663335886883 }, + { 10 , 11 , 0.28042823052537591 }, + { 10 , 12 , 0.300476035271269315 }, + { 10 , 13 , 0.23378201020301889179 }, + { 10 , 14 , 0.085006705446061009424 }, + { 10 , 15 , -0.09007181104765905888 }, + { 10 , 16 , -0.20620569442259728543 }, + { 10 , 17 , -0.19911331972770593413 }, + { 10 , 18 , -0.073169659187521246535 }, + { 10 , 19 , 0.091553331622639774756 }, + { 10 , 20 , 0.18648255802394508862 }, + { 10 , 30 , -0.129876893998588816 }, + { 10 , 100 , -0.054732176935472012791 }, + { 10 , 300 , 0.027563483890691235778 }, + { 10 , 1000 , -0.02452062230603655954 }, + { 30 , 1e-08 , 3.511074584737334481e-282 }, + { 30 , 3.16227766016838e-08 , 3.5110745847373276748e-267 }, + { 30 , 1e-07 , 3.5110745847373271436e-252 }, + { 30 , 3.16227766016838e-07 , 3.5110745847373244839e-237 }, + { 30 , 1e-06 , 3.5110745847372989351e-222 }, + { 30 , 3.16227766016838e-06 , 3.511074584737044636e-207 }, + { 30 , 1e-05 , 3.5110745847345094386e-192 }, + { 30 , 3.16227766016838e-05 , 3.5110745847090235522e-177 }, + { 30 , 1e-04 , 3.5110745844541855471e-162 }, + { 30 , 0.000316227766016838 , 3.5110745819058229075e-147 }, + { 30 , 0.001 , 3.5110745564222159037e-132 }, + { 30 , 0.00316227766016838 , 3.5110743015861690319e-117 }, + { 30 , 0.01 , 3.5110717532266786188e-102 }, + { 30 , 0.0316227766016838 , 3.5110462697303107185e-87 }, + { 30 , 0.1 , 3.5107914446214635799e-72 }, + { 30 , 0.316227766016838 , 3.5082441787554764315e-57 }, + { 30 , 1 , 3.4828697942514824077e-42 }, + { 30 , 2 , 3.6502562664740960186e-33 }, + { 30 , 3 , 6.7223399381463293316e-28 }, + { 30 , 4 , 3.5570357020361055268e-24 }, + { 30 , 5 , 2.6711772782507989195e-21 }, + { 30 , 6 , 5.7984683652785706951e-19 }, + { 30 , 7 , 5.3172607940100176027e-17 }, + { 30 , 7.5 , 3.9705139492720914996e-16 }, + { 30 , 7.6 , 5.8351206236969734897e-16 }, + { 30 , 7.7 , 8.5295046954365007979e-16 }, + { 30 , 7.8 , 1.240300099862031423e-15 }, + { 30 , 7.9 , 1.7943809060373146352e-15 }, + { 30 , 8 , 2.5830997825663086363e-15 }, + { 30 , 8.1 , 3.7004810818946501642e-15 }, + { 30 , 8.2 , 5.2761304350589830578e-15 }, + { 30 , 8.3 , 7.4879207291538333461e-15 }, + { 30 , 8.4 , 1.057892772982890842e-14 }, + { 30 , 8.5 , 1.4879948521285087748e-14 }, + { 30 , 9 , 7.6921564693354977569e-14 }, + { 30 , 10 , 1.5510960782574666161e-12 }, + { 30 , 11 , 2.2735383676316185421e-11 }, + { 30 , 12 , 2.5522590430344176732e-10 }, + { 30 , 13 , 2.2828783239868354402e-09 }, + { 30 , 14 , 1.6775399533577877891e-08 }, + { 30 , 15 , 1.0374710201078721135e-07 }, + { 30 , 16 , 5.5052386643076382366e-07 }, + { 30 , 17 , 2.5460065118711982301e-06 }, + { 30 , 18 , 1.0393652487465728599e-05 }, + { 30 , 19 , 3.7849142225173515583e-05 }, + { 30 , 20 , 0.00012401536360354329497 }, + { 30 , 30 , 0.14393585001030734238 }, + { 30 , 100 , 0.081460129581172213697 }, + { 30 , 300 , -0.029514887800373371812 }, + { 30 , 1000 , -0.020271896981075843147 }, + { 100 , 1e-08 , 0 }, + { 100 , 3.16227766016838e-08 , 0 }, + { 100 , 1e-07 , 0 }, + { 100 , 3.16227766016838e-07 , 0 }, + { 100 , 1e-06 , 0 }, + { 100 , 3.16227766016838e-06 , 0 }, + { 100 , 1e-05 , 0 }, + { 100 , 3.16227766016838e-05 , 0 }, + { 100 , 1e-04 , 0 }, + { 100 , 0.000316227766016838 , 0 }, + { 100 , 0.001 , 0 }, + { 100 , 0.00316227766016838 , 0 }, + { 100 , 0.01 , 0 }, + { 100 , 0.0316227766016838 , 0 }, + { 100 , 0.1 , 8.4525165351217888791e-289 }, + { 100 , 0.316227766016838 , 8.4506337559752745816e-239 }, + { 100 , 1 , 8.4318287896267070128e-189 }, + { 100 , 2 , 1.0609531124391718917e-158 }, + { 100 , 3 , 4.260360181132621405e-141 }, + { 100 , 4 , 1.305547836452271925e-128 }, + { 100 , 5 , 6.2677893955418752099e-119 }, + { 100 , 6 , 5.0513258541507019365e-111 }, + { 100 , 7 , 2.4215591572118171706e-104 }, + { 100 , 7.5 , 2.3583800455568589368e-101 }, + { 100 , 7.6 , 8.8352979458474109476e-101 }, + { 100 , 7.7 , 3.253025120751429903e-100 }, + { 100 , 7.8 , 1.1776236102157393805e-99 }, + { 100 , 7.9 , 4.1933885427120016432e-99 }, + { 100 , 8 , 1.4694094093552327336e-98 }, + { 100 , 8.1 , 5.0688862671208964077e-98 }, + { 100 , 8.2 , 1.7220304874625643909e-97 }, + { 100 , 8.3 , 5.7635248300942440709e-97 }, + { 100 , 8.4 , 1.9011188242236321325e-96 }, + { 100 , 8.5 , 6.182346491260611201e-96 }, + { 100 , 9 , 1.8369106342703587456e-93 }, + { 100 , 10 , 6.5973160641553802341e-89 }, + { 100 , 11 , 8.6297901331738815878e-85 }, + { 100 , 12 , 4.8983704457507876536e-81 }, + { 100 , 13 , 1.3781127544328333402e-77 }, + { 100 , 14 , 2.1310751903146119988e-74 }, + { 100 , 15 , 1.9660095611249536378e-71 }, + { 100 , 16 , 1.1559435724349575529e-68 }, + { 100 , 17 , 4.5721265690179434188e-66 }, + { 100 , 18 , 1.2722370655682102766e-63 }, + { 100 , 19 , 2.5856336302772506687e-61 }, + { 100 , 20 , 3.9617550943362506795e-59 }, + { 100 , 30 , 4.5788015281752424119e-42 }, + { 100 , 100 , 0.09636667329586150188 }, + { 100 , 300 , -0.014491227064785699996 }, + { 100 , 1000 , 0.011676135007802557891 }, + { 300 , 1e-08 , 0 }, + { 300 , 3.16227766016838e-08 , 0 }, + { 300 , 1e-07 , 0 }, + { 300 , 3.16227766016838e-07 , 0 }, + { 300 , 1e-06 , 0 }, + { 300 , 3.16227766016838e-06 , 0 }, + { 300 , 1e-05 , 0 }, + { 300 , 3.16227766016838e-05 , 0 }, + { 300 , 1e-04 , 0 }, + { 300 , 0.000316227766016838 , 0 }, + { 300 , 0.001 , 0 }, + { 300 , 0.00316227766016838 , 0 }, + { 300 , 0.01 , 0 }, + { 300 , 0.0316227766016838 , 0 }, + { 300 , 0.1 , 0 }, + { 300 , 0.316227766016838 , 0 }, + { 300 , 1 , 0 }, + { 300 , 2 , 0 }, + { 300 , 3 , 0 }, + { 300 , 4 , 0 }, + { 300 , 5 , 0 }, + { 300 , 6 , 0 }, + { 300 , 7 , 0 }, + { 300 , 7.5 , 0 }, + { 300 , 7.6 , 0 }, + { 300 , 7.7 , 0 }, + { 300 , 7.8 , 0 }, + { 300 , 7.9 , 0 }, + { 300 , 8 , 0 }, + { 300 , 8.1 , 0 }, + { 300 , 8.2 , 0 }, + { 300 , 8.3 , 0 }, + { 300 , 8.4 , 0 }, + { 300 , 8.5 , 0 }, + { 300 , 9 , 0 }, + { 300 , 10 , 0 }, + { 300 , 11 , 0 }, + { 300 , 12 , 0 }, + { 300 , 13 , 0 }, + { 300 , 14 , 0 }, + { 300 , 15 , 0 }, + { 300 , 16 , 0 }, + { 300 , 17 , 0 }, + { 300 , 18 , 0 }, + { 300 , 19 , 0 }, + { 300 , 20 , 0 }, + { 300 , 30 , 1.0388021531643495593e-262 }, + { 300 , 100 , 3.5203666218469330448e-109 }, + { 300 , 300 , 0.066818398128979980544 }, + { 300 , 1000 , 0.00046782803879124944908 } + }; + + @Test + public void testBesselJ() { + final double tol = 1e-15; + + for (int i = 0; i < BESSEL_J_REF.length; i++) { + final double[] data = BESSEL_J_REF[i]; + final double order = data[0]; + final double x = data[1]; + final double expected = data[2]; + final double actual = BesselJ.value(order, x); + + String msg = "" + order + " @ " + x; + Assert.assertEquals(msg, expected, actual, tol); + } + } + + @Test(expected=MathIllegalArgumentException.class) + public void testIAEBadOrder() { + BesselJ.value(-1, 1); + } + + @Test(expected=MathIllegalArgumentException.class) + public void testIAEBadArgument() { + BesselJ.value(1, 100000); + } +}