-<Sect2>
-<Title>Comparison operations</Title>
-
-<Para>
-<IndexTerm><Primary>comparisons, primitive</Primary></IndexTerm>
-<IndexTerm><Primary>operators, comparison</Primary></IndexTerm>
-</Para>
-
-<Para>
-
-<ProgramListing>
-{>,>=,==,/=,<,<=}# :: Int# -> Int# -> Bool
-
-{gt,ge,eq,ne,lt,le}Char# :: Char# -> Char# -> Bool
- -- ditto for Word# and Addr#
-</ProgramListing>
-
-<IndexTerm><Primary><literal>>#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>>=#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>==#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>/=#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal><#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal><=#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>gt{Char,Word,Addr}#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>ge{Char,Word,Addr}#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>eq{Char,Word,Addr}#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>ne{Char,Word,Addr}#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>lt{Char,Word,Addr}#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>le{Char,Word,Addr}#</literal></Primary></IndexTerm>
-</Para>
-
-</Sect2>
-
-<Sect2>
-<Title>Primitive-character operations</Title>
-
-<Para>
-<IndexTerm><Primary>characters, primitive operations</Primary></IndexTerm>
-<IndexTerm><Primary>operators, primitive character</Primary></IndexTerm>
-</Para>
-
-<Para>
-
-<ProgramListing>
-ord# :: Char# -> Int#
-chr# :: Int# -> Char#
-</ProgramListing>
-
-<IndexTerm><Primary><literal>ord#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>chr#</literal></Primary></IndexTerm>
-</Para>
-
-</Sect2>
-
-<Sect2>
-<Title>Primitive-<Literal>Int</Literal> operations</Title>
-
-<Para>
-<IndexTerm><Primary>integers, primitive operations</Primary></IndexTerm>
-<IndexTerm><Primary>operators, primitive integer</Primary></IndexTerm>
-</Para>
-
-<Para>
-
-<ProgramListing>
-{+,-,*,quotInt,remInt,gcdInt}# :: Int# -> Int# -> Int#
-negateInt# :: Int# -> Int#
-
-iShiftL#, iShiftRA#, iShiftRL# :: Int# -> Int# -> Int#
- -- shift left, right arithmetic, right logical
-
-addIntC#, subIntC#, mulIntC# :: Int# -> Int# -> (# Int#, Int# #)
- -- add, subtract, multiply with carry
-</ProgramListing>
-
-<IndexTerm><Primary><literal>+#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>-#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>*#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>quotInt#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>remInt#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>gcdInt#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>iShiftL#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>iShiftRA#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>iShiftRL#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>addIntC#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>subIntC#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>mulIntC#</literal></Primary></IndexTerm>
-<IndexTerm><Primary>shift operations, integer</Primary></IndexTerm>
-</Para>
-
-<Para>
-<Emphasis>Note:</Emphasis> No error/overflow checking!
-</Para>
-
-</Sect2>
-
-<Sect2>
-<Title>Primitive-<Literal>Double</Literal> and <Literal>Float</Literal> operations</Title>
-
-<Para>
-<IndexTerm><Primary>floating point numbers, primitive</Primary></IndexTerm>
-<IndexTerm><Primary>operators, primitive floating point</Primary></IndexTerm>
-</Para>
-
-<Para>
-
-<ProgramListing>
-{+,-,*,/}## :: Double# -> Double# -> Double#
-{<,<=,==,/=,>=,>}## :: Double# -> Double# -> Bool
-negateDouble# :: Double# -> Double#
-double2Int# :: Double# -> Int#
-int2Double# :: Int# -> Double#
-
-{plus,minux,times,divide}Float# :: Float# -> Float# -> Float#
-{gt,ge,eq,ne,lt,le}Float# :: Float# -> Float# -> Bool
-negateFloat# :: Float# -> Float#
-float2Int# :: Float# -> Int#
-int2Float# :: Int# -> Float#
-</ProgramListing>
-
-</Para>
-
-<Para>
-<IndexTerm><Primary><literal>+##</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>-##</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>*##</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>/##</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal><##</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal><=##</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>==##</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>=/##</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>>=##</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>>##</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>negateDouble#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>double2Int#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>int2Double#</literal></Primary></IndexTerm>
-</Para>
-
-<Para>
-<IndexTerm><Primary><literal>plusFloat#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>minusFloat#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>timesFloat#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>divideFloat#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>gtFloat#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>geFloat#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>eqFloat#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>neFloat#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>ltFloat#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>leFloat#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>negateFloat#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>float2Int#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>int2Float#</literal></Primary></IndexTerm>
-</Para>
-
-<Para>
-And a full complement of trigonometric functions:
-</Para>
-
-<Para>
-
-<ProgramListing>
-expDouble# :: Double# -> Double#
-logDouble# :: Double# -> Double#
-sqrtDouble# :: Double# -> Double#
-sinDouble# :: Double# -> Double#
-cosDouble# :: Double# -> Double#
-tanDouble# :: Double# -> Double#
-asinDouble# :: Double# -> Double#
-acosDouble# :: Double# -> Double#
-atanDouble# :: Double# -> Double#
-sinhDouble# :: Double# -> Double#
-coshDouble# :: Double# -> Double#
-tanhDouble# :: Double# -> Double#
-powerDouble# :: Double# -> Double# -> Double#
-</ProgramListing>
-
-<IndexTerm><Primary>trigonometric functions, primitive</Primary></IndexTerm>
-</Para>
-
-<Para>
-similarly for <Literal>Float#</Literal>.
-</Para>
-
-<Para>
-There are two coercion functions for <Literal>Float#</Literal>/<Literal>Double#</Literal>:
-</Para>
-
-<Para>
-
-<ProgramListing>
-float2Double# :: Float# -> Double#
-double2Float# :: Double# -> Float#
-</ProgramListing>
-
-<IndexTerm><Primary><literal>float2Double#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>double2Float#</literal></Primary></IndexTerm>
-</Para>
-
-<Para>
-The primitive version of <Function>decodeDouble</Function>
-(<Function>encodeDouble</Function> is implemented as an external C
-function):
-</Para>
-
-<Para>
-
-<ProgramListing>
-decodeDouble# :: Double# -> PrelNum.ReturnIntAndGMP
-</ProgramListing>
-
-<IndexTerm><Primary><literal>encodeDouble#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>decodeDouble#</literal></Primary></IndexTerm>
-</Para>
-
-<Para>
-(And the same for <Literal>Float#</Literal>s.)
-</Para>
-
-</Sect2>
-
-<Sect2 id="integer-operations">
-<Title>Operations on/for <Literal>Integers</Literal> (interface to GMP)
-</Title>
-
-<Para>
-<IndexTerm><Primary>arbitrary precision integers</Primary></IndexTerm>
-<IndexTerm><Primary>Integer, operations on</Primary></IndexTerm>
-</Para>
-
-<Para>
-We implement <Literal>Integers</Literal> (arbitrary-precision
-integers) using the GNU multiple-precision (GMP) package (version
-2.0.2).
-</Para>
-
-<Para>
-The data type for <Literal>Integer</Literal> is either a small
-integer, represented by an <Literal>Int</Literal>, or a large integer
-represented using the pieces required by GMP's
-<Literal>MP_INT</Literal> in <Filename>gmp.h</Filename> (see
-<Filename>gmp.info</Filename> in
-<Filename>ghc/includes/runtime/gmp</Filename>). It comes out as:
-</Para>
-
-<Para>
-
-<ProgramListing>
-data Integer = S# Int# -- small integers
- | J# Int# ByteArray# -- large integers
-</ProgramListing>
-
-<IndexTerm><Primary>Integer type</Primary></IndexTerm> The primitive
-ops to support large <Literal>Integers</Literal> use the
-“pieces” of the representation, and are as follows:
-</Para>
-
-<Para>
-
-<ProgramListing>
-negateInteger# :: Int# -> ByteArray# -> Integer
-
-{plus,minus,times}Integer#, gcdInteger#,
- quotInteger#, remInteger#, divExactInteger#
- :: Int# -> ByteArray#
- -> Int# -> ByteArray#
- -> (# Int#, ByteArray# #)
-
-cmpInteger#
- :: Int# -> ByteArray#
- -> Int# -> ByteArray#
- -> Int# -- -1 for <; 0 for ==; +1 for >
-
-cmpIntegerInt#
- :: Int# -> ByteArray#
- -> Int#
- -> Int# -- -1 for <; 0 for ==; +1 for >
-
-gcdIntegerInt# ::
- :: Int# -> ByteArray#
- -> Int#
- -> Int#
-
-divModInteger#, quotRemInteger#
- :: Int# -> ByteArray#
- -> Int# -> ByteArray#
- -> (# Int#, ByteArray#,
- Int#, ByteArray# #)
-
-integer2Int# :: Int# -> ByteArray# -> Int#
-
-int2Integer# :: Int# -> Integer -- NB: no error-checking on these two!
-word2Integer# :: Word# -> Integer
-
-addr2Integer# :: Addr# -> Integer
- -- the Addr# is taken to be a `char *' string
- -- to be converted into an Integer.
-</ProgramListing>
-
-<IndexTerm><Primary><literal>negateInteger#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>plusInteger#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>minusInteger#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>timesInteger#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>quotInteger#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>remInteger#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>gcdInteger#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>gcdIntegerInt#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>divExactInteger#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>cmpInteger#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>divModInteger#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>quotRemInteger#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>integer2Int#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>int2Integer#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>word2Integer#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>addr2Integer#</literal></Primary></IndexTerm>
-</Para>
-
-</Sect2>
-
-<Sect2>
-<Title>Words and addresses</Title>
-
-<Para>
-<IndexTerm><Primary>word, primitive type</Primary></IndexTerm>
-<IndexTerm><Primary>address, primitive type</Primary></IndexTerm>
-<IndexTerm><Primary>unsigned integer, primitive type</Primary></IndexTerm>
-<IndexTerm><Primary>pointer, primitive type</Primary></IndexTerm>
-</Para>
-
-<Para>
-A <Literal>Word#</Literal> is used for bit-twiddling operations.
-It is the same size as an <Literal>Int#</Literal>, but has no sign
-nor any arithmetic operations.
-
-<ProgramListing>
-type Word# -- Same size/etc as Int# but *unsigned*
-type Addr# -- A pointer from outside the "Haskell world" (from C, probably);
- -- described under "arrays"
-</ProgramListing>
-
-<IndexTerm><Primary><literal>Word#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>Addr#</literal></Primary></IndexTerm>
-</Para>
-
-<Para>
-<Literal>Word#</Literal>s and <Literal>Addr#</Literal>s have
-the usual comparison operations. Other
-unboxed-<Literal>Word</Literal> ops (bit-twiddling and coercions):
-</Para>
-
-<Para>
-
-<ProgramListing>
-{gt,ge,eq,ne,lt,le}Word# :: Word# -> Word# -> Bool
-
-and#, or#, xor# :: Word# -> Word# -> Word#
- -- standard bit ops.
-
-quotWord#, remWord# :: Word# -> Word# -> Word#
- -- word (i.e. unsigned) versions are different from int
- -- versions, so we have to provide these explicitly.
-
-not# :: Word# -> Word#
-
-shiftL#, shiftRL# :: Word# -> Int# -> Word#
- -- shift left, right logical
-
-int2Word# :: Int# -> Word# -- just a cast, really
-word2Int# :: Word# -> Int#
-</ProgramListing>
-
-<IndexTerm><Primary>bit operations, Word and Addr</Primary></IndexTerm>
-<IndexTerm><Primary><literal>gtWord#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>geWord#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>eqWord#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>neWord#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>ltWord#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>leWord#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>and#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>or#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>xor#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>not#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>quotWord#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>remWord#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>shiftL#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>shiftRA#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>shiftRL#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>int2Word#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>word2Int#</literal></Primary></IndexTerm>
-</Para>
-
-<Para>
-Unboxed-<Literal>Addr</Literal> ops (C casts, really):
-
-<ProgramListing>
-{gt,ge,eq,ne,lt,le}Addr# :: Addr# -> Addr# -> Bool
-
-int2Addr# :: Int# -> Addr#
-addr2Int# :: Addr# -> Int#
-addr2Integer# :: Addr# -> (# Int#, ByteArray# #)
-</ProgramListing>
-
-<IndexTerm><Primary><literal>gtAddr#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>geAddr#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>eqAddr#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>neAddr#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>ltAddr#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>leAddr#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>int2Addr#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>addr2Int#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>addr2Integer#</literal></Primary></IndexTerm>
-</Para>
-
-<Para>
-The casts between <Literal>Int#</Literal>,
-<Literal>Word#</Literal> and <Literal>Addr#</Literal>
-correspond to null operations at the machine level, but are required
-to keep the Haskell type checker happy.
-</Para>
-
-<Para>
-Operations for indexing off of C pointers
-(<Literal>Addr#</Literal>s) to snatch values are listed under
-“arrays”.
-</Para>
-
-</Sect2>
-
-<Sect2>
-<Title>Arrays</Title>
-
-<Para>
-<IndexTerm><Primary>arrays, primitive</Primary></IndexTerm>
-</Para>
-
-<Para>
-The type <Literal>Array# elt</Literal> is the type of primitive,
-unpointed arrays of values of type <Literal>elt</Literal>.
-</Para>
-
-<Para>
-
-<ProgramListing>
-type Array# elt
-</ProgramListing>
-
-<IndexTerm><Primary><literal>Array#</literal></Primary></IndexTerm>
-</Para>
-
-<Para>
-<Literal>Array#</Literal> is more primitive than a Haskell
-array—indeed, the Haskell <Literal>Array</Literal> interface is
-implemented using <Literal>Array#</Literal>—in that an
-<Literal>Array#</Literal> is indexed only by
-<Literal>Int#</Literal>s, starting at zero. It is also more
-primitive by virtue of being unboxed. That doesn't mean that it isn't
-a heap-allocated object—of course, it is. Rather, being unboxed
-means that it is represented by a pointer to the array itself, and not
-to a thunk which will evaluate to the array (or to bottom). The
-components of an <Literal>Array#</Literal> are themselves boxed.
-</Para>
-
-<Para>
-The type <Literal>ByteArray#</Literal> is similar to
-<Literal>Array#</Literal>, except that it contains just a string
-of (non-pointer) bytes.
-</Para>
-
-<Para>
-
-<ProgramListing>
-type ByteArray#
-</ProgramListing>
-
-<IndexTerm><Primary><literal>ByteArray#</literal></Primary></IndexTerm>
-</Para>
-
-<Para>
-Arrays of these types are useful when a Haskell program wishes to
-construct a value to pass to a C procedure. It is also possible to use
-them to build (say) arrays of unboxed characters for internal use in a
-Haskell program. Given these uses, <Literal>ByteArray#</Literal>
-is deliberately a bit vague about the type of its components.
-Operations are provided to extract values of type
-<Literal>Char#</Literal>, <Literal>Int#</Literal>,
-<Literal>Float#</Literal>, <Literal>Double#</Literal>, and
-<Literal>Addr#</Literal> from arbitrary offsets within a
-<Literal>ByteArray#</Literal>. (For type
-<Literal>Foo#</Literal>, the $i$th offset gets you the $i$th
-<Literal>Foo#</Literal>, not the <Literal>Foo#</Literal> at
-byte-position $i$. Mumble.) (If you want a
-<Literal>Word#</Literal>, grab an <Literal>Int#</Literal>,
-then coerce it.)
-</Para>
-
-<Para>
-Lastly, we have static byte-arrays, of type
-<Literal>Addr#</Literal> [mentioned previously]. (Remember
-the duality between arrays and pointers in C.) Arrays of this types
-are represented by a pointer to an array in the world outside Haskell,
-so this pointer is not followed by the garbage collector. In other
-respects they are just like <Literal>ByteArray#</Literal>. They
-are only needed in order to pass values from C to Haskell.
-</Para>
-
-</Sect2>
-
-<Sect2>
-<Title>Reading and writing</Title>
-
-<Para>
-Primitive arrays are linear, and indexed starting at zero.
-</Para>
-
-<Para>
-The size and indices of a <Literal>ByteArray#</Literal>, <Literal>Addr#</Literal>, and
-<Literal>MutableByteArray#</Literal> are all in bytes. It's up to the program to
-calculate the correct byte offset from the start of the array. This
-allows a <Literal>ByteArray#</Literal> to contain a mixture of values of different
-type, which is often needed when preparing data for and unpicking
-results from C. (Umm…not true of indices…WDP 95/09)
-</Para>
-
-<Para>
-<Emphasis>Should we provide some <Literal>sizeOfDouble#</Literal> constants?</Emphasis>
-</Para>
-
-<Para>
-Out-of-range errors on indexing should be caught by the code which
-uses the primitive operation; the primitive operations themselves do
-<Emphasis>not</Emphasis> check for out-of-range indexes. The intention is that the
-primitive ops compile to one machine instruction or thereabouts.
-</Para>
-
-<Para>
-We use the terms “reading” and “writing” to refer to accessing
-<Emphasis>mutable</Emphasis> arrays (see <XRef LinkEnd="sect-mutable">), and
-“indexing” to refer to reading a value from an <Emphasis>immutable</Emphasis>
-array.
-</Para>
-
-<Para>
-Immutable byte arrays are straightforward to index (all indices in bytes):
-
-<ProgramListing>
-indexCharArray# :: ByteArray# -> Int# -> Char#
-indexIntArray# :: ByteArray# -> Int# -> Int#
-indexAddrArray# :: ByteArray# -> Int# -> Addr#
-indexFloatArray# :: ByteArray# -> Int# -> Float#
-indexDoubleArray# :: ByteArray# -> Int# -> Double#
-
-indexCharOffAddr# :: Addr# -> Int# -> Char#
-indexIntOffAddr# :: Addr# -> Int# -> Int#
-indexFloatOffAddr# :: Addr# -> Int# -> Float#
-indexDoubleOffAddr# :: Addr# -> Int# -> Double#
-indexAddrOffAddr# :: Addr# -> Int# -> Addr#
- -- Get an Addr# from an Addr# offset
-</ProgramListing>
-
-<IndexTerm><Primary><literal>indexCharArray#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>indexIntArray#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>indexAddrArray#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>indexFloatArray#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>indexDoubleArray#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>indexCharOffAddr#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>indexIntOffAddr#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>indexFloatOffAddr#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>indexDoubleOffAddr#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>indexAddrOffAddr#</literal></Primary></IndexTerm>
-</Para>
-
-<Para>
-The last of these, <Function>indexAddrOffAddr#</Function>, extracts an <Literal>Addr#</Literal> using an offset
-from another <Literal>Addr#</Literal>, thereby providing the ability to follow a chain of
-C pointers.
-</Para>
-
-<Para>
-Something a bit more interesting goes on when indexing arrays of boxed
-objects, because the result is simply the boxed object. So presumably
-it should be entered—we never usually return an unevaluated
-object! This is a pain: primitive ops aren't supposed to do
-complicated things like enter objects. The current solution is to
-return a single element unboxed tuple (see <XRef LinkEnd="unboxed-tuples">).
-</Para>
-
-<Para>
-
-<ProgramListing>
-indexArray# :: Array# elt -> Int# -> (# elt #)
-</ProgramListing>
-
-<IndexTerm><Primary><literal>indexArray#</literal></Primary></IndexTerm>
-</Para>
-
-</Sect2>
-
-<Sect2>
-<Title>The state type</Title>
-
-<Para>
-<IndexTerm><Primary><literal>state, primitive type</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>State#</literal></Primary></IndexTerm>
-</Para>
-
-<Para>
-The primitive type <Literal>State#</Literal> represents the state of a state
-transformer. It is parameterised on the desired type of state, which
-serves to keep states from distinct threads distinct from one another.
-But the <Emphasis>only</Emphasis> effect of this parameterisation is in the type
-system: all values of type <Literal>State#</Literal> are represented in the same way.
-Indeed, they are all represented by nothing at all! The code
-generator “knows” to generate no code, and allocate no registers
-etc, for primitive states.
-</Para>
-
-<Para>
-
-<ProgramListing>
-type State# s
-</ProgramListing>
-
-</Para>
-
-<Para>
-The type <Literal>GHC.RealWorld</Literal> is truly opaque: there are no values defined
-of this type, and no operations over it. It is “primitive” in that
-sense - but it is <Emphasis>not unlifted!</Emphasis> Its only role in life is to be
-the type which distinguishes the <Literal>IO</Literal> state transformer.
-</Para>
-
-<Para>
-
-<ProgramListing>
-data RealWorld
-</ProgramListing>
-
-</Para>
-
-</Sect2>
-
-<Sect2>
-<Title>State of the world</Title>
-
-<Para>
-A single, primitive, value of type <Literal>State# RealWorld</Literal> is provided.
-</Para>
-
-<Para>
-
-<ProgramListing>
-realWorld# :: State# RealWorld
-</ProgramListing>
-
-<IndexTerm><Primary>realWorld# state object</Primary></IndexTerm>
-</Para>
-
-<Para>
-(Note: in the compiler, not a <Literal>PrimOp</Literal>; just a mucho magic
-<Literal>Id</Literal>. Exported from <Literal>GHC</Literal>, though).
-</Para>
-
-</Sect2>
-
-<Sect2 id="sect-mutable">
-<Title>Mutable arrays</Title>
-
-<Para>
-<IndexTerm><Primary>mutable arrays</Primary></IndexTerm>
-<IndexTerm><Primary>arrays, mutable</Primary></IndexTerm>
-Corresponding to <Literal>Array#</Literal> and <Literal>ByteArray#</Literal>, we have the types of
-mutable versions of each. In each case, the representation is a
-pointer to a suitable block of (mutable) heap-allocated storage.
-</Para>
-
-<Para>
-
-<ProgramListing>
-type MutableArray# s elt
-type MutableByteArray# s
-</ProgramListing>
-
-<IndexTerm><Primary><literal>MutableArray#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>MutableByteArray#</literal></Primary></IndexTerm>
-</Para>
-
-<Sect3>
-<Title>Allocation</Title>
-
-<Para>
-<IndexTerm><Primary>mutable arrays, allocation</Primary></IndexTerm>
-<IndexTerm><Primary>arrays, allocation</Primary></IndexTerm>
-<IndexTerm><Primary>allocation, of mutable arrays</Primary></IndexTerm>
-</Para>
-
-<Para>
-Mutable arrays can be allocated. Only pointer-arrays are initialised;
-arrays of non-pointers are filled in by “user code” rather than by
-the array-allocation primitive. Reason: only the pointer case has to
-worry about GC striking with a partly-initialised array.
-</Para>
-
-<Para>
-
-<ProgramListing>
-newArray# :: Int# -> elt -> State# s -> (# State# s, MutableArray# s elt #)
-
-newCharArray# :: Int# -> State# s -> (# State# s, MutableByteArray# s elt #)
-newIntArray# :: Int# -> State# s -> (# State# s, MutableByteArray# s elt #)
-newAddrArray# :: Int# -> State# s -> (# State# s, MutableByteArray# s elt #)
-newFloatArray# :: Int# -> State# s -> (# State# s, MutableByteArray# s elt #)
-newDoubleArray# :: Int# -> State# s -> (# State# s, MutableByteArray# s elt #)
-</ProgramListing>
-
-<IndexTerm><Primary><literal>newArray#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>newCharArray#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>newIntArray#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>newAddrArray#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>newFloatArray#</literal></Primary></IndexTerm>
-<IndexTerm><Primary><literal>newDoubleArray#</literal></Primary></IndexTerm>
-</Para>
-
-<Para>
-The size of a <Literal>ByteArray#</Literal> is given in bytes.
-</Para>
-
-</Sect3>
-
-<Sect3>
-<Title>Reading and writing</Title>