{-# LANGUAGE Safe #-}
module Data.Ratio
( Ratio
, Rational
, (%)
, numerator
, denominator
, approxRational
) where
import GHC.Real
approxRational :: (RealFrac a) => a -> a -> Rational
approxRational :: 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 a. Integral a => a -> a -> a -> a -> Ratio a
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 a. Integral a => a -> a -> a -> a -> Ratio a
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' :: a -> a -> a -> a -> Ratio a
simplest' a
n a
d a
n' a
d'
| a
r a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0 = a
q a -> a -> Ratio a
forall a. a -> a -> Ratio a
:% a
1
| a
q a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
q' = (a
qa -> a -> a
forall a. Num a => a -> a -> a
+a
1) a -> a -> Ratio a
forall a. a -> a -> Ratio a
:% a
1
| Bool
otherwise = (a
qa -> a -> a
forall a. Num a => a -> a -> a
*a
n''a -> a -> a
forall a. Num a => a -> a -> a
+a
d'') a -> a -> Ratio a
forall a. a -> a -> Ratio a
:% a
n''
where (a
q,a
r) = a -> a -> (a, a)
forall a. Integral a => a -> a -> (a, a)
quotRem a
n a
d
(a
q',a
r') = a -> a -> (a, a)
forall a. Integral a => a -> a -> (a, a)
quotRem a
n' a
d'
nd'' :: Ratio a
nd'' = a -> a -> a -> a -> Ratio a
simplest' a
d' a
r' a
d a
r
n'' :: a
n'' = Ratio a -> a
forall a. Ratio a -> a
numerator Ratio a
nd''
d'' :: a
d'' = Ratio a -> a
forall a. Ratio a -> a
denominator Ratio a
nd''