{-# LANGUAGE FlexibleInstances #-}
module Math.Factorial where

import Data.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 = Integer -> a
forall a. Num a => Integer -> a
fromInteger (Integer -> a) -> (b -> Integer) -> b -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b -> Integer
forall a b. (Factorial a, Integral b) => b -> a
factorial

instance Factorial Integer where
    factorial :: b -> Integer
factorial b
n
        | b
n b -> b -> Bool
forall a. Ord a => a -> a -> Bool
< b
0     = [Char] -> Integer
forall a. HasCallStack => [Char] -> a
error [Char]
"factorial: n < 0"
        | Bool
otherwise = [Integer] -> Integer
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
product [Integer
1..b -> Integer
forall b. Integral b => b -> Integer
toInteger b
n]

instance Factorial Float where
    factorial :: b -> Float
factorial = Double -> Float
double2Float (Double -> Float) -> (b -> Double) -> b -> Float
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b -> Double
forall a b. (Factorial a, Integral b) => b -> a
factorial
instance Factorial (Complex Float) where
    factorial :: b -> Complex Float
factorial = (Float -> Float -> Complex Float
forall a. a -> a -> Complex a
:+ Float
0) (Float -> Complex Float) -> (b -> Float) -> b -> Complex Float
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b -> Float
forall a b. (Factorial a, Integral b) => b -> a
factorial
instance Factorial Double where
    factorial :: b -> Double
factorial b
n
        | b
n b -> b -> Bool
forall a. Ord a => a -> a -> Bool
< b
0         = Double
0Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
0
        | b
n b -> b -> Bool
forall a. Ord a => a -> a -> Bool
< b
forall a. Num a => a
nFacs     = Vector Double
facs Vector Double -> Int -> Double
forall a. Unbox a => Vector a -> Int -> a
V.! b -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral b
n
        | Bool
otherwise     = Double
infinity
        where
            nFacs :: Num a => a
            nFacs :: a
nFacs       = a
171 -- any more is pointless, everything beyond here is "Infinity"
            facs :: Vector Double
facs        = (Double -> Double -> Double)
-> Double -> Vector Double -> Vector Double
forall a b.
(Unbox a, Unbox b) =>
(a -> b -> a) -> a -> Vector b -> Vector a
V.scanl Double -> Double -> Double
forall a. Num a => a -> a -> a
(*) Double
1 (Double -> Int -> Vector Double
forall a. (Unbox a, Num a) => a -> Int -> Vector a
V.enumFromN Double
1 Int
forall a. Num a => a
nFacs)
            infinity :: Double
infinity    = Vector Double
facs Vector Double -> Int -> Double
forall a. Unbox a => Vector a -> Int -> a
V.! Int
forall a. Num a => a
nFacs
instance Factorial (Complex Double) where
    factorial :: b -> Complex Double
factorial = (Double -> Double -> Complex Double
forall a. a -> a -> Complex a
:+ Double
0) (Double -> Complex Double) -> (b -> Double) -> b -> Complex Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b -> Double
forall a b. (Factorial a, Integral b) => b -> a
factorial