Nothing
#
# Online supplemental material for ``Even faster and more accurate
# first-passage time densities and distributions for the Wiener diffusion
# model'' by Gondan, Blurton, and Kesselmeier.
#
#
# log of Mill's ratio for the normal distribution
#
logMill = function(x) # log of Mills ratio
{
m = numeric(length(x))
m[x >= 10000] = -log(x[x >= 10000]) # limiting case for x -> Inf
m[x < 10000] = pnorm(x[x < 10000], lower=FALSE, log=TRUE) -
dnorm(x[x < 10000], log=TRUE)
return(m)
}
#
# Number of terms required for the distribution
#
Ks = function(t, v, a, w, eps)
{
K1 = (abs(v)*t - a*w)/2/a
arg = pmax(0, pmin(1, exp(v*a*w + v*v*t/2 + log(eps))/2))
K2 = -sqrt(t)/2/a * qnorm(arg)
return(ceiling(max(K1, K1 + K2)))
}
#
# Distribution at lower barrier - small time representation
#
# t: time (vector)
# v: drift
# a: upper barrier
# w: relative position of X(0) = z, w = z/a
# eps: required precision
#
Fs = function(t, v, a, w, eps=sqrt(.Machine$double.eps))
{
K = Ks(t, v, a, w, eps)
F = numeric(length(t))
sqt = sqrt(t)
for(k in K:0)
{
rj = 2*k*a + a*w
dj = -v*a*w - v*v*t/2 + dnorm(rj/sqt, log=TRUE)
pos1 = dj + logMill((rj-v*t)/sqt)
pos2 = dj + logMill((rj+v*t)/sqt)
rj = (2*k+1)*a + a*(1-w)
dj = -v*a*w - v*v*t/2 + dnorm(rj/sqt, log=TRUE)
neg1 = dj + logMill((rj-v*t)/sqt)
neg2 = dj + logMill((rj+v*t)/sqt)
F = exp(pos1) + exp(pos2) - exp(neg1) - exp(neg2) + F
}
return(F)
}
#
# Number of terms for the density
#
ks = function(t, w, eps)
{
K1 = K2 = (sqrt(2*t) - w)/2
u_eps = pmin(-1, log(2*pi*t*t*eps*eps)) # Safe bound so that
arg = -t * (u_eps - sqrt(-2*u_eps - 2)) # sqrt(x) with x > 0
K2[arg > 0] = 1/2 * sqrt(arg) - w/2
return(ceiling(max(K1, K2)))
}
#
# Density at the lower barrier - one-parameter form
#
fsw = function(t, w, eps)
{
K = ks(t, w, eps)
f = numeric(length(t))
if(K > 0) for(k in K:1)
f = (w+2*k) * exp(-(w+2*k) * (w+2*k)/2/t) +
(w-2*k) * exp(-(w-2*k) * (w-2*k)/2/t) + f
return(1/sqrt(2*pi*t*t*t) * (f + w * exp(-w*w/2/t)))
}
#
# Density at lower barrier
#
# t: time (vector)
# v: drift
# a: upper barrier
# w: relative position of X(0) = z, w = z/a
# eps: required precision
#
fs = function(t, v, a, w, eps=sqrt(.Machine$double.eps))
{
g = 1/a/a * exp(-v*a*w - v*v*t/2)
return(g * fsw(t/a/a, w, eps/g))
}
#
# Examples
#
# Fs(t=1:1000, v=-0.1, a=100, w=0.4) for the distribution within 1-1000 ms
# fs(t=1:1000, v=-0.1, a=100, w=0.4) for the density
# Fs(t=1:1000, v=-(-0.1), a=100, w=1-0.4) for the upper barrier
# sigma = 0.1
# Fs(t=1:1000, v=-0.1/sigma, a=100/sigma, w=0.6) same for non-unit SD
#
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.