ratio-int (empty) → 0.1
raw patch · 3 files changed
+105/−0 lines, 3 filesdep +basesetup-changed
Dependencies added: base
Files
- Data/RatioInt.hs +78/−0
- Setup.hs +2/−0
- ratio-int.cabal +25/−0
+ Data/RatioInt.hs view
@@ -0,0 +1,78 @@+{-# LANGUAGE BangPatterns #-}+-- | Provides a specialised version of 'Data.Ratio' for 'Int'.+--+-- Runs about ten times faster than 'Data.Ratio' while being half as fast as+-- floating-point types.+module Data.RatioInt (RatioInt (numerator, denominator), (%)) where++import qualified Data.Ratio as R++-- | Rational numbers, with numerator and denominator of the 'Int' type.+data RatioInt = RatioInt {+ numerator :: {-# UNPACK #-} !Int+ , denominator :: {-# UNPACK #-} !Int+ } deriving (Eq, Show, Read)++ratioZeroDenominatorError :: a+ratioZeroDenominatorError = error "Division by zero"++-- | Forms the ratio of two 'Int' numbers.+(%) :: Int -> Int -> RatioInt+x % y = reduce (x * signum y) (abs y)+infixl 7 %++reduce :: Int -> Int -> RatioInt+reduce _ 0 = ratioZeroDenominatorError+reduce !x !y = let d = gcd x y+ in RatioInt (x `quot` d) (y `quot` d)++-- Instances -------------------------------------------------------------------++instance Ord RatioInt where+ RatioInt x y <= RatioInt x' y' = x * y' <= x' * y+ RatioInt x y < RatioInt x' y' = x * y' < x' * y++instance Num RatioInt where+ RatioInt x y + RatioInt x' y' = reduce (x * y' + x' * y) (y * y')+ RatioInt x y - RatioInt x' y' = reduce (x * y' - x' * y) (y * y')+ RatioInt x y * RatioInt x' y' = reduce (x * x') (y * y')++ negate (RatioInt x y) = RatioInt (-x) y+ abs (RatioInt x y) = RatioInt (abs x) y+ signum (RatioInt x _) = RatioInt (signum x) 1+ fromInteger x = RatioInt (fromInteger x) 1++instance Fractional RatioInt where+ (RatioInt x y) / (RatioInt x' y') = (x * y') % (y * x')++ recip (RatioInt 0 _) = ratioZeroDenominatorError+ recip (RatioInt x y)+ | x < 0 = RatioInt (negate y) (negate x)+ | otherwise = RatioInt x y++ fromRational r = fromInteger (R.numerator r) % fromInteger (R.denominator r)++instance Real RatioInt where+ toRational (RatioInt x y) = toInteger x R.% toInteger y++instance RealFrac RatioInt where+ properFraction (RatioInt x y) = let (q, r) = x `quotRem` y+ in (fromIntegral q, RatioInt r y)+ truncate (RatioInt x y) = fromIntegral (x `quot` y)++instance Enum RatioInt where+ succ x = x + 1+ pred x = x - 1++ toEnum n = RatioInt n 1+ fromEnum = truncate++ enumFrom !n = n : enumFrom (n + 1)+ enumFromThen !n !m = n : enumFromThen m (m + m - n)+ enumFromTo !n !m = takeWhile (<= m + 1 / 2) (enumFrom n)+ enumFromThenTo !n !m !p =+ takeWhile predicate (enumFromThen n m)+ where+ mid = (m - n) / 2+ predicate | m >= n = (<= p + mid)+ | otherwise = (>= p + mid)
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ ratio-int.cabal view
@@ -0,0 +1,25 @@+name: ratio-int+version: 0.1+license: BSD3+author: Raphael Javaux <raphaeljavaux[at]gmail.com>+maintainer: Raphael Javaux <raphaeljavaux[at]gmail.com>+synopsis: Fast specialisation of Data.Ratio for Int.+description: Fast specialisation of Data.Ratio for Int.+ .+ Runs about ten times faster than Data.Int while being half+ as fast as floating-point types.+category: Math+cabal-version: >= 1.9.2+build-type: Simple+homepage: https://github.com/RaphaelJ/ratio-int++library+ exposed-modules: Data.RatioInt++ ghc-options: -Wall -O2++ build-depends: base >= 4 && < 5++source-repository head+ type: git+ location: https://github.com/RaphaelJ/ratio-int