summaryrefslogtreecommitdiff
path: root/libraries/base/Data/Ratio.hs
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/base/Data/Ratio.hs')
-rw-r--r--libraries/base/Data/Ratio.hs49
1 files changed, 27 insertions, 22 deletions
diff --git a/libraries/base/Data/Ratio.hs b/libraries/base/Data/Ratio.hs
index 8517e485ff..946824fec2 100644
--- a/libraries/base/Data/Ratio.hs
+++ b/libraries/base/Data/Ratio.hs
@@ -47,27 +47,32 @@ import GHC.Real -- The basic defns for Ratio
-- and abs r' < d', and the simplest rational is q%1 + the reciprocal of
-- the simplest rational between d'%r' and d%r.
-approxRational :: (RealFrac a) => a -> a -> Rational
-approxRational rat eps = simplest (rat-eps) (rat+eps)
- where simplest x y | y < x = simplest y x
- | x == y = xr
- | x > 0 = simplest' n d n' d'
- | y < 0 = - simplest' (-n') d' (-n) d
- | otherwise = 0 :% 1
- where xr = toRational x
- n = numerator xr
- d = denominator xr
- nd' = toRational y
- n' = numerator nd'
- d' = denominator nd'
+approxRational :: (RealFrac a) => a -> a -> Rational
+approxRational rat eps =
+ -- We convert rat and eps to rational *before* subtracting/adding since
+ -- otherwise we may overflow. This was the cause of #14425.
+ simplest (toRational rat - toRational eps) (toRational rat + toRational eps)
+ where
+ simplest x y
+ | y < x = simplest y x
+ | x == y = xr
+ | x > 0 = simplest' n d n' d'
+ | y < 0 = - simplest' (-n') d' (-n) d
+ | otherwise = 0 :% 1
+ where xr = toRational x
+ n = numerator xr
+ d = denominator xr
+ nd' = toRational y
+ n' = numerator nd'
+ d' = denominator nd'
- simplest' n d n' d' -- assumes 0 < n%d < n'%d'
- | r == 0 = q :% 1
- | q /= q' = (q+1) :% 1
- | otherwise = (q*n''+d'') :% n''
- where (q,r) = quotRem n d
- (q',r') = quotRem n' d'
- nd'' = simplest' d' r' d r
- n'' = numerator nd''
- d'' = denominator nd''
+ simplest' n d n' d' -- assumes 0 < n%d < n'%d'
+ | r == 0 = q :% 1
+ | q /= q' = (q+1) :% 1
+ | otherwise = (q*n''+d'') :% n''
+ where (q,r) = quotRem n d
+ (q',r') = quotRem n' d'
+ nd'' = simplest' d' r' d r
+ n'' = numerator nd''
+ d'' = denominator nd''