{-# LANGUAGE CPP #-}

module Math.Combinatrics.Double where

import qualified Data.Vector.Unboxed as U

#define LOG_FACT_CACHE_SIZE 1024

logFactCache :: U.Vector Double
logFactCache :: Vector Double
logFactCache =
  (Double -> Double -> Double)
-> Double -> Vector Double -> Vector Double
forall a b.
(Unbox a, Unbox b) =>
(a -> b -> a) -> a -> Vector b -> Vector a
U.scanl' Double -> Double -> Double
forall a. Num a => a -> a -> a
(+) Double
0.0 (Vector Double -> Vector Double) -> Vector Double -> Vector Double
forall a b. (a -> b) -> a -> b
$
    Int -> (Int -> Double) -> Vector Double
forall a. Unbox a => Int -> (Int -> a) -> Vector a
U.generate LOG_FACT_CACHE_SIZE (log . fromIntegral . (+ 1))
{-# NOINLINE logFactCache #-}

logFact :: Int -> Double
logFact :: Int -> Double
logFact = Vector Double -> Int -> Double
forall a. Unbox a => Vector a -> Int -> a
U.unsafeIndex Vector Double
logFactCache
{-# INLINE logFact #-}

logPerm :: Int -> Int -> Double
logPerm :: Int -> Int -> Double
logPerm Int
n Int
k = Int -> Double
logFact Int
n Double -> Double -> Double
forall a. Num a => a -> a -> a
- Int -> Double
logFact (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
k)
{-# INLINE logPerm #-}

logComb :: Int -> Int -> Double
logComb :: Int -> Int -> Double
logComb Int
n Int
k = Int -> Double
logFact Int
n Double -> Double -> Double
forall a. Num a => a -> a -> a
- Int -> Double
logFact Int
k Double -> Double -> Double
forall a. Num a => a -> a -> a
- Int -> Double
logFact (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
k)
{-# INLINE logComb #-}