{-# LANGUAGE BangPatterns #-} import Data.List import Data.Ratio facs :: [Integer] facs = 1 : zipWith (*) [1..] facs tangents :: [Integer] tangents = go 1 facs where go k (!x : xs) = x : go (k + 1) (go' 0 x xs) go' !j !x (!y : ys) = let z = j * x + (j + 2) * y in z `seq` z : go' (j + 1) z ys tangent = genericIndex tangents bernoulli :: Integer -> Rational bernoulli 0 = 1 bernoulli 1 = -0.5 bernoulli n | odd n = 0 bernoulli n = negateIfOdd (n `div` 2) $ (n * tangent (n `div` 2 - 1)) % (2 ^ n - 4 ^ n) where negateIfOdd n = if even n then id else negate