{-# 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 {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''