<commit_before>{-|
Module      : TrueSkill.Math
Description : Implements math helper needed for learning and inference.
Copyright   : (c) <NAME>, 2014
License     : BSD2
Maintainer  : <EMAIL>
Stability   : experimental
Portability : portable
-}

module TrueSkill.Math
  ( erf
  , normPdf
  , normCdf
  , monomialGauss
  , choose
  , fac
  , doubleFac
  )
  where

import           TrueSkill.Autodiff

-- | Binomial coefficient.
choose :: Int -> Int -> Int
choose _ 0 = 1
choose 0 _ = 0
choose n k = choose (n-1) (k-1) * n `div` k

-- | Direct implemntation of error function to make it differentiable.
-- Taken from http://en.wikipedia.org/wiki/Error_function
erf :: (Floating d, Ord d) => d -> d
erf x
    | x < 0     = -erf(-x)
    | otherwise = 1 - 1 / (1 +
                           a1*x +
                           a2*x^(2 :: Int) +
                           a3*x^(3 :: Int) +
                           a4*x^(4 :: Int))^(4 :: Int)
  where
    a1 = 0.278393
    a2 = 0.230389
    a3 = 0.000972
    a4 = 0.078108
{-# SPECIALISE erf :: Double -> Double #-}
{-# SPECIALISE erf :: AD -> AD #-}

-- | Cummulative density function of a normal Gaussion distribution.
normCdf :: (Floating d, Ord d) => d -> d
normCdf x = 0.5 * (1 + erf (x / sqrt 2))
{-# SPECIALISE normCdf :: Double -> Double #-}
{-# SPECIALISE normCdf :: AD -> AD #-}

-- | Probability density function of a normal Gaussian distribution.
normPdf :: Floating d => d -> d
normPdf x = exp (-x^(2 :: Int) / 2) / sqrt (2 * pi)
{-# SPECIALISE normPdf :: Double -> Double #-}
{-# SPECIALISE normPdf :: AD -> AD #-}<commit_msg>Adds more precise erf function.<commit_after>{-|
Module      : TrueSkill.Math
Description : Implements math helper needed for learning and inference.
Copyright   : (c) <NAME>, 2014
License     : BSD2
Maintainer  : <EMAIL>
Stability   : experimental
Portability : portable
-}

module TrueSkill.Math
  ( erf
  , normPdf
  , normCdf
  , monomialGauss
  , choose
  , fac
  , doubleFac
  )
  where

import           TrueSkill.Autodiff

-- | Binomial coefficient.
choose :: Int -> Int -> Int
choose _ 0 = 1
choose 0 _ = 0
choose n k = choose (n-1) (k-1) * n `div` k

-- | Direct implemntation of error function to make it differentiable.
-- Taken from http://en.wikipedia.org/wiki/Error_function
erf :: (Floating d, Ord d) => d -> d
erf x
    | x < 0     = -erf (-x)
    | otherwise = 1 - 1 / (1 + a1*x + a2*x**2 + a3*x**3 + a4*x**4 + a5*x**5 +
                           a6*x**6)**16
  where
    a1 = 0.0705230784
    a2 = 0.0422820123
    a3 = 0.0092705272
    a4 = 0.0001520143
    a5 = 0.0002765672
    a6 = 0.0000430638
{-# SPECIALISE erf :: Double -> Double #-}
{-# SPECIALISE erf :: AD -> AD #-}

-- | Cummulative density function of a normal Gaussion distribution.
normCdf :: (Floating d, Ord d) => d -> d
normCdf x = 0.5 * (1 + erf (x / sqrt 2))
{-# SPECIALISE normCdf :: Double -> Double #-}
{-# SPECIALISE normCdf :: AD -> AD #-}

-- | Probability density function of a normal Gaussian distribution.
normPdf :: Floating d => d -> d
normPdf x = exp (-x^(2 :: Int) / 2) / sqrt (2 * pi)
{-# SPECIALISE normPdf :: Double -> Double #-}
{-# SPECIALISE normPdf :: AD -> AD #-}
{'fraction_non_alphanumeric': 0.14773805757671624, 'fraction_numerical': 0.05346409364125277, 'mean_word_length': 2.2665289256198347, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1307347', 'n_tokens_mistral': 1277, 'n_tokens_neox': 1127, 'n_words': 349}