exact-pi 0.4.0.0 → 0.4.1.0
raw patch · 3 files changed
+31/−3 lines, 3 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Data.ExactPi: rationalApproximations :: ExactPi -> [Rational]
Files
- changelog.md +4/−0
- exact-pi.cabal +1/−1
- src/Data/ExactPi.hs +26/−2
changelog.md view
@@ -1,3 +1,7 @@+0.4.1.0 +------- +* Added function for computing rational approximations of ExactPi values. + 0.4.0.0 ------- * Added simpler constraints for converting ExactPi types to terms with the minimal context.
exact-pi.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/ name: exact-pi -version: 0.4.0.0 +version: 0.4.1.0 synopsis: Exact rational multiples of pi (and integer powers of pi) description: Provides an exact representation for rational multiples of pi alongside an approximate representation of all reals. Useful for storing and computing with conversion factors between physical units.
src/Data/ExactPi.hs view
@@ -27,12 +27,13 @@ isExactInteger, toExactInteger, isExactRational, - toExactRational + toExactRational, + rationalApproximations ) where import Data.Monoid -import Data.Ratio (numerator, denominator) +import Data.Ratio ((%), numerator, denominator) import Prelude -- | Represents an exact or approximate real value. @@ -92,6 +93,29 @@ toExactRational :: ExactPi -> Maybe Rational toExactRational (Exact 0 q) = Just q toExactRational _ = Nothing + +-- | Converts an 'ExactPi' to a list of increasingly accurate rational approximations, on alternating +-- sides of the actual value. Note that 'Approximate' values are converted using the 'Real' instance +-- for 'Double' into a singleton list. Note that exact rationals are also converted into a singleton list. +-- +-- Implementation based on work by Anders Kaseorg shared at http://qr.ae/RbXl8M. +rationalApproximations :: ExactPi -> [Rational] +rationalApproximations (Approximate x) = [toRational (x :: Double)] +rationalApproximations (Exact 0 q) = [q] +rationalApproximations (Exact z q) = fmap (\pi' -> q * (pi' ^^ z)) piConvergents + where + piConvergents :: [Rational] + piConvergents = go True 2 4 where + go s p' q' | ltPi m = [q' | not s] ++ go True m q' + | otherwise = [p' | s] ++ go False p' m where + m = (numerator p' + numerator q')%(denominator p' + denominator q') + ltPi :: Rational -> Bool + ltPi x = ok x 1 where + ok y i = + y <= (27*i - 12)%5 || + (y < (675*i - 216)%125 && + ok ((y - fromInteger (5*i - 2))*(3*(3*i + 1)*(3*i + 2)%(i*(2*i - 1)))) + (i + 1)) instance Show ExactPi where show (Exact z q) | z == 0 = "Exactly " ++ show q