```{-# LANGUAGE Trustworthy #-}
{-# LANGUAGE NoImplicitPrelude, MagicHash, UnboxedTuples #-}

-----------------------------------------------------------------------------
-- |
-- Module      :  GHC.Num
-- Copyright   :  (c) The University of Glasgow 1994-2002
--
-- Stability   :  internal
-- Portability :  non-portable (GHC Extensions)
--
-- The 'Num' class and the 'Integer' type.
--
-----------------------------------------------------------------------------

module GHC.Num (module GHC.Num, module GHC.Integer) where

import GHC.Base
import GHC.Integer

infixl 7  *
infixl 6  +, -

default ()              -- Double isn't available yet,
-- and we shouldn't be using defaults anyway

-- | Basic numeric class.
class  Num a  where
{-# MINIMAL (+), (*), abs, signum, fromInteger, (negate | (-)) #-}

(+), (-), (*)       :: a -> a -> a
-- | Unary negation.
negate              :: a -> a
-- | Absolute value.
abs                 :: a -> a
-- | Sign of a number.
-- The functions 'abs' and 'signum' should satisfy the law:
--
-- > abs x * signum x == x
--
-- For real numbers, the 'signum' is either @-1@ (negative), @0@ (zero)
-- or @1@ (positive).
signum              :: a -> a
-- | Conversion from an 'Integer'.
-- An integer literal represents the application of the function
-- 'fromInteger' to the appropriate value of type 'Integer',
-- so such literals have type @('Num' a) => a@.
fromInteger         :: Integer -> a

{-# INLINE (-) #-}
{-# INLINE negate #-}
x - y               = x + negate y
negate x            = 0 - x

-- | the same as @'flip' ('-')@.
--
-- Because @-@ is treated specially in the Haskell grammar,
-- @(-@ /e/@)@ is not a section, but an application of prefix negation.
-- However, @('subtract'@ /exp/@)@ is equivalent to the disallowed section.
{-# INLINE subtract #-}
subtract :: (Num a) => a -> a -> a
subtract x y = y - x

instance  Num Int  where
I# x + I# y = I# (x +# y)
I# x - I# y = I# (x -# y)
negate (I# x) = I# (negateInt# x)
I# x * I# y = I# (x *# y)
abs n  = if n `geInt` 0 then n else negate n

signum n | n `ltInt` 0 = negate 1
| n `eqInt` 0 = 0
| otherwise   = 1

{-# INLINE fromInteger #-}   -- Just to be sure!
fromInteger i = I# (integerToInt i)

instance Num Word where
(W# x#) + (W# y#)      = W# (x# `plusWord#` y#)
(W# x#) - (W# y#)      = W# (x# `minusWord#` y#)
(W# x#) * (W# y#)      = W# (x# `timesWord#` y#)
negate (W# x#)         = W# (int2Word# (negateInt# (word2Int# x#)))
abs x                  = x
signum 0               = 0
signum _               = 1
fromInteger i          = W# (integerToWord i)

instance  Num Integer  where
(+) = plusInteger
(-) = minusInteger
(*) = timesInteger
negate         = negateInteger
fromInteger x  =  x

abs = absInteger
signum = signumInteger
```