Title: | Computations and Approximations for Bessel Functions |
---|---|
Description: | Computations for Bessel function for complex, real and partly 'mpfr' (arbitrary precision) numbers; notably interfacing TOMS 644; approximations for large arguments, experiments, etc. |
Authors: | Martin Maechler [aut, cre] |
Maintainer: | Martin Maechler <[email protected]> |
License: | GPL (>= 2) |
Version: | 0.6-2 |
Built: | 2024-11-02 19:12:50 UTC |
Source: | https://github.com/r-forge/specfun |
Compute the Airy functions or
or their first
derivatives,
and
.
The Airy functions are solutions of the differential equation
for , and are related to each other and to the
(modified) Bessel functions via (many identities, see
https://dlmf.nist.gov/9.6), e.g., if
,
and
AiryA(z, deriv = 0, expon.scaled = FALSE, verbose = 0) AiryB(z, deriv = 0, expon.scaled = FALSE, verbose = 0)
AiryA(z, deriv = 0, expon.scaled = FALSE, verbose = 0) AiryB(z, deriv = 0, expon.scaled = FALSE, verbose = 0)
z |
complex or numeric vector. |
deriv |
order of derivative; must be 0 or 1. |
expon.scaled |
logical indicating if the result should be scaled by an exponential factor (typically to avoid under- or over-flow). |
verbose |
integer defaulting to 0, indicating the level of verbosity notably from C code. |
By default, when expon.scaled
is false, AiryA()
computes the complex Airy function or its derivative
on
deriv=0
or deriv=1
respectively.
When expon.scaled
is true, it returns
or
,
effectively removing the exponential decay in
and
the exponential growth in
,
where
, and
Arg(z)
.
While the Airy functions and
are
analytic in the whole
plane, the corresponding scaled
functions (for
expon.scaled=TRUE
) have a cut along the
negative real axis.
By default, when expon.scaled
is false, AiryB()
computes the complex Airy function or its derivative
on
deriv=0
or deriv=1
respectively.
When expon.scaled
is true, it returns
or
,
to remove the exponential behavior in both the left and right half
planes where, as above,
.
a complex or numeric vector of the same length (and class) as z
.
Donald E. Amos, Sandia National Laboratories, wrote the original fortran code. Martin Maechler did the R interface.
see BesselJ
; notably for many results the
Digital Library of Mathematical Functions (DLMF), Chapter 9 Airy and Related Functions at https://dlmf.nist.gov/9.
BesselI
etc; the Hankel functions Hankel
.
The CRAN package Rmpfr has Ai(x)
for
arbitrary precise "mpfr"-numbers x
.
## The AiryA() := Ai() function ------------- curve(AiryA, -20, 100, n=1001) curve(AiryA, -1, 100, n=1011, log="y") -> Aix curve(AiryA(x, expon.scaled=TRUE), -1, 50, n=1001) ## Numerically "proving" the 1st identity above : z <- Aix$x; i <- z > 0; head(z <- z[i <- z > 0]) Aix <- Aix$y[i]; zeta <- 2/3*z*sqrt(z) stopifnot(all.equal(Aix, 1/pi * sqrt(z/3)* BesselK(zeta, nu = 1/3), tol = 4e-15)) # 64b Lnx: 7.9e-16; 32b Win: 1.8e-15 ## This gives many warnings (248 on nb-mm4, F24) about lost accuracy, but on Windows takes ~ 4 sec: curve(AiryA(x, expon.scaled=TRUE), 1, 10000, n=1001, log="xy") ## The AiryB() := Bi() function ------------- curve(AiryB, -20, 2, n=1001); abline(h=0,v=0, col="gray",lty=2) curve(AiryB, -1, 20, n=1001, log = "y") # exponential growth (x > 0) curve(AiryB(x,expon.scaled=TRUE), -1, 20, n=1001) curve(AiryB(x,expon.scaled=TRUE), 1, 10000, n=1001, log="x")
## The AiryA() := Ai() function ------------- curve(AiryA, -20, 100, n=1001) curve(AiryA, -1, 100, n=1011, log="y") -> Aix curve(AiryA(x, expon.scaled=TRUE), -1, 50, n=1001) ## Numerically "proving" the 1st identity above : z <- Aix$x; i <- z > 0; head(z <- z[i <- z > 0]) Aix <- Aix$y[i]; zeta <- 2/3*z*sqrt(z) stopifnot(all.equal(Aix, 1/pi * sqrt(z/3)* BesselK(zeta, nu = 1/3), tol = 4e-15)) # 64b Lnx: 7.9e-16; 32b Win: 1.8e-15 ## This gives many warnings (248 on nb-mm4, F24) about lost accuracy, but on Windows takes ~ 4 sec: curve(AiryA(x, expon.scaled=TRUE), 1, 10000, n=1001, log="xy") ## The AiryB() := Bi() function ------------- curve(AiryB, -20, 2, n=1001); abline(h=0,v=0, col="gray",lty=2) curve(AiryB, -1, 20, n=1001, log = "y") # exponential growth (x > 0) curve(AiryB(x,expon.scaled=TRUE), -1, 20, n=1001) curve(AiryB(x,expon.scaled=TRUE), 1, 10000, n=1001, log="x")
Compute the Bessel functions I(), J(), K(), and Y(), of complex
arguments z
and real nu
,
BesselI(z, nu, expon.scaled = FALSE, nSeq = 1, verbose = 0) BesselJ(z, nu, expon.scaled = FALSE, nSeq = 1, verbose = 0) BesselK(z, nu, expon.scaled = FALSE, nSeq = 1, verbose = 0) BesselY(z, nu, expon.scaled = FALSE, nSeq = 1, verbose = 0)
BesselI(z, nu, expon.scaled = FALSE, nSeq = 1, verbose = 0) BesselJ(z, nu, expon.scaled = FALSE, nSeq = 1, verbose = 0) BesselK(z, nu, expon.scaled = FALSE, nSeq = 1, verbose = 0) BesselY(z, nu, expon.scaled = FALSE, nSeq = 1, verbose = 0)
z |
complex or numeric vector. |
nu |
numeric (scalar). |
expon.scaled |
logical indicating if the result should be scaled by an exponential factor, typically to avoid under- or over-flow. See the ‘Details’ about the specific scaling. |
nSeq |
positive integer; if |
verbose |
integer defaulting to 0, indicating the level of verbosity notably from C code. |
The case nu < 0
is handled by using simple formula from
Abramowitz and Stegun, see details in besselI()
.
The scaling activated by expon.scaled = TRUE
depends on the
function and the scaled versions are
BesselJ(z, nu, expo=TRUE)
BesselY(z, nu, expo=TRUE)
BesselI(z, nu, expo=TRUE)
BesselK(z, nu, expo=TRUE)
a complex or numeric vector (or matrix
with nSeq
columns if nSeq > 1
)
of the same length (or nrow
when nSeq > 1
) and
mode
as z
.
Donald E. Amos, Sandia National Laboratories, wrote the original
fortran code.
Martin Maechler did the translation to C, and partial cleanup
(replacing goto
's), in addition to the R interface.
Abramowitz, M., and Stegun, I. A. (1964, etc). Handbook of mathematical functions (NBS AMS series 55, U.S. Dept. of Commerce), https://personal.math.ubc.ca/~cbm/aands/
Wikipedia (20nn). Bessel Function, https://en.wikipedia.org/wiki/Bessel_function
D. E. Amos (1986) Algorithm 644: A portable package for Bessel functions of a complex argument and nonnegative order; ACM Trans. Math. Software 12, 3, 265–273.
D. E. Amos (1983) Computation of Bessel Functions of Complex Argument; Sand83-0083.
D. E. Amos (1983) Computation of Bessel Functions of Complex Argument and Large Order; Sand83-0643.
D. E. Amos (1985) A subroutine package for Bessel functions of a complex argument and nonnegative order; Sand85-1018.
Olver, F.W.J. (1974). Asymptotics and Special Functions; Academic Press, N.Y., p.420
The base R functions besselI()
, besselK()
, etc.
The Hankel functions (of first and second kind),
and
:
Hankel
.
The Airy functions and
and their first
derivatives,
Airy
.
For large x
and/or nu
arguments, algorithm AS~644 is not
good enough, and the results may overflow to Inf
or underflow
to zero, such that direct computation of and
are desirable. For this, we provide
besselI.nuAsym()
, besselIasym()
and
besselK.nuAsym(*, log= *)
, based on asymptotic expansions.
## For real small arguments, BesselI() gives the same as base::besselI() : set.seed(47); x <- sort(round(rlnorm(20), 2)) M <- cbind(x, b = besselI(x, 3), B = BesselI(x, 3)) stopifnot(all.equal(M[,"b"], M[,"B"], tol = 2e-15)) # ~4e-16 even M ## and this is true also for the 'exponentially scaled' version: Mx <- cbind(x, b = besselI(x, 3, expon.scaled=TRUE), B = BesselI(x, 3, expon.scaled=TRUE)) stopifnot(all.equal(Mx[,"b"], Mx[,"B"], tol = 2e-15)) # ~4e-16 even
## For real small arguments, BesselI() gives the same as base::besselI() : set.seed(47); x <- sort(round(rlnorm(20), 2)) M <- cbind(x, b = besselI(x, 3), B = BesselI(x, 3)) stopifnot(all.equal(M[,"b"], M[,"B"], tol = 2e-15)) # ~4e-16 even M ## and this is true also for the 'exponentially scaled' version: Mx <- cbind(x, b = besselI(x, 3, expon.scaled=TRUE), B = BesselI(x, 3, expon.scaled=TRUE)) stopifnot(all.equal(Mx[,"b"], Mx[,"B"], tol = 2e-15)) # ~4e-16 even
Compute the Hankel functions and
,
also called ‘H-Bessel’ function (of the third kind),
of complex arguments. They are defined as
where and
are the
Bessel functions of the first and second kind, see
BesselJ
, etc.
BesselH(m, z, nu, expon.scaled = FALSE, nSeq = 1, verbose = 0)
BesselH(m, z, nu, expon.scaled = FALSE, nSeq = 1, verbose = 0)
m |
integer, either 1 or 2, indicating the kind of Hankel function. |
z |
complex or numeric vector of values different from 0. |
nu |
numeric, must currently be non-negative. |
expon.scaled |
logical indicating if the result should be scaled by an exponential factor (typically to avoid under- or over-flow). |
nSeq |
positive integer; if |
verbose |
integer defaulting to 0, indicating the level of verbosity notably from C code. |
By default (when expon.scaled
is false), the resulting sequence
(of length nSeq
) is for ,
computed for .
If expon.scaled
is true, the sequence is for
where
(and
), for
.
a complex or numeric vector (or matrix
if nSeq > 1
)
of the same length and mode
as z
.
Donald E. Amos, Sandia National Laboratories, wrote the original fortran code. Martin Maechler did the R interface.
see BesselI
.
BesselI
etc; the Airy function Airy
.
##------------------ H(1, *) ---------------- nus <- c(1,2,5,10) for(i in seq_along(nus)) curve(BesselH(1, x, nu=nus[i]), -10, 10, add= i > 1, col=i, n=1000) legend("topleft", paste("nu = ", format(nus)), col = seq_along(nus), lty=1) ## nu = 10 looks a bit "special" ... hmm... curve(BesselH(1, x, nu=10), -.3, .3, col=4, ylim = c(-10,10), n=1000) ##------------------ H(2, *) ---------------- for(i in seq_along(nus)) curve(BesselH(2, x, nu=nus[i]), -10, 10, add= i > 1, col=i, n=1000) legend("bottomright", paste("nu = ", format(nus)), col = seq_along(nus), lty=1) ## the same nu = 10 behavior ..
##------------------ H(1, *) ---------------- nus <- c(1,2,5,10) for(i in seq_along(nus)) curve(BesselH(1, x, nu=nus[i]), -10, 10, add= i > 1, col=i, n=1000) legend("topleft", paste("nu = ", format(nus)), col = seq_along(nus), lty=1) ## nu = 10 looks a bit "special" ... hmm... curve(BesselH(1, x, nu=10), -.3, .3, col=4, ylim = c(-10,10), n=1000) ##------------------ H(2, *) ---------------- for(i in seq_along(nus)) curve(BesselH(2, x, nu=nus[i]), -10, 10, add= i > 1, col=i, n=1000) legend("bottomright", paste("nu = ", format(nus)), col = seq_along(nus), lty=1) ## the same nu = 10 behavior ..
Compute Bessel functions and
for large
and possibly large
,
using asymptotic expansions in Debye polynomials.
besselI.nuAsym(x, nu, k.max, expon.scaled = FALSE, log = FALSE) besselK.nuAsym(x, nu, k.max, expon.scaled = FALSE, log = FALSE)
besselI.nuAsym(x, nu, k.max, expon.scaled = FALSE, log = FALSE) besselK.nuAsym(x, nu, k.max, expon.scaled = FALSE, log = FALSE)
x |
numeric or |
nu |
numeric; The order (maybe fractional!) of the corresponding Bessel function. |
k.max |
integer number of terms in the expansion. Must be in
|
expon.scaled |
logical; if |
log |
logical; if TRUE, |
Abramowitz & Stegun , page 378, has formula 9.7.7 and 9.7.8 for the asymptotic
expansions of and
, respectively,
also saying
When
, these expansions
(of
and
)
hold uniformly with respect to
in the sector
,
where
iw qn arbitrary positive number.
and for this reason, we require
.
The Debye polynomials are defined in 9.3.9 and 9.3.10 (page 366).
a numeric vector of the same length as the long of x
and
nu
. (usual argument recycling is applied implicitly.)
Martin Maechler
Abramowitz, M., and Stegun, I. A. (1964, etc). Handbook of mathematical functions, pp. 366, 378.
From this package Bessel: BesselI()
; further,
besselIasym()
for the case when is large and
is small or moderate.
Further, from base: besselI
, etc.
x <- c(1:10, 20, 50, 100, 100000) nu <- c(1, 10, 20, 50, 10^(2:10)) sapply(0:4, function(k.) sapply(nu, function(n.) besselI.nuAsym(x, nu=n., k.max = k., log = TRUE))) sapply(0:4, function(k.) sapply(nu, function(n.) besselK.nuAsym(x, nu=n., k.max = k., log = TRUE)))
x <- c(1:10, 20, 50, 100, 100000) nu <- c(1, 10, 20, 50, 10^(2:10)) sapply(0:4, function(k.) sapply(nu, function(n.) besselI.nuAsym(x, nu=n., k.max = k., log = TRUE))) sapply(0:4, function(k.) sapply(nu, function(n.) besselK.nuAsym(x, nu=n., k.max = k., log = TRUE)))
Compute Bessel function
and
for large
and small or moderate
, using the asymptotic expansions (9.7.1) and (9.7.2), p.377-8 of
Abramowitz & Stegun, for
, even valid for
complex
,
where
and and
.
Whereas besselIasym(x,a)
computes a possibly exponentially scaled
and/or log
ged version of ,
besselI.ftrms
returns the corresponding terms in the
series expansion of above.
besselIasym (x, nu, k.max = 10, expon.scaled = FALSE, log = FALSE) besselKasym (x, nu, k.max = 10, expon.scaled = FALSE, log = FALSE) besselI.ftrms(x, nu, K = 20)
besselIasym (x, nu, k.max = 10, expon.scaled = FALSE, log = FALSE) besselKasym (x, nu, k.max = 10, expon.scaled = FALSE, log = FALSE) besselI.ftrms(x, nu, K = 20)
x |
numeric or complex (with real part) |
nu |
numeric; the order (maybe fractional!) of the corresponding Bessel function. |
k.max , K
|
integer number of terms in the expansion. |
expon.scaled |
logical; if |
log |
logical; if TRUE, |
Even though the reference (A. & S.) requires
for
and
for
,
where
Arg(z)
,
the zero-th order term seems correct also for negative (real) numbers.
a numeric (or complex) vector of the same length as x
.
Martin Maechler
Abramowitz, M., and Stegun, I. A. (1964, etc). Handbook of mathematical functions (NBS AMS series 55, U.S. Dept. of Commerce).
From this package Bessel() BesselI()
; further,
besselI.nuAsym()
which is useful when is large
(as well); further base
besselI
, etc
x <- c(1:10, 20, 50, 100^(2:10)) nu <- c(1, 10, 20, 50, 100) r <- lapply(c(0:4,10,20), function(k.) sapply(nu, function(n.) besselIasym(x, nu=n., k.max = k., log = TRUE))) warnings() try( # needs improvement in R [or a local workaround] besselIasym(10000*(1+1i), nu=200, k.max=20, log=TRUE) ) # Error in log1p(-d) : unimplemented complex function
x <- c(1:10, 20, 50, 100^(2:10)) nu <- c(1, 10, 20, 50, 100) r <- lapply(c(0:4,10,20), function(k.) sapply(nu, function(n.) besselIasym(x, nu=n., k.max = k., log = TRUE))) warnings() try( # needs improvement in R [or a local workaround] besselIasym(10000*(1+1i), nu=200, k.max=20, log=TRUE) ) # Error in log1p(-d) : unimplemented complex function
Computes the modified Bessel function, using one of its basic
definitions as an infinite series, e.g. A. & S., p.360, (9.1.10). The
implementation is pure R, working for
numeric
,
complex
, but also e.g., for objects of class
"mpfr"
from package Rmpfr.
besselJs(x, nu, nterm = 800, log = FALSE, Ceps = if (isNum) 8e-16 else 2^([email protected][[1]]@prec))
besselJs(x, nu, nterm = 800, log = FALSE, Ceps = if (isNum) 8e-16 else 2^(-x@.Data[[1]]@prec))
x |
numeric or complex vector, or of another |
nu |
non-negative numeric (scalar). |
nterm |
integer indicating the number of terms to be used.
Should be in the order of |
log |
logical indicating if the logarithm |
Ceps |
a relative error tolerance for checking if |
a “numeric” (or complex or "mpfr"
)
vector of the same class and length as x
.
Martin Maechler
Abramowitz, M., and Stegun, I. A. (1964–1972). Handbook of mathematical functions (NBS AMS series 55, U.S. Dept. of Commerce). https://personal.math.ubc.ca/~cbm/aands/page_360.htm
This package BesselJ()
, base besselJ()
, etc
stopifnot(all.equal(besselJs(1:10, 1), # our R code --> 4 warnings, for x = 4:7 besselJ (1:10, 1)))# internal C code w/ different algorithm ## Large 'nu' ... x <- (0:20)/4 if(interactive()) op <- options(nwarnings = 999) (bx <- besselJ(x, nu=200))# base R's -- gives 19 (mostly wrong) warnings about precision lost ## Visualize: bj <- curve(besselJ(1, x), 1, 2^10, log="xy", n=1001, main=quote(J[nu](1)), xlab = quote(nu), xaxt="n", yaxt="n") # 50+ warnings eaxis <- if(!requireNamespace("sfsmisc")) axis else sfsmisc::eaxis eaxis(1, sub10 = 3); eaxis(2) bj6 <- curve(besselJ(6, x), add=TRUE, n=1001, col=adjustcolor(2, 1/2), lwd=2) plot(y~x, as.data.frame(bj6), log="x", type="l", col=2, lwd=2, main = quote(J[nu](6)), xlab = quote(nu), xaxt="n") eaxis(1, sub10=3); abline(h=0, lty=3) if(require("Rmpfr")) { ## Use high precision, notably large exponent range, numbers: Bx <- besselJs(mpfr(x, 64), nu=200) all.equal(Bx, bx, tol = 1e-15)# TRUE -- warnings were mostly wrong; specifically: cbind(bx, Bx) signif(asNumeric(1 - (bx/Bx)[19:21]), 4) # only [19] had lost accuracy ## With*out* mpfr numbers -- using log -- is accurate (here) lbx <- besselJs( x, nu=200, log=TRUE) lBx <- besselJs(mpfr(x, 64), nu=200, log=TRUE) cbind(x, lbx, lBx) stopifnot(all.equal(asNumeric(log(Bx)), lbx, tol=1e-15), all.equal(lBx, lbx, tol=4e-16)) } # Rmpfr if(interactive()) options(op) # reset 'nwarnings'
stopifnot(all.equal(besselJs(1:10, 1), # our R code --> 4 warnings, for x = 4:7 besselJ (1:10, 1)))# internal C code w/ different algorithm ## Large 'nu' ... x <- (0:20)/4 if(interactive()) op <- options(nwarnings = 999) (bx <- besselJ(x, nu=200))# base R's -- gives 19 (mostly wrong) warnings about precision lost ## Visualize: bj <- curve(besselJ(1, x), 1, 2^10, log="xy", n=1001, main=quote(J[nu](1)), xlab = quote(nu), xaxt="n", yaxt="n") # 50+ warnings eaxis <- if(!requireNamespace("sfsmisc")) axis else sfsmisc::eaxis eaxis(1, sub10 = 3); eaxis(2) bj6 <- curve(besselJ(6, x), add=TRUE, n=1001, col=adjustcolor(2, 1/2), lwd=2) plot(y~x, as.data.frame(bj6), log="x", type="l", col=2, lwd=2, main = quote(J[nu](6)), xlab = quote(nu), xaxt="n") eaxis(1, sub10=3); abline(h=0, lty=3) if(require("Rmpfr")) { ## Use high precision, notably large exponent range, numbers: Bx <- besselJs(mpfr(x, 64), nu=200) all.equal(Bx, bx, tol = 1e-15)# TRUE -- warnings were mostly wrong; specifically: cbind(bx, Bx) signif(asNumeric(1 - (bx/Bx)[19:21]), 4) # only [19] had lost accuracy ## With*out* mpfr numbers -- using log -- is accurate (here) lbx <- besselJs( x, nu=200, log=TRUE) lBx <- besselJs(mpfr(x, 64), nu=200, log=TRUE) cbind(x, lbx, lBx) stopifnot(all.equal(asNumeric(log(Bx)), lbx, tol=1e-15), all.equal(lBx, lbx, tol=4e-16)) } # Rmpfr if(interactive()) options(op) # reset 'nwarnings'
Computes the modified Bessel function, using one of its basic
definitions as an infinite series. The implementation is pure R,
working for
numeric
, complex
, but also
e.g., for objects of class "mpfr"
from package Rmpfr.
besselIs(x, nu, nterm = 800, expon.scaled = FALSE, log = FALSE, Ceps = if (isNum) 8e-16 else 2^([email protected][[1]]@prec))
besselIs(x, nu, nterm = 800, expon.scaled = FALSE, log = FALSE, Ceps = if (isNum) 8e-16 else 2^(-x@.Data[[1]]@prec))
x |
numeric or complex vector, or of another |
nu |
non-negative numeric (scalar). |
nterm |
integer indicating the number of terms to be used.
Should be in the order of |
expon.scaled |
logical indicating if the result should be scaled
by |
log |
logical indicating if the logarithm |
Ceps |
a relative error tolerance for checking if |
a “numeric” (or complex or "mpfr"
)
vector of the same class and length as x
.
Martin Maechler
Abramowitz, M., and Stegun, I. A. (1964,.., 1972). Handbook of mathematical functions (NBS AMS series 55, U.S. Dept. of Commerce).
This package BesselI
, base besselI
, etc
(nus <- c(outer((0:3)/4, 1:5, `+`))) stopifnot( all.equal(besselIs(1:10, 1), # our R code besselI (1:10, 1)) # internal C code w/ different algorithm , sapply(nus, function(nu) all.equal(besselIs(1:10, nu, expon.scale=TRUE), # our R code BesselI (1:10, nu, expon.scale=TRUE)) # TOMS644 code ) , ## complex argument [gives warnings 'nterm=800' may be too small] sapply(nus, function(nu) all.equal(besselIs((1:10)*(1+1i), nu, expon.scale=TRUE), # our R code BesselI ((1:10)*(1+1i), nu, expon.scale=TRUE)) # TOMS644 code ) ) ## Large 'nu' ... x <- (0:20)/4 (bx <- besselI(x, nu=200))# base R's -- gives (mostly wrong) warnings if(require("Rmpfr")) { ## Use high precision (notably large exponent range) numbers: Bx <- besselIs(mpfr(x, 64), nu=200) all.equal(Bx, bx, tol = 1e-15)# TRUE -- warning were mostly wrong; specifically: cbind(bx, Bx) signif(asNumeric(1 - (bx/Bx)[19:21]), 4) # only [19] had lost accuracy ## With*out* mpfr numbers -- using log -- is accurate (here) (lbx <- besselIs( x, nu=200, log=TRUE)) lBx <- besselIs(mpfr(x, 64), nu=200, log=TRUE) stopifnot(all.equal(asNumeric(log(Bx)), lbx, tol=1e-15), all.equal(lBx, lbx, tol=4e-16)) } # Rmpfr
(nus <- c(outer((0:3)/4, 1:5, `+`))) stopifnot( all.equal(besselIs(1:10, 1), # our R code besselI (1:10, 1)) # internal C code w/ different algorithm , sapply(nus, function(nu) all.equal(besselIs(1:10, nu, expon.scale=TRUE), # our R code BesselI (1:10, nu, expon.scale=TRUE)) # TOMS644 code ) , ## complex argument [gives warnings 'nterm=800' may be too small] sapply(nus, function(nu) all.equal(besselIs((1:10)*(1+1i), nu, expon.scale=TRUE), # our R code BesselI ((1:10)*(1+1i), nu, expon.scale=TRUE)) # TOMS644 code ) ) ## Large 'nu' ... x <- (0:20)/4 (bx <- besselI(x, nu=200))# base R's -- gives (mostly wrong) warnings if(require("Rmpfr")) { ## Use high precision (notably large exponent range) numbers: Bx <- besselIs(mpfr(x, 64), nu=200) all.equal(Bx, bx, tol = 1e-15)# TRUE -- warning were mostly wrong; specifically: cbind(bx, Bx) signif(asNumeric(1 - (bx/Bx)[19:21]), 4) # only [19] had lost accuracy ## With*out* mpfr numbers -- using log -- is accurate (here) (lbx <- besselIs( x, nu=200, log=TRUE)) lBx <- besselIs(mpfr(x, 64), nu=200, log=TRUE) stopifnot(all.equal(asNumeric(log(Bx)), lbx, tol=1e-15), all.equal(lBx, lbx, tol=4e-16)) } # Rmpfr