{-# LANGUAGE FlexibleInstances #-}
module Math.Factorial
( Factorial (..)
) where
import Data.Complex (Complex (..))
import qualified Data.Vector.Unboxed as V
import GHC.Float (double2Float)
class Num a => Factorial a where
factorial :: Integral b => b -> a
factorial = fromInteger . factorial
instance Factorial Integer where
factorial n
| n < 0 = error "factorial: n < 0"
| otherwise = product [1..toInteger n]
instance Factorial Float where
factorial = double2Float . factorial
instance Factorial (Complex Float) where
factorial = (:+ 0) . factorial
instance Factorial Double where
factorial n
| n < 0 = 0/0
| n < nFacs = facs V.! fromIntegral n
| otherwise = infinity
where
nFacs :: Num a => a
nFacs = 171
facs = V.scanl (*) 1 (V.enumFromN 1 nFacs)
infinity = facs V.! nFacs
instance Factorial (Complex Double) where
factorial = (:+ 0) . factorial