ref: 60e96185f08ab8f36698c16c41633bc3a4295b77
dir: /lib/Data/Ratio.hs/
module Data.Ratio(
Ratio, Rational,
(%),
numerator, denominator,
rationalInfinity,
rationalNaN,
rationalMinusZero,
) where
import Prelude() -- do not import Prelude
import Data.Bool
import Data.Eq
import Data.Fractional
import Data.Function
import Data.Integer
import Data.Integral
import Data.Num
import Data.Ord
import Data.Ratio_Type
import Data.Real
import Text.Show
{- in Data.Ratio_Type
data Ratio a = !a :% !a
-}
-- The value x :% y represents the rational number x/y.
-- The y is always >= 0, and the number is in reduced for,
-- i.e., there are no common factor > 1 for x and y.
-- In addition to the ordinary rationals, we use the "wheel"
-- extension of the rationals.
-- This means that the / operation is total. In particular
-- x/0 == 1/0 == rationalInfinity, when x/=0
-- 0/0 == rationalNaN (often called perp for wheels).
-- Wheels obey most of the usual algebraic laws for rationals,
-- but the distributive law has to be augmented to work for all
-- numbers.
-- (x + y) * z + 0*z == x*z + y*z
-- When z is a normal rational number the is clearly the same
-- as the usual distributive law.
--
-- NOTE. Experimentally, we extend this with:
-- x/0 == 1/0 when x > 0
-- x/0 == -1/0 when x < 0
instance forall a . Eq a => Eq (Ratio a) where
(x :% y) == (x' :% y') = x == x' && y == y'
instance forall a . (Integral a, Ord a) => Ord (Ratio a) where
(x :% y) <= (x' :% y') = x * y' <= x' * y
(x :% y) < (x' :% y') = x * y' < x' * y
(x :% y) >= (x' :% y') = x * y' >= x' * y
(x :% y) > (x' :% y') = x * y' > x' * y
instance forall a . (Integral a, Ord a) => Num (Ratio a) where
(x:%y) + (x':%y') = reduce (x*y' + x'*y) (y*y')
(x:%y) - (x':%y') = reduce (x*y' - x'*y) (y*y')
(x:%y) * (x':%y') = reduce (x * x') (y * y')
negate (x:%y) = negate x :% y
abs (x:%y) = abs x :% y
signum (x:%_) = signum x :% 1
fromInteger x = fromInteger x :% 1
instance forall a . (Integral a, Ord a) => Fractional (Ratio a) where
(x:%y) / (x':%y') = reduce (x*y') (y*x')
recip (x:%y)
| x < 0 = (-y) :% (-x)
| otherwise = y :% x
fromRational (x:%y) = fromInteger x % fromInteger y
instance forall a . (Show a) => Show (Ratio a) where
showsPrec p (x:%y) = showParen (p > 7) $
showsPrec 8 x .
showString " % " .
showsPrec 8 y
instance forall a . (Integral a, Ord a) => Real (Ratio a) where
toRational (x :% y) = toInteger x :% toInteger y
rationalInfinity :: Rational
rationalInfinity = 1 :% 0
rationalNaN :: Rational
rationalNaN = 0 :% 0
rationalMinusZero :: Rational
rationalMinusZero = 0 :% (-1)
infixl 7 %
(%) :: forall a . (Integral a, Ord a) => a -> a -> Ratio a
x % y = reduce x y
reduce :: forall a . (Ord a, Integral a) => a -> a -> Ratio a
reduce x y | y > 0 = let d = gcd x y in (x `quot` d) :% (y `quot` d)
| y < 0 = reduce (- x) (- y)
| otherwise = signum x :% 0
numerator :: forall a . Ratio a -> a
numerator (x :% _) = x
denominator :: forall a . Ratio a -> a
denominator (_ :% y) = y