Skip to content

Commit

Permalink
Implement the T-distribution via the F-distribution (#149)
Browse files Browse the repository at this point in the history
  • Loading branch information
andreasnoack authored Nov 29, 2022
1 parent e5699db commit 12c838e
Showing 1 changed file with 64 additions and 14 deletions.
78 changes: 64 additions & 14 deletions src/distrs/tdist.jl
Original file line number Diff line number Diff line change
@@ -1,19 +1,5 @@
# functions related to student's T distribution

# R implementations
using .RFunctions:
# tdistpdf,
# tdistlogpdf,
tdistcdf,
tdistccdf,
tdistlogcdf,
tdistlogccdf,
tdistinvcdf,
tdistinvccdf,
tdistinvlogcdf,
tdistinvlogccdf

# Julia implementations
tdistpdf::Real, x::Real) = exp(tdistlogpdf(ν, x))

tdistlogpdf::Real, x::Real) = tdistlogpdf(promote(ν, x)...)
Expand All @@ -22,3 +8,67 @@ function tdistlogpdf(ν::T, x::T) where {T<:Real}
νp12 =+ 1) / 2
return loggamma(νp12) - (logπ + log(ν)) / 2 - loggamma/ 2) - νp12 * log1p(x^2 / ν)
end

function tdistcdf::T, x::T) where T<:Real
if isinf(ν)
return normcdf(x)
elseif x < 0
return fdistccdf(one(ν), ν, x^2)/2
else
return 1 - fdistccdf(one(ν), ν, x^2)/2
end
end
tdistcdf::Real, x::Real) = tdistcdf(map(float, promote(ν, x))...)

tdistccdf::Real, x::Real) = tdistcdf(ν, -x)

function tdistlogcdf::T, x::T) where T<:Real
if isinf(ν)
return normlogcdf(x)
elseif x < 0
ret = fdistlogccdf(one(ν), ν, x^2)
return ret - logtwo
else
return log1p(-fdistccdf(one(ν), ν, x^2)/2)
end
end
tdistlogcdf::Real, x::Real) = tdistlogcdf(map(float, promote(ν, x))...)

tdistlogccdf::Real, x::Real) = tdistlogcdf(ν, -x)

function tdistinvcdf::T, p::T) where T<:Real
if isinf(ν)
return norminvcdf(p)
elseif p < 0.5
return -sqrt(fdistinvccdf(one(ν), ν, 2*p))
else
return sqrt(fdistinvccdf(one(ν), ν, 2*(1 - p)))
end
end
tdistinvcdf::Real, p::Real) = tdistinvcdf(map(float, promote(ν, p))...)

tdistinvccdf::Real, p::Real) = -tdistinvcdf(ν, p)

if VERSION < v"1.7.0-DEV.1172"
function _expm1(x::Float16)
if -0.2 < x < 0.1
return @evalpoly(x, Float16(0), Float16(1), Float16(1/2), Float16(1/6), Float16(1/24), Float16(1/120))
else
return exp(x) - 1
end
end
end
_expm1(x::Number) = expm1(x)

function tdistinvlogcdf::T, logp::T) where T<:Real
if isinf(ν)
return norminvlogcdf(logp)
elseif logp < -log(2)
return -sqrt(fdistinvlogccdf(one(ν), ν, logp + logtwo))
else
return sqrt(fdistinvccdf(one(ν), ν, -2*_expm1(logp)))
end
end
tdistinvlogcdf::Real, logp::Real) = tdistinvlogcdf(map(float, promote(ν, logp))...)

tdistinvlogccdf::Real, logp::Real) = -tdistinvlogcdf(ν, logp)

0 comments on commit 12c838e

Please sign in to comment.