{- The Taylor series for the exponential function e^x: e^z = lim n|->inf \Sum_{n=1}^inf z^n / n! See: http://en.wikipedia.org/wiki/Power_series See the corresponding C+GMP version for comparison Compile: ghc -O2 -o p_circ power_circ.hs Run: ./p_circ 4000 10 Measure: time ./p_circ 4000 10 1>/dev/null -} import System.Environment import Control.Monad import Data.Ratio fact 0 = 1 fact n = n*(fact (n-1)) -- compute e^z up to d digits power_e :: Integer -> Integer -> Rational power_e z d = sum (takeWhile (>(1 % (10^d))) taylor) where -- infinite list of entire Taylor series taylor = [ (pow_ints!!n % 1) / (factorials!!n % 1) | n<-[0,1..] ] -- 2 circular lists, to memoise earlier computations factorials = 1:1:[ (toInteger i)*(factorials!!(i-1)) | i<-[2..] ] pow_ints = 1:[ z*(pow_ints!!(i-1)) | i<-[1..] ] main = do args <- getArgs let (z:d:_) = map read args :: [Integer] let res = power_e z d putStrLn $ "e^"++(show z)++" with a precision of "++(show d)++" digits is "++(show ((fromRational res)::Double)) putStrLn $ " or as Rational " ++(show res) putStrLn $ "Expected result: " ++(show (exp (fromInteger z)))