Logic.hs 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. -- Calculate and store values of Pi.
  2. module Logic (hexDigits) where
  3. import Control.Parallel (par)
  4. import Data.Char (intToDigit)
  5. import Numeric (showIntAtBase)
  6. -- Get the hex digit of Pi at place n.
  7. hexPi :: Integer -> Integer
  8. hexPi n =
  9. let
  10. summation = let
  11. sOne = (4 * sumPi n 1)
  12. sFour = (2 * sumPi n 4)
  13. sFive = (sumPi n 5)
  14. sSix = (sumPi n 6)
  15. in
  16. sOne `par` sFour `par` sFive `par` sSix `par` sOne - sFour - sFive - sSix
  17. skimmedSum = summation - (fromIntegral (floor summation :: Integer)) -- Take only the decimal portion
  18. in
  19. floor (16 * skimmedSum) :: Integer
  20. -- Calculate the summation.
  21. -- 5000 is used in place of Infinity. This value drops off quickly, so no need to go too far.
  22. sumPi :: Integer -> Integer -> Double
  23. sumPi n x =
  24. let
  25. summation1 = sum [(fromIntegral (fastModExp 16 (n-k) ((8*k)+x))) / (fromIntegral ((8*k)+x)) | k <- [0..n]]
  26. summation2 = sum [16^^(n-k) / (fromIntegral ((8*k)+x)) | k <- [(n+1)..5000]]
  27. in
  28. summation1 + summation2
  29. -- The list of answers.
  30. hexDigits :: [Integer]
  31. hexDigits = [hexPi x | x <- [0..]]
  32. -- Calculate a^b mod c.
  33. fastModExp :: Integer -> Integer -> Integer -> Integer
  34. fastModExp a b c =
  35. let
  36. -- Represent b as a binary string, and reverse it.
  37. -- This lets index n indicate 2^n.
  38. revBinaryB = reverse (showIntAtBase 2 intToDigit b "")
  39. powersOfA = [a^(2^n) `mod` c | n <- [0..]]
  40. -- Take only binary powers of a that comprise b.
  41. bPowersOfA = map (\(_, n) -> n) $ filter (\(char, _) -> char == '1') $ zip revBinaryB powersOfA
  42. in
  43. foldr (\m n -> (m * n) `mod` c) 1 bPowersOfA