Logic.hs 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546
  1. -- Calculate and store values of Pi.
  2. module Logic (hexDigits) where
  3. import Data.Bits (testBit, shiftR)
  4. import Control.Parallel.Strategies
  5. -- Get the hex digit of Pi at place n.
  6. hexPi :: Integer -> Integer
  7. hexPi n =
  8. let
  9. summation = (4 * sumPi n 1) - (2 * sumPi n 4) - (sumPi n 5) - (sumPi n 6)
  10. in
  11. floor (16 * skim summation) :: Integer
  12. -- Calculate the summation.
  13. -- n+5000 is used in place of Infinity. This value drops off quickly, so no need to go too far.
  14. sumPi :: Integer -> Integer -> Double
  15. sumPi n x =
  16. let
  17. summation1 = sum ([skim $ (fromIntegral (modExp 16 (n-k) ((8*k)+x))) / (fromIntegral ((8*k)+x)) | k <- [0..n]] `using` parList rseq)
  18. summation2 = sum ([skim $ (16^^(n-k)) / (fromIntegral ((8*k)+x)) | k <- [(n+1)..(n+5000)]] `using` parList rseq)
  19. in
  20. summation1 + summation2
  21. -- Take only the decimal portion of a number.
  22. skim :: Double -> Double
  23. skim n
  24. | n == (read "Infinity" :: Double) = 0 -- Without this check, skim returns NaN
  25. | otherwise = n - fromIntegral (floor n :: Integer)
  26. -- The list of answers.
  27. hexDigits :: [Integer]
  28. hexDigits = [hexPi x | x <- [0..]]
  29. modExp :: Integer -> Integer -> Integer -> Integer
  30. modExp _ 0 _ = 1
  31. modExp a b c =
  32. let
  33. n = if testBit b 0 then a `mod` c else 1
  34. in
  35. n * modExp ((a^2) `mod` c) (shiftR b 1) c `mod` c