-% ------------------------------------------------------------------------------
-% $Id: Num.lhs,v 1.2 2001/07/31 13:09:11 simonmar Exp $
-%
-% (c) The University of Glasgow, 1994-2000
-%
-
-\section[GHC.Num]{Module @GHC.Num@}
-
-The class
-
- Num
-
-and the type
-
- Integer
-
-
\begin{code}
-{-# OPTIONS -fno-implicit-prelude #-}
+{-# OPTIONS_GHC -fno-implicit-prelude #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module : GHC.Num
+-- 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)
+--
+-- The 'Num' class and the 'Integer' type.
+--
+-----------------------------------------------------------------------------
#include "MachDeps.h"
-#if WORD_SIZE_IN_BYTES == 4
+#if SIZEOF_HSWORD == 4
#define LEFTMOST_BIT 2147483648
-#elif WORD_SIZE_IN_BYTES == 8
+#elif SIZEOF_HSWORD == 8
#define LEFTMOST_BIT 9223372036854775808
#else
-#error Please define LEFTMOST_BIT to be 2^(WORD_SIZE_IN_BYTES*8-1)
+#error Please define LEFTMOST_BIT to be 2^(SIZEOF_HSWORD*8-1)
#endif
module GHC.Num where
import {-# SOURCE #-} GHC.Err
import GHC.Base
-import GHC.List
import GHC.Enum
import GHC.Show
%*********************************************************
\begin{code}
+-- | Basic numeric class.
+--
+-- Minimal complete definition: all except 'negate' or @(-)@
class (Eq a, Show a) => Num a where
(+), (-), (*) :: a -> a -> a
+ -- | Unary negation.
negate :: a -> a
- abs, signum :: 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
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
| otherwise = 1
fromInteger = integer2Int
-\end{code}
-
-
-\begin{code}
--- These can't go in GHC.Base with the defn of Int, because
--- we don't have pairs defined at that time!
quotRemInt :: Int -> Int -> (Int, Int)
-a@(I# _) `quotRemInt` b@(I# _) = (a `quotInt` b, a `remInt` b)
+quotRemInt a@(I# _) b@(I# _) = (a `quotInt` b, a `remInt` b)
-- OK, so I made it a little stricter. Shoot me. (WDP 94/10)
divModInt :: Int -> Int -> (Int, Int)
-- Stricter. Sorry if you don't like it. (WDP 94/10)
\end{code}
-
%*********************************************************
%* *
\subsection{The @Integer@ type}
%*********************************************************
\begin{code}
+-- | Arbitrary-precision integers.
data Integer
= S# Int# -- small integers
+#ifndef ILX
| J# Int# ByteArray# -- large integers
+#else
+ | J# Void BigInteger -- .NET big ints
+
+foreign type dotnet "BigInteger" BigInteger
+#endif
\end{code}
Convenient boxed Integer PrimOps.
minusInteger i1@(S# _) i2@(J# _ _) = toBig i1 - i2
minusInteger (J# s1 d1) (J# s2 d2) = case minusInteger# s1 d1 s2 d2 of (# s, d #) -> J# s d
-timesInteger i1@(S# i) i2@(S# j) = case mulIntC# i j of { (# r, c #) ->
- if c ==# 0# then S# r
- else toBig i1 * toBig i2 }
+timesInteger i1@(S# i) i2@(S# j) = if mulIntMayOflo# i j ==# 0#
+ then S# (i *# j)
+ else toBig i1 * toBig i2
timesInteger i1@(J# _ _) i2@(S# _) = i1 * toBig i2
timesInteger i1@(S# _) i2@(J# _ _) = toBig i1 * i2
timesInteger (J# s1 d1) (J# s2 d2) = case timesInteger# s1 d1 s2 d2 of (# s, d #) -> J# s d
{-# INLINE enumFromThen #-}
{-# INLINE enumFromTo #-}
{-# INLINE enumFromThenTo #-}
- enumFrom x = efdInteger x 1
- enumFromThen x y = efdInteger x (y-x)
- enumFromTo x lim = efdtInteger x 1 lim
- enumFromThenTo x y lim = efdtInteger x (y-x) lim
-
-
-efdInteger = enumDeltaIntegerList
-efdtInteger = enumDeltaToIntegerList
+ enumFrom x = enumDeltaInteger x 1
+ enumFromThen x y = enumDeltaInteger x (y-x)
+ enumFromTo x lim = enumDeltaToInteger x 1 lim
+ enumFromThenTo x y lim = enumDeltaToInteger x (y-x) lim
{-# RULES
-"efdInteger" forall x y. efdInteger x y = build (\c _ -> enumDeltaIntegerFB c x y)
-"efdtInteger" forall x y l.efdtInteger x y l = build (\c n -> enumDeltaToIntegerFB c n x y l)
-"enumDeltaInteger" enumDeltaIntegerFB (:) = enumDeltaIntegerList
-"enumDeltaToInteger" enumDeltaToIntegerFB (:) [] = enumDeltaToIntegerList
+"enumDeltaInteger" [~1] forall x y. enumDeltaInteger x y = build (\c _ -> enumDeltaIntegerFB c x y)
+"efdtInteger" [~1] forall x y l.enumDeltaToInteger x y l = build (\c n -> enumDeltaToIntegerFB c n x y l)
+"enumDeltaInteger" [1] enumDeltaIntegerFB (:) = enumDeltaInteger
+"enumDeltaToInteger" [1] enumDeltaToIntegerFB (:) [] = enumDeltaToInteger
#-}
enumDeltaIntegerFB :: (Integer -> b -> b) -> Integer -> Integer -> b
enumDeltaIntegerFB c x d = x `c` enumDeltaIntegerFB c (x+d) d
-enumDeltaIntegerList :: Integer -> Integer -> [Integer]
-enumDeltaIntegerList x d = x : enumDeltaIntegerList (x+d) d
+enumDeltaInteger :: Integer -> Integer -> [Integer]
+enumDeltaInteger x d = x : enumDeltaInteger (x+d) d
enumDeltaToIntegerFB c n x delta lim
| delta >= 0 = up_fb c n x delta lim
| otherwise = dn_fb c n x delta lim
-enumDeltaToIntegerList x delta lim
+enumDeltaToInteger x delta lim
| delta >= 0 = up_list x delta lim
| otherwise = dn_list x delta lim
\begin{code}
instance Show Integer where
showsPrec p n r
- | n < 0 && p > 6 = '(' : jtos n (')' : r)
+ | p > 6 && n < 0 = '(' : jtos n (')' : r)
+ -- Minor point: testing p first gives better code
+ -- in the not-uncommon case where the p argument
+ -- is a constant
| otherwise = jtos n r
showList = showList__ (showsPrec 0)