Skip to content

Commit

Permalink
Improve precision for large NDF (#214)
Browse files Browse the repository at this point in the history
For large ndf fraction `ndf / (ndf + x*x)` becomes close to 1 and
taking logarithm loses precision. It's better to rewrite

log(ndf / (ndf + x²)) = -log(1 + x²/ndf) = -log1p(x²/ndf)
  • Loading branch information
Shimuuar authored Feb 16, 2025
1 parent e629285 commit 1fb9e45
Showing 1 changed file with 4 additions and 3 deletions.
7 changes: 4 additions & 3 deletions Statistics/Distribution/StudentT.hs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import Data.Binary (Binary(..))
import Data.Data (Data, Typeable)
import GHC.Generics (Generic)
import Numeric.SpecFunctions (
logBeta, incompleteBeta, invIncompleteBeta, digamma)
logBeta, incompleteBeta, invIncompleteBeta, digamma, log1p)

import qualified Statistics.Distribution as D
import Statistics.Distribution.Transform (LinearTransform (..))
Expand Down Expand Up @@ -94,8 +94,9 @@ complCumulative (StudentT ndf) x


logDensityUnscaled :: StudentT -> Double -> Double
logDensityUnscaled (StudentT ndf) x =
log (ndf / (ndf + x*x)) * (0.5 * (1 + ndf)) - logBeta 0.5 (0.5 * ndf)
logDensityUnscaled (StudentT ndf) x
= log1p (x*x/ndf) * (-(0.5 * (1 + ndf)))
- logBeta 0.5 (0.5 * ndf)

quantile :: StudentT -> Double -> Double
quantile (StudentT ndf) p
Expand Down

0 comments on commit 1fb9e45

Please sign in to comment.