Adjust behaviour of gcd
[ghc-base.git] / GHC / Real.lhs
index 13be142..51d7db4 100644 (file)
@@ -1,11 +1,12 @@
 \begin{code}
-{-# OPTIONS -fno-implicit-prelude #-}
+{-# LANGUAGE CPP, NoImplicitPrelude, MagicHash, UnboxedTuples #-}
+{-# OPTIONS_HADDOCK hide #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  GHC.Real
--- Copyright   :  (c) The FFI Task Force, 1994-2002
+-- Copyright   :  (c) The University of Glasgow, 1994-2002
 -- License     :  see libraries/base/LICENSE
--- 
+--
 -- Maintainer  :  cvs-ghc@haskell.org
 -- Stability   :  internal
 -- Portability :  non-portable (GHC Extensions)
 --
 -----------------------------------------------------------------------------
 
+-- #hide
 module GHC.Real where
 
-import {-# SOURCE #-} GHC.Err
 import GHC.Base
 import GHC.Num
 import GHC.List
 import GHC.Enum
 import GHC.Show
+import GHC.Err
 
 infixr 8  ^, ^^
 infixl 7  /, `quot`, `rem`, `div`, `mod`
+infixl 7  %
 
-default ()             -- Double isn't available yet, 
-                       -- and we shouldn't be using defaults anyway
+default ()              -- Double isn't available yet,
+                        -- and we shouldn't be using defaults anyway
 \end{code}
 
 
 %*********************************************************
-%*                                                     *
+%*                                                      *
 \subsection{The @Ratio@ and @Rational@ types}
-%*                                                     *
+%*                                                      *
 %*********************************************************
 
 \begin{code}
-data  (Integral a)     => Ratio a = !a :% !a  deriving (Eq)
-type  Rational         =  Ratio Integer
+-- | Rational numbers, with numerator and denominator of some 'Integral' type.
+data  Ratio a = !a :% !a  deriving (Eq)
+
+-- | Arbitrary-precision rational numbers, represented as a ratio of
+-- two 'Integer' values.  A rational number may be constructed using
+-- the '%' operator.
+type  Rational          =  Ratio Integer
+
+ratioPrec, ratioPrec1 :: Int
+ratioPrec  = 7  -- Precedence of ':%' constructor
+ratioPrec1 = ratioPrec + 1
+
+infinity, notANumber :: Rational
+infinity   = 1 :% 0
+notANumber = 0 :% 0
+
+-- Use :%, not % for Inf/NaN; the latter would
+-- immediately lead to a runtime error, because it normalises.
 \end{code}
 
 
 \begin{code}
+-- | Forms the ratio of two integral numbers.
 {-# SPECIALISE (%) :: Integer -> Integer -> Rational #-}
-(%)                    :: (Integral a) => a -> a -> Ratio a
-numerator, denominator :: (Integral a) => Ratio a -> a
+(%)                     :: (Integral a) => a -> a -> Ratio a
+
+-- | Extract the numerator of the ratio in reduced form:
+-- the numerator and denominator have no common factor and the denominator
+-- is positive.
+numerator       :: (Integral a) => Ratio a -> a
+
+-- | Extract the denominator of the ratio in reduced form:
+-- the numerator and denominator have no common factor and the denominator
+-- is positive.
+denominator     :: (Integral a) => Ratio a -> a
 \end{code}
 
 \tr{reduce} is a subsidiary function used only in this module .
@@ -57,212 +86,307 @@ their greatest common divisor.
 \begin{code}
 reduce ::  (Integral a) => a -> a -> Ratio a
 {-# SPECIALISE reduce :: Integer -> Integer -> Rational #-}
-reduce _ 0             =  error "Ratio.%: zero denominator"
-reduce x y             =  (x `quot` d) :% (y `quot` d)
-                          where d = gcd x y
+reduce _ 0              =  error "Ratio.%: zero denominator"
+reduce x y              =  (x `quot` d) :% (y `quot` d)
+                           where d = gcd x y
 \end{code}
 
 \begin{code}
-x % y                  =  reduce (x * signum y) (abs y)
+x % y                   =  reduce (x * signum y) (abs y)
 
-numerator   (x :% _)   =  x
-denominator (_ :% y)   =  y
+numerator   (x :% _)    =  x
+denominator (_ :% y)    =  y
 \end{code}
 
 
 %*********************************************************
-%*                                                     *
+%*                                                      *
 \subsection{Standard numeric classes}
-%*                                                     *
+%*                                                      *
 %*********************************************************
 
 \begin{code}
 class  (Num a, Ord a) => Real a  where
-    toRational         ::  a -> Rational
+    -- | the rational equivalent of its real argument with full precision
+    toRational          ::  a -> Rational
 
+-- | Integral numbers, supporting integer division.
+--
+-- Minimal complete definition: 'quotRem' and 'toInteger'
 class  (Real a, Enum a) => Integral a  where
-    quot, rem, div, mod        :: a -> a -> a
-    quotRem, divMod    :: a -> a -> (a,a)
-    toInteger          :: a -> Integer
-
-    n `quot` d         =  q  where (q,_) = quotRem n d
-    n `rem` d          =  r  where (_,r) = quotRem n d
-    n `div` d          =  q  where (q,_) = divMod n d
-    n `mod` d          =  r  where (_,r) = divMod n d
-    divMod n d                 =  if signum r == negate (signum d) then (q-1, r+d) else qr
-                          where qr@(q,r) = quotRem n d
-
+    -- | integer division truncated toward zero
+    quot                :: a -> a -> a
+    -- | integer remainder, satisfying
+    --
+    -- > (x `quot` y)*y + (x `rem` y) == x
+    rem                 :: a -> a -> a
+    -- | integer division truncated toward negative infinity
+    div                 :: a -> a -> a
+    -- | integer modulus, satisfying
+    --
+    -- > (x `div` y)*y + (x `mod` y) == x
+    mod                 :: a -> a -> a
+    -- | simultaneous 'quot' and 'rem'
+    quotRem             :: a -> a -> (a,a)
+    -- | simultaneous 'div' and 'mod'
+    divMod              :: a -> a -> (a,a)
+    -- | conversion to 'Integer'
+    toInteger           :: a -> Integer
+
+    {-# INLINE quot #-}
+    {-# INLINE rem #-}
+    {-# INLINE div #-}
+    {-# INLINE mod #-}
+    n `quot` d          =  q  where (q,_) = quotRem n d
+    n `rem` d           =  r  where (_,r) = quotRem n d
+    n `div` d           =  q  where (q,_) = divMod n d
+    n `mod` d           =  r  where (_,r) = divMod n d
+
+    divMod n d          =  if signum r == negate (signum d) then (q-1, r+d) else qr
+                           where qr@(q,r) = quotRem n d
+
+-- | Fractional numbers, supporting real division.
+--
+-- Minimal complete definition: 'fromRational' and ('recip' or @('/')@)
 class  (Num a) => Fractional a  where
-    (/)                        :: a -> a -> a
-    recip              :: a -> a
-    fromRational       :: Rational -> a
-
-    recip x            =  1 / x
-    x / y              = x * recip y
-
+    -- | fractional division
+    (/)                 :: a -> a -> a
+    -- | reciprocal fraction
+    recip               :: a -> a
+    -- | Conversion from a 'Rational' (that is @'Ratio' 'Integer'@).
+    -- A floating literal stands for an application of 'fromRational'
+    -- to a value of type 'Rational', so such literals have type
+    -- @('Fractional' a) => a@.
+    fromRational        :: Rational -> a
+
+    {-# INLINE recip #-}
+    {-# INLINE (/) #-}
+    recip x             =  1 / x
+    x / y               = x * recip y
+
+-- | Extracting components of fractions.
+--
+-- Minimal complete definition: 'properFraction'
 class  (Real a, Fractional a) => RealFrac a  where
-    properFraction     :: (Integral b) => a -> (b,a)
-    truncate, round    :: (Integral b) => a -> b
-    ceiling, floor     :: (Integral b) => a -> b
-
-    truncate x         =  m  where (m,_) = properFraction x
-    
-    round x            =  let (n,r) = properFraction x
-                              m     = if r < 0 then n - 1 else n + 1
-                          in case signum (abs r - 0.5) of
-                               -1 -> n
-                               0  -> if even n then n else m
-                               1  -> m
-    
-    ceiling x          =  if r > 0 then n + 1 else n
-                          where (n,r) = properFraction x
-    
-    floor x            =  if r < 0 then n - 1 else n
-                          where (n,r) = properFraction x
+    -- | The function 'properFraction' takes a real fractional number @x@
+    -- and returns a pair @(n,f)@ such that @x = n+f@, and:
+    --
+    -- * @n@ is an integral number with the same sign as @x@; and
+    --
+    -- * @f@ is a fraction with the same type and sign as @x@,
+    --   and with absolute value less than @1@.
+    --
+    -- The default definitions of the 'ceiling', 'floor', 'truncate'
+    -- and 'round' functions are in terms of 'properFraction'.
+    properFraction      :: (Integral b) => a -> (b,a)
+    -- | @'truncate' x@ returns the integer nearest @x@ between zero and @x@
+    truncate            :: (Integral b) => a -> b
+    -- | @'round' x@ returns the nearest integer to @x@;
+    --   the even integer if @x@ is equidistant between two integers
+    round               :: (Integral b) => a -> b
+    -- | @'ceiling' x@ returns the least integer not less than @x@
+    ceiling             :: (Integral b) => a -> b
+    -- | @'floor' x@ returns the greatest integer not greater than @x@
+    floor               :: (Integral b) => a -> b
+
+    {-# INLINE truncate #-}
+    truncate x          =  m  where (m,_) = properFraction x
+
+    round x             =  let (n,r) = properFraction x
+                               m     = if r < 0 then n - 1 else n + 1
+                           in case signum (abs r - 0.5) of
+                                -1 -> n
+                                0  -> if even n then n else m
+                                1  -> m
+                                _  -> error "round default defn: Bad value"
+
+    ceiling x           =  if r > 0 then n + 1 else n
+                           where (n,r) = properFraction x
+
+    floor x             =  if r < 0 then n - 1 else n
+                           where (n,r) = properFraction x
 \end{code}
 
 
 These 'numeric' enumerations come straight from the Report
 
 \begin{code}
-numericEnumFrom                :: (Fractional a) => a -> [a]
-numericEnumFrom                =  iterate (+1)
+numericEnumFrom         :: (Fractional a) => a -> [a]
+numericEnumFrom n      =  n `seq` (n : numericEnumFrom (n + 1))
 
-numericEnumFromThen    :: (Fractional a) => a -> a -> [a]
-numericEnumFromThen n m        =  iterate (+(m-n)) n
+numericEnumFromThen     :: (Fractional a) => a -> a -> [a]
+numericEnumFromThen n m        = n `seq` m `seq` (n : numericEnumFromThen m (m+m-n))
 
 numericEnumFromTo       :: (Ord a, Fractional a) => a -> a -> [a]
 numericEnumFromTo n m   = takeWhile (<= m + 1/2) (numericEnumFrom n)
 
 numericEnumFromThenTo   :: (Ord a, Fractional a) => a -> a -> a -> [a]
-numericEnumFromThenTo e1 e2 e3 = takeWhile pred (numericEnumFromThen e1 e2)
-                               where
-                                mid = (e2 - e1) / 2
-                                pred | e2 > e1   = (<= e3 + mid)
-                                     | otherwise = (>= e3 + mid)
+numericEnumFromThenTo e1 e2 e3
+    = takeWhile predicate (numericEnumFromThen e1 e2)
+                                where
+                                 mid = (e2 - e1) / 2
+                                 predicate | e2 >= e1  = (<= e3 + mid)
+                                           | otherwise = (>= e3 + mid)
 \end{code}
 
 
 %*********************************************************
-%*                                                     *
+%*                                                      *
 \subsection{Instances for @Int@}
-%*                                                     *
+%*                                                      *
 %*********************************************************
 
 \begin{code}
 instance  Real Int  where
-    toRational x       =  toInteger x % 1
-
-instance  Integral Int where
-    toInteger i = int2Integer i  -- give back a full-blown Integer
-
-    -- Following chks for zero divisor are non-standard (WDP)
-    a `quot` b =  if b /= 0
-                  then a `quotInt` b
-                  else error "Prelude.Integral.quot{Int}: divide by 0"
-    a `rem` b  =  if b /= 0
-                  then a `remInt` b
-                  else error "Prelude.Integral.rem{Int}: divide by 0"
-
-    x `div` y = x `divInt` y
-    x `mod` y = x `modInt` y
-
-    a `quotRem` b = a `quotRemInt` b
-    a `divMod`  b = a `divModInt`  b
+    toRational x        =  toInteger x % 1
+
+instance  Integral Int  where
+    toInteger (I# i) = smallInteger i
+
+    a `quot` b
+     | b == 0                     = divZeroError
+     | b == (-1) && a == minBound = overflowError -- Note [Order of tests]
+                                                  -- in GHC.Int
+     | otherwise                  =  a `quotInt` b
+
+    a `rem` b
+     | b == 0                     = divZeroError
+     | b == (-1) && a == minBound = overflowError -- Note [Order of tests]
+                                                  -- in GHC.Int
+     | otherwise                  =  a `remInt` b
+
+    a `div` b
+     | b == 0                     = divZeroError
+     | b == (-1) && a == minBound = overflowError -- Note [Order of tests]
+                                                  -- in GHC.Int
+     | otherwise                  =  a `divInt` b
+
+    a `mod` b
+     | b == 0                     = divZeroError
+     | b == (-1) && a == minBound = overflowError -- Note [Order of tests]
+                                                  -- in GHC.Int
+     | otherwise                  =  a `modInt` b
+
+    a `quotRem` b
+     | b == 0                     = divZeroError
+     | b == (-1) && a == minBound = overflowError -- Note [Order of tests]
+                                                  -- in GHC.Int
+     | otherwise                  =  a `quotRemInt` b
+
+    a `divMod` b
+     | b == 0                     = divZeroError
+     | b == (-1) && a == minBound = overflowError -- Note [Order of tests]
+                                                  -- in GHC.Int
+     | otherwise                  =  a `divModInt` b
 \end{code}
 
 
 %*********************************************************
-%*                                                     *
+%*                                                      *
 \subsection{Instances for @Integer@}
-%*                                                     *
+%*                                                      *
 %*********************************************************
 
 \begin{code}
 instance  Real Integer  where
-    toRational x       =  x % 1
+    toRational x        =  x % 1
 
 instance  Integral Integer where
-    toInteger n             = n
+    toInteger n      = n
 
+    _ `quot` 0 = divZeroError
     n `quot` d = n `quotInteger` d
+
+    _ `rem` 0 = divZeroError
     n `rem`  d = n `remInteger`  d
 
-    n `div` d  =  q  where (q,_) = divMod n d
-    n `mod` d  =  r  where (_,r) = divMod n d
+    _ `divMod` 0 = divZeroError
+    a `divMod` b = case a `divModInteger` b of
+                   (# x, y #) -> (x, y)
+
+    _ `quotRem` 0 = divZeroError
+    a `quotRem` b = case a `quotRemInteger` b of
+                    (# q, r #) -> (q, r)
 
-    a `divMod` b = a `divModInteger` b
-    a `quotRem` b = a `quotRemInteger` b
+    -- use the defaults for div & mod
 \end{code}
 
 
 %*********************************************************
-%*                                                     *
+%*                                                      *
 \subsection{Instances for @Ratio@}
-%*                                                     *
+%*                                                      *
 %*********************************************************
 
 \begin{code}
-instance  (Integral a) => Ord (Ratio a)  where
+instance  (Integral a)  => Ord (Ratio a)  where
     {-# SPECIALIZE instance Ord Rational #-}
-    (x:%y) <= (x':%y') =  x * y' <= x' * y
-    (x:%y) <  (x':%y') =  x * y' <  x' * y
+    (x:%y) <= (x':%y')  =  x * y' <= x' * y
+    (x:%y) <  (x':%y')  =  x * y' <  x' * y
 
-instance  (Integral a) => Num (Ratio a)  where
+instance  (Integral a)  => Num (Ratio a)  where
     {-# SPECIALIZE instance Num Rational #-}
-    (x:%y) + (x':%y')  =  reduce (x*y' + x'*y) (y*y')
-    (x:%y) - (x':%y')  =  reduce (x*y' - x'*y) (y*y')
-    (x:%y) * (x':%y')  =  reduce (x * x') (y * y')
-    negate (x:%y)      =  (-x) :% y
-    abs (x:%y)         =  abs x :% y
-    signum (x:%_)      =  signum x :% 1
-    fromInteger x      =  fromInteger x :% 1
-
-instance  (Integral a) => Fractional (Ratio a)  where
+    (x:%y) + (x':%y')   =  reduce (x*y' + x'*y) (y*y')
+    (x:%y) - (x':%y')   =  reduce (x*y' - x'*y) (y*y')
+    (x:%y) * (x':%y')   =  reduce (x * x') (y * y')
+    negate (x:%y)       =  (-x) :% y
+    abs (x:%y)          =  abs x :% y
+    signum (x:%_)       =  signum x :% 1
+    fromInteger x       =  fromInteger x :% 1
+
+{-# RULES "fromRational/id" fromRational = id :: Rational -> Rational #-}
+instance  (Integral a)  => Fractional (Ratio a)  where
     {-# SPECIALIZE instance Fractional Rational #-}
-    (x:%y) / (x':%y')  =  (x*y') % (y*x')
-    recip (x:%y)       =  y % x
-    fromRational (x:%y) =  fromInteger x :% fromInteger y
-
-instance  (Integral a) => Real (Ratio a)  where
+    (x:%y) / (x':%y')   =  (x*y') % (y*x')
+    recip (0:%_)        = error "Ratio.%: zero denominator"
+    recip (x:%y)
+        | x < 0         = negate y :% negate x
+        | otherwise     = y :% x
+    fromRational (x:%y) =  fromInteger x % fromInteger y
+
+instance  (Integral a)  => Real (Ratio a)  where
     {-# SPECIALIZE instance Real Rational #-}
-    toRational (x:%y)  =  toInteger x :% toInteger y
+    toRational (x:%y)   =  toInteger x :% toInteger y
 
-instance  (Integral a) => RealFrac (Ratio a)  where
+instance  (Integral a)  => RealFrac (Ratio a)  where
     {-# SPECIALIZE instance RealFrac Rational #-}
     properFraction (x:%y) = (fromInteger (toInteger q), r:%y)
-                         where (q,r) = quotRem x y
+                          where (q,r) = quotRem x y
 
 instance  (Integral a)  => Show (Ratio a)  where
     {-# SPECIALIZE instance Show Rational #-}
-    showsPrec p (x:%y) =  showParen (p > ratio_prec)
-                              (shows x . showString " % " . shows y)
-
-ratio_prec :: Int
-ratio_prec = 7
-
-instance  (Integral a) => Enum (Ratio a)  where
+    showsPrec p (x:%y)  =  showParen (p > ratioPrec) $
+                           showsPrec ratioPrec1 x .
+                           showString " % " .
+                           -- H98 report has spaces round the %
+                           -- but we removed them [May 04]
+                           -- and added them again for consistency with
+                           -- Haskell 98 [Sep 08, #1920]
+                           showsPrec ratioPrec1 y
+
+instance  (Integral a)  => Enum (Ratio a)  where
     {-# SPECIALIZE instance Enum Rational #-}
-    succ x             =  x + 1
-    pred x             =  x - 1
+    succ x              =  x + 1
+    pred x              =  x - 1
 
-    toEnum n            =  fromInteger (int2Integer n) :% 1
+    toEnum n            =  fromIntegral n :% 1
     fromEnum            =  fromInteger . truncate
 
-    enumFrom           =  numericEnumFrom
-    enumFromThen       =  numericEnumFromThen
-    enumFromTo         =  numericEnumFromTo
-    enumFromThenTo     =  numericEnumFromThenTo
+    enumFrom            =  numericEnumFrom
+    enumFromThen        =  numericEnumFromThen
+    enumFromTo          =  numericEnumFromTo
+    enumFromThenTo      =  numericEnumFromThenTo
 \end{code}
 
 
 %*********************************************************
-%*                                                     *
+%*                                                      *
 \subsection{Coercions}
-%*                                                     *
+%*                                                      *
 %*********************************************************
 
 \begin{code}
+-- | general coercion from integral types
 fromIntegral :: (Integral a, Num b) => a -> b
 fromIntegral = fromInteger . toInteger
 
@@ -270,6 +394,7 @@ fromIntegral = fromInteger . toInteger
 "fromIntegral/Int->Int" fromIntegral = id :: Int -> Int
     #-}
 
+-- | general coercion to fractional types
 realToFrac :: (Real a, Fractional b) => a -> b
 realToFrac = fromRational . toRational
 
@@ -279,61 +404,148 @@ realToFrac = fromRational . toRational
 \end{code}
 
 %*********************************************************
-%*                                                     *
+%*                                                      *
 \subsection{Overloaded numeric functions}
-%*                                                     *
+%*                                                      *
 %*********************************************************
 
 \begin{code}
-showSigned :: (Real a) => (a -> ShowS) -> Int -> a -> ShowS
-showSigned showPos p x 
+-- | Converts a possibly-negative 'Real' value to a string.
+showSigned :: (Real a)
+  => (a -> ShowS)       -- ^ a function that can show unsigned values
+  -> Int                -- ^ the precedence of the enclosing context
+  -> a                  -- ^ the value to show
+  -> ShowS
+showSigned showPos p x
    | x < 0     = showParen (p > 6) (showChar '-' . showPos (-x))
    | otherwise = showPos x
 
-even, odd      :: (Integral a) => a -> Bool
-even n         =  n `rem` 2 == 0
-odd            =  not . even
+even, odd       :: (Integral a) => a -> Bool
+even n          =  n `rem` 2 == 0
+odd             =  not . even
 
 -------------------------------------------------------
+-- | raise a number to a non-negative integral power
 {-# SPECIALISE (^) ::
-       Integer -> Integer -> Integer,
-       Integer -> Int -> Integer,
-       Int -> Int -> Int #-}
-(^)            :: (Num a, Integral b) => a -> b -> a
-_ ^ 0          =  1
-x ^ n | n > 0  =  f x (n-1) x
-                  where f _ 0 y = y
-                        f a d y = g a d  where
-                                  g b i | even i  = g (b*b) (i `quot` 2)
-                                        | otherwise = f b (i-1) (b*y)
-_ ^ _          = error "Prelude.^: negative exponent"
-
-{-# SPECIALISE (^^) ::
-       Rational -> Int -> Rational #-}
-(^^)           :: (Fractional a, Integral b) => a -> b -> a
-x ^^ n         =  if n >= 0 then x^n else recip (x^(negate n))
-
+        Integer -> Integer -> Integer,
+        Integer -> Int -> Integer,
+        Int -> Int -> Int #-}
+{-# INLINABLE (^) #-}    -- See Note [Inlining (^)]
+(^) :: (Num a, Integral b) => a -> b -> a
+x0 ^ y0 | y0 < 0    = error "Negative exponent"
+        | y0 == 0   = 1
+        | otherwise = f x0 y0
+    where -- f : x0 ^ y0 = x ^ y
+          f x y | even y    = f (x * x) (y `quot` 2)
+                | y == 1    = x
+                | otherwise = g (x * x) ((y - 1) `quot` 2) x
+          -- g : x0 ^ y0 = (x ^ y) * z
+          g x y z | even y = g (x * x) (y `quot` 2) z
+                  | y == 1 = x * z
+                  | otherwise = g (x * x) ((y - 1) `quot` 2) (x * z)
+
+-- | raise a number to an integral power
+(^^)            :: (Fractional a, Integral b) => a -> b -> a
+{-# INLINABLE (^^) #-}         -- See Note [Inlining (^)
+x ^^ n          =  if n >= 0 then x^n else recip (x^(negate n))
+
+{- Note [Inlining (^)
+   ~~~~~~~~~~~~~~~~~~~~~
+   The INLINABLE pragma allows (^) to be specialised at its call sites.
+   If it is called repeatedly at the same type, that can make a huge
+   difference, because of those constants which can be repeatedly
+   calculated.
+
+   Currently the fromInteger calls are not floated because we get
+             \d1 d2 x y -> blah
+   after the gentle round of simplification. -}
 
 -------------------------------------------------------
-gcd            :: (Integral a) => a -> a -> a
-gcd 0 0                =  error "Prelude.gcd: gcd 0 0 is undefined"
-gcd x y                =  gcd' (abs x) (abs y)
-                  where gcd' a 0  =  a
-                        gcd' a b  =  gcd' b (a `rem` b)
+-- Special power functions for Rational
+--
+-- see #4337
+--
+-- Rationale:
+-- For a legitimate Rational (n :% d), the numerator and denominator are
+-- coprime, i.e. they have no common prime factor.
+-- Therefore all powers (n ^ a) and (d ^ b) are also coprime, so it is
+-- not necessary to compute the greatest common divisor, which would be
+-- done in the default implementation at each multiplication step.
+-- Since exponentiation quickly leads to very large numbers and
+-- calculation of gcds is generally very slow for large numbers,
+-- avoiding the gcd leads to an order of magnitude speedup relatively
+-- soon (and an asymptotic improvement overall).
+--
+-- Note:
+-- We cannot use these functions for general Ratio a because that would
+-- change results in a multitude of cases.
+-- The cause is that if a and b are coprime, their remainders by any
+-- positive modulus generally aren't, so in the default implementation
+-- reduction occurs.
+--
+-- Example:
+-- (17 % 3) ^ 3 :: Ratio Word8
+-- Default:
+-- (17 % 3) ^ 3 = ((17 % 3) ^ 2) * (17 % 3)
+--              = ((289 `mod` 256) % 9) * (17 % 3)
+--              = (33 % 9) * (17 % 3)
+--              = (11 % 3) * (17 % 3)
+--              = (187 % 9)
+-- But:
+-- ((17^3) `mod` 256) % (3^3)   = (4913 `mod` 256) % 27
+--                              = 49 % 27
+--
+-- TODO:
+-- Find out whether special-casing for numerator, denominator or
+-- exponent = 1 (or -1, where that may apply) gains something.
+
+-- Special version of (^) for Rational base
+{-# RULES "(^)/Rational"    (^) = (^%^) #-}
+(^%^)           :: Integral a => Rational -> a -> Rational
+(n :% d) ^%^ e
+    | e < 0     = error "Negative exponent"
+    | e == 0    = 1 :% 1
+    | otherwise = (n ^ e) :% (d ^ e)
+
+-- Special version of (^^) for Rational base
+{-# RULES "(^^)/Rational"   (^^) = (^^%^^) #-}
+(^^%^^)         :: Integral a => Rational -> a -> Rational
+(n :% d) ^^%^^ e
+    | e > 0     = (n ^ e) :% (d ^ e)
+    | e == 0    = 1 :% 1
+    | n > 0     = (d ^ (negate e)) :% (n ^ (negate e))
+    | n == 0    = error "Ratio.%: zero denominator"
+    | otherwise = let nn = d ^ (negate e)
+                      dd = (negate n) ^ (negate e)
+                  in if even e then (nn :% dd) else (negate nn :% dd)
 
-lcm            :: (Integral a) => a -> a -> a
+-------------------------------------------------------
+-- | @'gcd' x y@ is the greatest (nonnegative) integer that divides both @x@
+-- and @y@; for example @'gcd' (-3) 6@ = @3@, @'gcd' (-3) (-6)@ = @3@,
+-- @'gcd' 0 4@ = @4@.  @'gcd' 0 0@ = @0@.
+gcd             :: (Integral a) => a -> a -> a
+gcd x y         =  gcd' (abs x) (abs y)
+                   where gcd' a 0  =  a
+                         gcd' a b  =  gcd' b (a `rem` b)
+
+-- | @'lcm' x y@ is the smallest positive integer that both @x@ and @y@ divide.
+lcm             :: (Integral a) => a -> a -> a
 {-# SPECIALISE lcm :: Int -> Int -> Int #-}
-lcm _ 0                =  0
-lcm 0 _                =  0
-lcm x y                =  abs ((x `quot` (gcd x y)) * y)
-
+lcm _ 0         =  0
+lcm 0 _         =  0
+lcm x y         =  abs ((x `quot` (gcd x y)) * y)
 
+#ifdef OPTIMISE_INTEGER_GCD_LCM
 {-# RULES
 "gcd/Int->Int->Int"             gcd = gcdInt
 "gcd/Integer->Integer->Integer" gcd = gcdInteger
 "lcm/Integer->Integer->Integer" lcm = lcmInteger
  #-}
 
+gcdInt :: Int -> Int -> Int
+gcdInt a b = fromIntegral (gcdInteger (fromIntegral a) (fromIntegral b))
+#endif
+
 integralEnumFrom :: (Integral a, Bounded a) => a -> [a]
 integralEnumFrom n = map fromInteger [toInteger n .. toInteger (maxBound `asTypeOf` n)]