Improve documentation of `integer-gmp`
authorHerbert Valerio Riedel <hvr@gnu.org>
Fri, 31 Jan 2014 17:37:28 +0000 (18:37 +0100)
committerHerbert Valerio Riedel <hvr@gnu.org>
Fri, 31 Jan 2014 18:31:28 +0000 (19:31 +0100)
Among other things, this unhides `GHC.Integer` and re-groups the export list.
Moreover, the internal representation of `Integer` is explained a bit more,
and `/Since: 0.5.1.0/` annotations have been added.

Signed-off-by: Herbert Valerio Riedel <hvr@gnu.org>
GHC/Integer.lhs
GHC/Integer/GMP/Internals.hs
GHC/Integer/Type.lhs
integer-gmp.cabal

index fe3f89f..392a94a 100644 (file)
@@ -1,6 +1,6 @@
 \begin{code}
 {-# LANGUAGE CPP, MagicHash, NoImplicitPrelude #-}
-{-# OPTIONS_HADDOCK hide #-}
+
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  GHC.Integer
 --
 -- The 'Integer' type.
 --
+-- This module exposes the /portable/ 'Integer' API.  See
+-- "GHC.Integer.GMP.Internals" for the GMP-specific internal
+-- representation of 'Integer' as well as optimized GMP-specific
+-- operations.
 -----------------------------------------------------------------------------
 
 #include "MachDeps.h"
 
 module GHC.Integer (
-    Integer, mkInteger,
-    smallInteger, wordToInteger, integerToWord, integerToInt,
+    Integer,
+
+    -- * Construct 'Integer's
+    mkInteger, smallInteger, wordToInteger,
 #if WORD_SIZE_IN_BITS < 64
-    integerToWord64, word64ToInteger,
-    integerToInt64, int64ToInteger,
+    word64ToInteger, int64ToInteger,
 #endif
+    -- * Conversion to other integral types
+    integerToWord, integerToInt,
+#if WORD_SIZE_IN_BITS < 64
+    integerToWord64, integerToInt64,
+#endif
+
+    -- * Helpers for 'RealFloat' type-class operations
+    encodeFloatInteger, floatFromInteger,
+    encodeDoubleInteger, decodeDoubleInteger, doubleFromInteger,
+
+    -- * Arithmetic operations
     plusInteger, minusInteger, timesInteger, negateInteger,
-    eqInteger, neqInteger, absInteger, signumInteger,
+ absInteger, signumInteger,
+    divModInteger, divInteger, modInteger,
+    quotRemInteger, quotInteger, remInteger,
+
+    -- * Comparison predicates
+    eqInteger, neqInteger,
     leInteger, gtInteger, ltInteger, geInteger, compareInteger,
     eqInteger#, neqInteger#,
     leInteger#, gtInteger#, ltInteger#, geInteger#,
-    divModInteger, divInteger, modInteger,
-    quotRemInteger, quotInteger, remInteger,
-    encodeFloatInteger, floatFromInteger,
-    encodeDoubleInteger, decodeDoubleInteger, doubleFromInteger,
-    -- gcdInteger, lcmInteger,
+
+    -- * Bit-operations
     andInteger, orInteger, xorInteger, complementInteger,
     shiftLInteger, shiftRInteger, testBitInteger,
+
+    -- * Hashing
     hashInteger,
  ) where
 
index 7667a39..0a212f7 100644 (file)
@@ -2,6 +2,15 @@
 
 -- | This modules provides access to the 'Integer' constructors and
 -- exposes some highly optimized GMP-operations.
+--
+-- Note that since @integer-gmp@ does not depend on `base`, error
+-- reporting via exceptions, 'error', or 'undefined' is not
+-- available. Instead, the low-level functions will crash the runtime
+-- if called with invalid arguments.
+--
+-- See also
+-- <https://ghc.haskell.org/trac/ghc/wiki/Commentary/Libraries/Integer GHC Commentary: Libraries/Integer>.
+
 module GHC.Integer.GMP.Internals
     ( -- * The 'Integer' type
       Integer(..)
index a4f919f..8596562 100644 (file)
@@ -104,13 +104,32 @@ Convenient boxed Integer PrimOps.
 \begin{code}
 -- | Arbitrary-precision integers.
 data Integer
-   = S# Int#                            -- small integers
-   | J# Int# ByteArray#                 -- large integers
-
-mkInteger :: Bool   -- non-negative?
-          -> [Int]  -- absolute value in 31 bit chunks, least significant first
-                    -- ideally these would be Words rather than Ints, but
-                    -- we don't have Word available at the moment.
+   = S# Int#            -- ^ \"small\" integers fitting into an 'Int#'
+   | J# Int# ByteArray# -- ^ \"big\" integers represented as GMP's @mpz_t@ structure.
+     --
+     -- The 'Int#' field corresponds to @mpz_t@'s @_mp_size@ field,
+     -- which encodes the sign and the number of /limbs/ stored in the
+     -- 'ByteArray#' field (i.e. @mpz_t@'s @_mp_d@ field). Note: The
+     -- 'ByteArray#' may have been over-allocated, and thus larger
+     -- than the size denoted by the 'Int#' field.
+     --
+     -- This representation tries to avoid using the GMP number
+     -- representation for small integers that fit into a native
+     -- 'Int#'. This allows to reduce (or at least defer) calling into GMP
+     -- for operations whose results remain in the 'Int#'-domain.
+     --
+     -- Note: It does __not__ constitute a violation of invariants to
+     -- represent an integer which would fit into an 'Int#' with the
+     -- 'J#'-constructor. For instance, the value @0@ has (only) two valid
+     -- representations, either @'S#' 0#@ or @'J#' 0 _@.
+
+-- | Construct 'Integer' value from list of 'Int's.
+--
+-- This function is used by GHC for constructing 'Integer' literals.
+mkInteger :: Bool   -- ^ sign of integer ('True' if non-negative)
+          -> [Int]  -- ^ absolute value expressed in 31 bit chunks, least significant first
+
+                    -- (ideally these would be machine-word 'Word's rather than 31-bit truncated 'Int's)
           -> Integer
 mkInteger nonNegative is = let abs = f is
                            in if nonNegative then abs else negateInteger abs
@@ -416,6 +435,8 @@ gcdInteger (J# sa a) (J# sb b)   = mpzToInteger (gcdInteger# sa a sb b)
 --
 -- For @/a/@ and @/b/@, compute their greatest common divisor @/g/@
 -- and the coefficient @/s/@ satisfying @/a//s/ + /b//t/ = /g/@.
+--
+-- /Since: 0.5.1.0/
 {-# NOINLINE gcdExtInteger #-}
 gcdExtInteger :: Integer -> Integer -> (# Integer, Integer #)
 gcdExtInteger a@(S# _)   b@(S# _) = gcdExtInteger (toBig a) (toBig b)
@@ -464,6 +485,8 @@ divExact (J# sa a) (J# sb b) = mpzToInteger (divExactInteger# sa a sb b)
 %*********************************************************
 
 \begin{code}
+
+-- | /Since: 0.5.1.0/
 {-# NOINLINE eqInteger# #-}
 eqInteger# :: Integer -> Integer -> Int#
 eqInteger# (S# i)     (S# j)     = i ==# j
@@ -471,6 +494,7 @@ eqInteger# (S# i)     (J# s d)   = cmpIntegerInt# s d i ==# 0#
 eqInteger# (J# s d)   (S# i)     = cmpIntegerInt# s d i ==# 0#
 eqInteger# (J# s1 d1) (J# s2 d2) = (cmpInteger# s1 d1 s2 d2) ==# 0#
 
+-- | /Since: 0.5.1.0/
 {-# NOINLINE neqInteger# #-}
 neqInteger# :: Integer -> Integer -> Int#
 neqInteger# (S# i)     (S# j)     = i /=# j
@@ -490,6 +514,7 @@ instance  Eq Integer  where
 
 ------------------------------------------------------------------------
 
+-- | /Since: 0.5.1.0/
 {-# NOINLINE leInteger# #-}
 leInteger# :: Integer -> Integer -> Int#
 leInteger# (S# i)     (S# j)     = i <=# j
@@ -497,6 +522,7 @@ leInteger# (J# s d)   (S# i)     = cmpIntegerInt# s d i <=# 0#
 leInteger# (S# i)     (J# s d)   = cmpIntegerInt# s d i >=# 0#
 leInteger# (J# s1 d1) (J# s2 d2) = (cmpInteger# s1 d1 s2 d2) <=# 0#
 
+-- | /Since: 0.5.1.0/
 {-# NOINLINE gtInteger# #-}
 gtInteger# :: Integer -> Integer -> Int#
 gtInteger# (S# i)     (S# j)     = i ># j
@@ -504,6 +530,7 @@ gtInteger# (J# s d)   (S# i)     = cmpIntegerInt# s d i ># 0#
 gtInteger# (S# i)     (J# s d)   = cmpIntegerInt# s d i <# 0#
 gtInteger# (J# s1 d1) (J# s2 d2) = (cmpInteger# s1 d1 s2 d2) ># 0#
 
+-- | /Since: 0.5.1.0/
 {-# NOINLINE ltInteger# #-}
 ltInteger# :: Integer -> Integer -> Int#
 ltInteger# (S# i)     (S# j)     = i <# j
@@ -511,6 +538,7 @@ ltInteger# (J# s d)   (S# i)     = cmpIntegerInt# s d i <# 0#
 ltInteger# (S# i)     (J# s d)   = cmpIntegerInt# s d i ># 0#
 ltInteger# (J# s1 d1) (J# s2 d2) = (cmpInteger# s1 d1 s2 d2) <# 0#
 
+-- | /Since: 0.5.1.0/
 {-# NOINLINE geInteger# #-}
 geInteger# :: Integer -> Integer -> Int#
 geInteger# (S# i)     (S# j)     = i >=# j
@@ -759,12 +787,15 @@ shiftRInteger :: Integer -> Int# -> Integer
 shiftRInteger j@(S# _) i = shiftRInteger (toBig j) i
 shiftRInteger (J# s d) i = mpzToInteger (fdivQ2ExpInteger# s d i)
 
+-- | /Since: 0.5.1.0/
 {-# NOINLINE testBitInteger #-}
 testBitInteger :: Integer -> Int# -> Bool
 testBitInteger j@(S# _) i = testBitInteger (toBig j) i
 testBitInteger (J# s d) i = isTrue# (testBitInteger# s d i /=# 0#)
 
 -- | \"@'powInteger' /b/ /e/@\" computes base @/b/@ raised to exponent @/e/@.
+--
+-- /Since: 0.5.1.0/
 {-# NOINLINE powInteger #-}
 powInteger :: Integer -> Word# -> Integer
 powInteger j@(S# _) e = powInteger (toBig j) e
@@ -778,6 +809,8 @@ powInteger (J# s d) e = mpzToInteger (powInteger# s d e)
 -- exponents unless it is guaranteed the inverse exists, as failure to
 -- do so will likely cause program abortion due to a divide-by-zero
 -- fault. See also 'recipModInteger'.
+--
+-- /Since: 0.5.1.0/
 {-# NOINLINE powModInteger #-}
 powModInteger :: Integer -> Integer -> Integer -> Integer
 powModInteger (J# s1 d1) (J# s2 d2) (J# s3 d3) =
@@ -792,6 +825,8 @@ powModInteger b e m = powModInteger (toBig b) (toBig e) (toBig m)
 -- @mpz_powm_sec()@ function which is designed to be resilient to side
 -- channel attacks and is therefore intended for cryptographic
 -- applications.
+--
+-- /Since: 0.5.1.0/
 {-# NOINLINE powModSecInteger #-}
 powModSecInteger :: Integer -> Integer -> Integer -> Integer
 powModSecInteger (J# s1 d1) (J# s2 d2) (J# s3 d3) =
@@ -805,6 +840,8 @@ powModSecInteger b e m = powModSecInteger (toBig b) (toBig e) (toBig m)
 -- Note: The implementation exploits the undocumented property of
 -- @mpz_invert()@ to not mangle the result operand (which is initialized
 -- to 0) in case of non-existence of the inverse.
+--
+-- /Since: 0.5.1.0/
 {-# NOINLINE recipModInteger #-}
 recipModInteger :: Integer -> Integer -> Integer
 recipModInteger j@(S# _) m@(S# _)   = recipModInteger (toBig j) (toBig m)
@@ -826,6 +863,8 @@ recipModInteger (J# s d) (J# ms md) = mpzToInteger (recipModInteger# s d ms md)
 -- The @/k/@ argument controls how many test rounds are performed for
 -- determining a /probable prime/. For more details, see
 -- <http://gmplib.org/manual/Number-Theoretic-Functions.html#index-mpz_005fprobab_005fprime_005fp-360 GMP documentation for `mpz_probab_prime_p()`>.
+--
+-- /Since: 0.5.1.0/
 {-# NOINLINE testPrimeInteger #-}
 testPrimeInteger :: Integer -> Int# -> Int#
 testPrimeInteger j@(S# _) reps = testPrimeInteger (toBig j) reps
@@ -837,6 +876,8 @@ testPrimeInteger (J# s d) reps = testPrimeInteger# s d reps
 -- @mpz_nextprime()@ \"uses a probabilistic algorithm to identify
 -- primes. For practical purposes it's adequate, the chance of a
 -- composite passing will be extremely small.\"
+--
+-- /Since: 0.5.1.0/
 {-# NOINLINE nextPrimeInteger #-}
 nextPrimeInteger :: Integer -> Integer
 nextPrimeInteger j@(S# _) = nextPrimeInteger (toBig j)
@@ -863,6 +904,8 @@ nextPrimeInteger (J# s d) = mpzToInteger (nextPrimeInteger# s d)
 --
 -- * \"@'sizeInBaseInteger' /i/ 2#@\" can be used to determine the most
 --   significant bit of @/i/@.
+--
+-- /Since: 0.5.1.0/
 {-# NOINLINE sizeInBaseInteger #-}
 sizeInBaseInteger :: Integer -> Int# -> Word#
 sizeInBaseInteger (J# s d) b = sizeInBaseInteger# s d b
@@ -872,9 +915,7 @@ sizeInBaseInteger j@(S# _) b = sizeInBaseInteger (toBig j) b -- TODO
 --
 -- The call
 --
--- @
--- 'exportIntegerToMutableByteArray' /i/ /mba/ /offset/ /order/
--- @
+-- @'exportIntegerToMutableByteArray' /i/ /mba/ /offset/ /order/@
 --
 -- writes
 --
@@ -895,6 +936,8 @@ sizeInBaseInteger j@(S# _) b = sizeInBaseInteger (toBig j) b -- TODO
 -- It's recommended to avoid calling 'exportIntegerToMutableByteArray' for small
 -- integers as this function would currently convert those to big
 -- integers in order to call @mpz_export()@.
+--
+-- /Since: 0.5.1.0/
 {-# NOINLINE exportIntegerToMutableByteArray #-}
 exportIntegerToMutableByteArray :: Integer -> MutableByteArray# s -> Word# -> Int# -> State# s -> (# State# s, Word# #)
 exportIntegerToMutableByteArray (J# s d) mba o e = exportIntegerToMutableByteArray# s d mba o e
@@ -902,11 +945,11 @@ exportIntegerToMutableByteArray j@(S# _) mba o e = exportIntegerToMutableByteArr
 
 -- | Dump 'Integer' (without sign) to @/addr/@ in base-256 representation.
 --
--- @
--- 'exportIntegerToAddr' /addr/ /o/ /e/
--- @
+-- @'exportIntegerToAddr' /addr/ /o/ /e/@
 --
 -- See description of 'exportIntegerToMutableByteArray' for more details.
+--
+-- /Since: 0.5.1.0/
 {-# NOINLINE exportIntegerToAddr #-}
 exportIntegerToAddr :: Integer -> Addr# -> Int# -> State# s -> (# State# s, Word# #)
 exportIntegerToAddr (J# s d) addr o e = exportIntegerToAddr# s d addr o e
@@ -916,9 +959,7 @@ exportIntegerToAddr j@(S# _) addr o e = exportIntegerToAddr (toBig j) addr o e -
 --
 -- The call
 --
--- @
--- 'importIntegerFromByteArray' /ba/ /offset/ /size/ /order/
--- @
+-- @'importIntegerFromByteArray' /ba/ /offset/ /size/ /order/@
 --
 -- reads
 --
@@ -928,6 +969,8 @@ exportIntegerToAddr j@(S# _) addr o e = exportIntegerToAddr (toBig j) addr o e -
 --   significant byte first if @/order/@ is @-1#@, and
 --
 -- * returns a new 'Integer'
+--
+-- /Since: 0.5.1.0/
 {-# NOINLINE importIntegerFromByteArray #-}
 importIntegerFromByteArray :: ByteArray# -> Word# -> Word# -> Int# -> Integer
 importIntegerFromByteArray ba o l e = mpzToInteger (importIntegerFromByteArray# ba o l e)
@@ -935,11 +978,11 @@ importIntegerFromByteArray ba o l e = mpzToInteger (importIntegerFromByteArray#
 -- | Read 'Integer' (without sign) from memory location at @/addr/@ in
 -- base-256 representation.
 --
--- @
--- 'importIntegerFromAddr' /addr/ /size/ /order/
--- @
+-- @'importIntegerFromAddr' /addr/ /size/ /order/@
 --
 -- See description of 'importIntegerFromByteArray' for more details.
+--
+-- /Since: 0.5.1.0/
 {-# NOINLINE importIntegerFromAddr #-}
 importIntegerFromAddr :: Addr# -> Word# -> Int# -> State# s -> (# State# s, Integer #)
 importIntegerFromAddr addr l e st = case importIntegerFromAddr# addr l e st of
@@ -956,9 +999,11 @@ importIntegerFromAddr addr l e st = case importIntegerFromAddr# addr l e st of
 \begin{code}
 -- This is used by hashUnique
 
--- | hashInteger returns the same value as 'fromIntegral', although in
+-- | 'hashInteger' returns the same value as 'fromIntegral', although in
 -- unboxed form.  It might be a reasonable hash function for 'Integer',
 -- given a suitable distribution of 'Integer' values.
+--
+-- Note: 'hashInteger' is currently just an alias for 'integerToInt'.
 
 hashInteger :: Integer -> Int#
 hashInteger = integerToInt
index 9de49ab..ed1242f 100644 (file)
@@ -8,7 +8,16 @@ maintainer:     libraries@haskell.org
 bug-reports:    http://ghc.haskell.org/trac/ghc/newticket?component=libraries%20%28other%29&keywords=integer-gmp
 synopsis:       Integer library based on GMP
 description:
-    This package contains an Integer library based on GMP.
+    This package provides the low-level implementation of the standard
+    'Integer' type based on the
+    <http://gmplib.org/ GNU Multiple Precision Arithmetic Library (GMP)>.
+    .
+    This package provides access to the internal representation of
+    'Integer' as well as primitive operations with no proper error
+    handling, and should only be used directly with the utmost care.
+    .
+    For more details about the design of @integer-gmp@, see
+    <https://ghc.haskell.org/trac/ghc/wiki/Commentary/Libraries/Integer GHC Commentary: Libraries/Integer>.
 build-type:     Configure
 cabal-version:  >=1.10