{-# LANGUAGE RebindableSyntax #-}
module Data.YAP.Ratio
( Ratio
, Rational
, (%)
, numerator
, denominator
, approxRational
) where
import Prelude.YAP
import Data.YAP.Algebra (ToRational(..))
import Data.YAP.Algebra.Internal (Ratio(..), (%), numerator, denominator)
approxRational :: (ToRational a) => a -> a -> Rational
approxRational :: forall a. ToRational a => a -> a -> Rational
approxRational a
rat a
eps =
Rational -> Rational -> Rational
forall {a}. (Ring a, ToRational a) => a -> a -> Rational
simplest (a -> Rational
forall a. ToRational a => a -> Rational
toRational a
rat Rational -> Rational -> Rational
forall a. AbelianGroup a => a -> a -> a
- a -> Rational
forall a. ToRational a => a -> Rational
toRational a
eps) (a -> Rational
forall a. ToRational a => a -> Rational
toRational a
rat Rational -> Rational -> Rational
forall a. AdditiveMonoid a => a -> a -> a
+ a -> Rational
forall a. ToRational 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. ToRational 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. ToRational 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. AdditiveMonoid 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. Semiring a => a -> a -> a
*a
n''a -> a -> a
forall a. AdditiveMonoid 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''