2 % (c) The AQUA Project, Glasgow University, 1994-1999
5 \section[Ratio]{Module @Ratio@}
7 Standard functions on rational numbers
13 , (%) -- :: (Integral a) => a -> a -> Ratio a
14 , numerator -- :: (Integral a) => Ratio a -> a
15 , denominator -- :: (Integral a) => Ratio a -> a
16 , approxRational -- :: (RealFrac a) => a -> a -> Rational
19 -- (Integral a) => Eq (Ratio a)
20 -- (Integral a) => Ord (Ratio a)
21 -- (Integral a) => Num (Ratio a)
22 -- (Integral a) => Real (Ratio a)
23 -- (Integral a) => Fractional (Ratio a)
24 -- (Integral a) => RealFrac (Ratio a)
25 -- (Integral a) => Enum (Ratio a)
26 -- (Read a, Integral a) => Read (Ratio a)
27 -- (Integral a) => Show (Ratio a)
29 -- Implementation checked wrt. Haskell 98 lib report, 1/99.
38 import Prelude -- To generate the dependencies
39 import PrelReal -- The basic defns for Ratio
42 %*********************************************************
44 \subsection{approxRational}
46 %*********************************************************
48 @approxRational@, applied to two real fractional numbers x and epsilon,
49 returns the simplest rational number within epsilon of x. A rational
50 number n%d in reduced form is said to be simpler than another n'%d' if
51 abs n <= abs n' && d <= d'. Any real interval contains a unique
52 simplest rational; here, for simplicity, we assume a closed rational
53 interval. If such an interval includes at least one whole number, then
54 the simplest rational is the absolutely least whole number. Otherwise,
55 the bounds are of the form q%1 + r%d and q%1 + r'%d', where abs r < d
56 and abs r' < d', and the simplest rational is q%1 + the reciprocal of
57 the simplest rational between d'%r' and d%r.
60 approxRational :: (RealFrac a) => a -> a -> Rational
61 approxRational rat eps = simplest (rat-eps) (rat+eps)
62 where simplest x y | y < x = simplest y x
64 | x > 0 = simplest' n d n' d'
65 | y < 0 = - simplest' (-n') d' (-n) d
67 where xr = toRational x
74 simplest' n d n' d' -- assumes 0 < n%d < n'%d'
76 | q /= q' = (q+1) :% 1
77 | otherwise = (q*n''+d'') :% n''
78 where (q,r) = quotRem n d
79 (q',r') = quotRem n' d'
80 nd'' = simplest' d' r' d r
82 d'' = denominator nd''
89 -- Hugs already has this functionally inside its prelude