{-# LANGUAGE FlexibleInstances #-} module Math.Factorial ( Factorial (..) ) where import Data.Complex (Complex (..)) import qualified Data.Vector.Unboxed as V import GHC.Float (double2Float) -- |Factorial function 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 -- any more is pointless, everything beyond here is "Infinity" facs = V.scanl (*) 1 (V.enumFromN 1 nFacs) infinity = facs V.! nFacs instance Factorial (Complex Double) where factorial = (:+ 0) . factorial