{-# LANGUAGE Safe #-}
module Data.Ratio
( Ratio
, Rational
, (%)
, numerator
, denominator
, approxRational
) where
import GHC.Real
approxRational :: (RealFrac a) => a -> a -> Rational
approxRational :: forall a. RealFrac a => a -> a -> Rational
approxRational a
rat a
eps =
Rational -> Rational -> Rational
forall {a}. Real a => a -> a -> Rational
simplest (a -> Rational
forall a. Real a => a -> Rational
toRational a
rat Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
- a -> Rational
forall a. Real a => a -> Rational
toRational a
eps) (a -> Rational
forall a. Real a => a -> Rational
toRational a
rat Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
+ a -> Rational
forall a. Real a => a -> Rational
toRational a
eps)
where
simplest :: a -> a -> Rational
simplest a
x a
y
| a
y a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
x = a -> a -> Rational
simplest a
y a
x
| a
x a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
y = Rational
xr
| a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
0 = Integer -> Integer -> Integer -> Integer -> Rational
forall {p}. Integral p => p -> p -> p -> p -> Ratio p
simplest' Integer
n Integer
d Integer
n' Integer
d'
| a
y a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
0 = - Integer -> Integer -> Integer -> Integer -> Rational
forall {p}. Integral p => p -> p -> p -> p -> Ratio p
simplest' (-Integer
n') Integer
d' (-Integer
n) Integer
d
| Bool
otherwise = Integer
0 Integer -> Integer -> Rational
forall a. a -> a -> Ratio a
:% Integer
1
where xr :: Rational
xr = a -> Rational
forall a. Real a => a -> Rational
toRational a
x
n :: Integer
n = Rational -> Integer
forall a. Ratio a -> a
numerator Rational
xr
d :: Integer
d = Rational -> Integer
forall a. Ratio a -> a
denominator Rational
xr
nd' :: Rational
nd' = a -> Rational
forall a. Real a => a -> Rational
toRational a
y
n' :: Integer
n' = Rational -> Integer
forall a. Ratio a -> a
numerator Rational
nd'
d' :: Integer
d' = Rational -> Integer
forall a. Ratio a -> a
denominator Rational
nd'
simplest' :: p -> p -> p -> p -> Ratio p
simplest' p
n p
d p
n' p
d'
| p
r p -> p -> Bool
forall a. Eq a => a -> a -> Bool
== p
0 = p
q p -> p -> Ratio p
forall a. a -> a -> Ratio a
:% p
1
| p
q p -> p -> Bool
forall a. Eq a => a -> a -> Bool
/= p
q' = (p
qp -> p -> p
forall a. Num a => a -> a -> a
+p
1) p -> p -> Ratio p
forall a. a -> a -> Ratio a
:% p
1
| Bool
otherwise = (p
qp -> p -> p
forall a. Num a => a -> a -> a
*p
n''p -> p -> p
forall a. Num a => a -> a -> a
+p
d'') p -> p -> Ratio p
forall a. a -> a -> Ratio a
:% p
n''
where (p
q,p
r) = p -> p -> (p, p)
forall a. Integral a => a -> a -> (a, a)
quotRem p
n p
d
(p
q',p
r') = p -> p -> (p, p)
forall a. Integral a => a -> a -> (a, a)
quotRem p
n' p
d'
nd'' :: Ratio p
nd'' = p -> p -> p -> p -> Ratio p
simplest' p
d' p
r' p
d p
r
n'' :: p
n'' = Ratio p -> p
forall a. Ratio a -> a
numerator Ratio p
nd''
d'' :: p
d'' = Ratio p -> p
forall a. Ratio a -> a
denominator Ratio p
nd''