Logic.hs 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. -- Calculate and store values of Pi.
  2. module Logic (hexDigits) where
  3. import Control.Parallel (par)
  4. -- Get the hex digit of Pi at place n.
  5. hexPi :: Integer -> Integer
  6. hexPi n =
  7. let
  8. summation = let
  9. sone = (4 * sumPi n 1)
  10. sfour = (2 * sumPi n 4)
  11. sfive = (sumPi n 5)
  12. ssix = (sumPi n 6)
  13. in
  14. sone `par` sfour `par` sfive `par` ssix `par` sone - sfour - sfive - ssix
  15. skimmedSum = summation - (fromIntegral (floor summation :: Integer)) -- Take only the decimal portion
  16. in
  17. floor (16 * skimmedSum) :: Integer
  18. -- Calculate the summation.
  19. -- 5000 is used in place of Infinity. This value drops off quickly, so no need to go too far.
  20. sumPi :: Integer -> Integer -> Double
  21. sumPi n x =
  22. let
  23. summation1 = sum [(fromIntegral (fastMod 16 (n-k) ((8*k)+x))) / (fromIntegral ((8*k)+x)) | k <- [0..n]]
  24. summation2 = sum [16^^(n-k) / (fromIntegral ((8*k)+x)) | k <- [(n+1)..5000]]
  25. in
  26. summation1 + summation2
  27. -- The list of answers.
  28. hexDigits :: [Integer]
  29. hexDigits = [hexPi x | x <- [0..]]
  30. fastMod :: Integer -> Integer -> Integer -> Integer
  31. fastMod b n k =
  32. let
  33. t = largestT 0 n
  34. in
  35. a b (fromIntegral n) k 1 t
  36. -- Get the largest t such that t^2 <= n
  37. largestT :: Integer -> Integer -> Double
  38. largestT t n
  39. | (2 ^ (t + 1)) <= n = largestT (t + 1) n
  40. | otherwise = 2^^t
  41. a :: Integer -> Double -> Integer -> Integer -> Double -> Integer
  42. a b n k r t =
  43. if n >= t then
  44. let
  45. r' = (b * r) `mod` k
  46. n' = n - t
  47. t' = t / 2
  48. in
  49. if t' >= 1 then
  50. a b n' k ((r' ^ 2) `mod` k) t'
  51. else
  52. r'
  53. else
  54. let t' = t / 2 in
  55. if t' >= 1 then
  56. a b n k ((r ^ 2) `mod` k) t'
  57. else
  58. r