exact-pi (empty) → 0.1.0.0
raw patch · 5 files changed
+157/−0 lines, 5 filesdep +basedep +groupssetup-changed
Dependencies added: base, groups
Files
- LICENSE +20/−0
- README.md +2/−0
- Setup.hs +2/−0
- exact-pi.cabal +32/−0
- src/Data/ExactPi.hs +101/−0
+ LICENSE view
@@ -0,0 +1,20 @@+Copyright (c) 2015 Douglas McClean + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ README.md view
@@ -0,0 +1,2 @@+# exact-pi +Exact rational multiples of pi (and integer powers of pi) in Haskell
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple +main = defaultMain
+ exact-pi.cabal view
@@ -0,0 +1,32 @@+-- Initial exact-pi.cabal generated by cabal init. For further +-- documentation, see http://haskell.org/cabal/users-guide/ + +name: exact-pi +version: 0.1.0.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. +homepage: https://github.com/dmcclean/exact-pi +license: MIT +license-file: LICENSE +author: Douglas McClean +maintainer: douglas.mcclean@gmail.com +-- copyright: +category: Data +build-type: Simple +extra-source-files: README.md +cabal-version: >=1.10 + +library + exposed-modules: Data.ExactPi + -- other-modules: + -- other-extensions: + build-depends: base >=4.8 && <4.9, + groups >= 0.4 && < 0.5 + hs-source-dirs: src + default-language: Haskell2010 + +source-repository head + type: git + location: https://github.com/dmcclean/exact-pi.git +
+ src/Data/ExactPi.hs view
@@ -0,0 +1,101 @@+{-# LANGUAGE RankNTypes #-} + +{-# OPTIONS_HADDOCK show-extensions #-} + +{-| +Module : Kaos.Math.AugmentedRational +Description : Exact rational multiples of powers of pi +License : MIT +Maintainer : douglas.mcclean@gmail.com +Stability : experimental + +This type is sufficient to exactly express the closure of Q ∪ {π} under multiplication and division. +As a result it is useful for representing conversion factors +between physical units. Approximate values are included both to close the remainder +of the arithmetic operations in the `Num` typeclass and to encode conversion +factors defined experimentally. +-} +module Data.ExactPi +( + ExactPi(..), + approximateValue, + isExactZero +) +where + +import Data.Group + +-- | Represents an exact or approximate real value. +-- The exactly representable values are rational multiples of an integer power of pi. +data ExactPi = Exact Integer Rational -- ^ @'Exact' z q@ = q * pi^z. Note that this means there are many representations of zero. + | Approximate (forall a.Floating a => a) -- ^ An approximate value. This representation was chosen because it allows conversion to floating types using their native definition of 'pi'. + +-- | Approximates an exact or approximate value, converting it to a `Floating` type. +-- This uses the value of `pi` supplied by the destination type, to provide the appropriate +-- precision. +approximateValue :: Floating a => ExactPi -> a +approximateValue (Exact z q) = (pi ^ z) * (fromRational q) +approximateValue (Approximate x) = x + +-- | Identifies whether an 'ExactPi' is an exact representation of zero. +isExactZero :: ExactPi -> Bool +isExactZero (Exact _ 0) = True +isExactZero _ = False + +instance Show ExactPi where + show (Exact z q) | z == 0 = "Exactly " ++ show q + | z == 1 = "Exactly pi * " ++ show q + | otherwise = "Exactly pi^" ++ show z ++ " * " ++ show q + show (Approximate x) = "Approximately " ++ show (x :: Double) + +instance Num ExactPi where + fromInteger n = Exact 0 (fromInteger n) + (Exact z1 q1) * (Exact z2 q2) = Exact (z1 + z2) (q1 * q2) + (Exact _ 0) * _ = 0 + _ * (Exact _ 0) = 0 + x * y = Approximate $ approximateValue x * approximateValue y + (Exact z1 q1) + (Exact z2 q2) | z1 == z2 = Exact z1 (q1 + q2) -- by distributive property + x + y = Approximate $ approximateValue x + approximateValue y + abs (Exact z q) = Exact z (abs q) + abs (Approximate x) = Approximate $ abs x + signum (Exact _ q) = Exact 0 (signum q) + signum (Approximate x) = Approximate $ signum x -- we leave this tagged as approximate because we don't know "how" approximate the input was. a case could be made for exact answers here. + negate x = (-1) * x + +instance Fractional ExactPi where + fromRational = Exact 0 + recip (Exact z q) = Exact z (recip q) + +instance Floating ExactPi where + pi = Exact 1 1 + exp x | isExactZero x = 1 + | otherwise = approx1 exp x + log (Exact 0 1) = 0 + log x = approx1 log x + -- It would be possible to give tighter bounds to the trig functions, preserving exactness for arguments that have an exactly representable result. + sin = approx1 sin + cos = approx1 cos + tan = approx1 tan + asin = approx1 asin + atan = approx1 atan + acos = approx1 acos + sinh = approx1 sinh + cosh = approx1 cosh + tanh = approx1 tanh + asinh = approx1 asinh + acosh = approx1 acosh + atanh = approx1 atanh + +approx1 :: (forall a.Floating a => a -> a) -> ExactPi -> ExactPi +approx1 f x = Approximate (f (approximateValue x)) + +-- | The multiplicative monoid over augmented rationals. +instance Monoid ExactPi where + mempty = 1 + mappend = (*) + +-- | The multiplicative group over augmented rationals. +instance Group ExactPi where + invert = recip + +instance Abelian ExactPi