[project @ 1999-02-02 13:26:31 by sof]
[ghc-hetmet.git] / ghc / lib / exts / Word.lhs
index d98d89a..6958a32 100644 (file)
@@ -17,34 +17,53 @@ module Word
        , Word64         --  Integral, Ix, Enum,
                         --  Read, Show, Bits,
                         --  CCallable, CReturnable
-                        --  (last two 
+                        --  (last two are GHC specific.)
 
+       , word8ToWord16   -- :: Word8  -> Word16
        , word8ToWord32   -- :: Word8  -> Word32
-       , word32ToWord8   -- :: Word32 -> Word8
+       , word8ToWord64   -- :: Word8  -> Word64
+
+       , word16ToWord8   -- :: Word16 -> Word32
        , word16ToWord32  -- :: Word16 -> Word32
+       , word16ToWord64  -- :: Word8  -> Word64
+
+       , word32ToWord8   -- :: Word32 -> Word8
        , word32ToWord16  -- :: Word32 -> Word16
+       , word32ToWord64  -- :: Word32 -> Word64
 
+       , word64ToWord8   -- :: Word64 -> Word8
+       , word64ToWord16  -- :: Word64 -> Word16
+       , word64ToWord32  -- :: Word64 -> Word32
+        
        , word8ToInt      -- :: Word8  -> Int
-       , intToWord8      -- :: Int    -> Word8
        , word16ToInt     -- :: Word16 -> Int
-       , intToWord16     -- :: Int    -> Word16
        , word32ToInt     -- :: Word32 -> Int
+       , word64ToInt     -- :: Word64 -> Int
+
+       , intToWord8      -- :: Int    -> Word8
+       , intToWord16     -- :: Int    -> Word16
        , intToWord32     -- :: Int    -> Word32
+       , intToWord64     -- :: Int    -> Word64
 
-       , word32ToWord64  -- :: Word32 -> Word64
-       , word64ToWord32  -- :: Word64 -> Word32
-        
+        , word8ToInteger  -- :: Word8   -> Integer
+        , word16ToInteger -- :: Word16  -> Integer
+        , word32ToInteger -- :: Word32  -> Integer
         , word64ToInteger -- :: Word64  -> Integer
+
+       , integerToWord8  -- :: Integer -> Word8
+       , integerToWord16 -- :: Integer -> Word16
+       , integerToWord32 -- :: Integer -> Word32
        , integerToWord64 -- :: Integer -> Word64
 
        -- NB! GHC SPECIFIC:
        , wordToWord8     -- :: Word   -> Word8
-       , word8ToWord     -- :: Word8  -> Word
        , wordToWord16    -- :: Word   -> Word16
-       , word16ToWord    -- :: Word16 -> Word
        , wordToWord32    -- :: Word   -> Word32
-       , word32ToWord    -- :: Word32 -> Word
        , wordToWord64    -- :: Word   -> Word64
+
+       , word8ToWord     -- :: Word8  -> Word
+       , word16ToWord    -- :: Word16 -> Word
+       , word32ToWord    -- :: Word32 -> Word
        , word64ToWord    -- :: Word64 -> Word
 
        -- The "official" place to get these from is Addr.
@@ -89,39 +108,66 @@ module Word
        -- non-standard, GHC specific
        , wordToInt
 
+       -- Internal, do not use.
+       , word8ToWord#
+       , word16ToWord#
+       , word32ToWord#
+
        ) where
 
-import GlaExts
-import Ix
-import Bits
+#ifdef __HUGS__
+import PreludeBuiltin
+#else
+import PrelBase
 import CCall
-import Numeric (readDec, showInt)
 import PrelForeign
 import PrelIOBase
+import PrelAddr
+#endif
+import Ix
+import Bits
+import Ratio
+import Numeric (readDec, showInt)
 
 -----------------------------------------------------------------------------
 -- The "official" coercion functions
 -----------------------------------------------------------------------------
 
 word8ToWord32  :: Word8  -> Word32
-word32ToWord8  :: Word32 -> Word8
 word16ToWord32 :: Word16 -> Word32
+word32ToWord8  :: Word32 -> Word8
 word32ToWord16 :: Word32 -> Word16
 
-word8ToInt   :: Word8  -> Int
-intToWord8   :: Int    -> Word8
-word16ToInt  :: Word16 -> Int
-intToWord16  :: Int    -> Word16
+word8ToInt      :: Word8  -> Int
+word16ToInt     :: Word16 -> Int
+intToWord8      :: Int    -> Word8
+intToWord16     :: Int    -> Word16
+
+integerToWord8  :: Integer -> Word8
+integerToWord16 :: Integer -> Word16
 
-word8ToInt  = word32ToInt    . word8ToWord32
-intToWord8  = word32ToWord8  . intToWord32
-word16ToInt = word32ToInt    . word16ToWord32
-intToWord16 = word32ToWord16 . intToWord32
+word8ToInt      = word32ToInt     . word8ToWord32
+intToWord8      = word32ToWord8   . intToWord32
+word16ToInt     = word32ToInt     . word16ToWord32
+intToWord16     = word32ToWord16  . intToWord32
+word8ToInteger  = word32ToInteger . word8ToWord32
+word16ToInteger = word32ToInteger . word16ToWord32
+integerToWord8  = fromInteger
+integerToWord16 = fromInteger
 
+intToWord32 :: Int -> Word32
 intToWord32 (I# x)   = W32# ((int2Word# x) `and#` (case (maxBound::Word32) of W32# x# -> x#))
 --intToWord32 (I# x)   = W32# (int2Word# x)
+
+word32ToInt :: Word32 -> Int
 word32ToInt (W32# x) = I#   (word2Int# x)
 
+word32ToInteger :: Word32 -> Integer
+word32ToInteger (W32# x) = word2Integer x
+
+integerToWord32 :: Integer -> Word32
+integerToWord32 = fromInteger
+
 wordToInt :: Word -> Int
 wordToInt (W# w#) = I# (word2Int# w#)
 
@@ -143,6 +189,7 @@ instance CCallable Word8
 instance CReturnable Word8
 
 word8ToWord32 (W8#  x) = W32# x
+word8ToWord16 (W8#  x) = W16# x
 word32ToWord8 (W32# x) = W8# (wordToWord8# x)
 
 -- mask out upper three bytes.
@@ -202,37 +249,63 @@ instance Real Word8 where
 -- Note: no need to mask results here 
 -- as they cannot overflow.
 instance Integral Word8 where
-  div  (W8# x)  (W8# y)   = W8# (x `quotWord#` y)
-  quot (W8# x)  (W8# y)   = W8# (x `quotWord#` y)
-  rem  (W8# x)  (W8# y)   = W8# (x `remWord#` y)
-  mod  (W8# x)  (W8# y)   = W8# (x `remWord#` y)
+  div  x@(W8# x#)  (W8# y#) 
+    | y# `neWord#` (int2Word# 0#) = W8# (x# `quotWord#` y#)
+    | otherwise                   = divZeroError "div{Word8}" x
+
+  quot x@(W8# x#)  (W8# y#)   
+    | y# `neWord#` (int2Word# 0#) = W8# (x# `quotWord#` y#)
+    | otherwise                   = divZeroError "quot{Word8}" x
+
+  rem  x@(W8# x#)  (W8# y#)
+    | y# `neWord#` (int2Word# 0#) = W8# (x# `remWord#` y#)
+    | otherwise                   = divZeroError "rem{Word8}" x
+
+  mod  x@(W8# x#)  (W8# y#)
+    | y# `neWord#` (int2Word# 0#) = W8# (x# `remWord#` y#)
+    | otherwise                   = divZeroError "mod{Word8}" x
+
   quotRem (W8# x) (W8# y) = (W8# (x `quotWord#` y), W8# (x `remWord#` y))
   divMod  (W8# x) (W8# y) = (W8# (x `quotWord#` y), W8# (x `remWord#` y))
-  toInteger (W8# x)       = word2Integer# x
+
+  toInteger (W8# x)       = word2Integer x
   toInt x                 = word8ToInt x
 
 instance Ix Word8 where
     range (m,n)          = [m..n]
-    index b@(m,n) i
+    index b@(m,_) i
           | inRange b i = word8ToInt (i-m)
-          | otherwise   = error (showString "Ix{Word8}.index: Index " .
-                                 showParen True (showsPrec 0 i) .
-                                  showString " out of range " $
-                                 showParen True (showsPrec 0 b) "")
+          | otherwise   = indexError i b "Word8"
     inRange (m,n) i      = m <= i && i <= n
 
 instance Enum Word8 where
-    toEnum    (I# i)  = W8# (intToWord8# i)
+    succ w         
+      | w == maxBound = succError "Word8"
+      | otherwise     = w+1
+    pred w         
+      | w == minBound = predError "Word8"
+      | otherwise     = w-1
+
+    toEnum   i@(I# i#)  
+      | i >= toInt (minBound::Word8) && i <= toInt (maxBound::Word8) 
+      = W8# (intToWord8# i#)
+      | otherwise
+      = toEnumError "Word8" i (minBound::Word8,maxBound::Word8)
+
     fromEnum  (W8# w) = I# (word2Int# w)
-    enumFrom c       = map toEnum [fromEnum c .. fromEnum (maxBound::Word8)]
-    enumFromThen c d = map toEnum [fromEnum c, fromEnum d .. fromEnum (last::Word8)]
-                      where last = if d < c then minBound else maxBound
+    enumFrom c        = map toEnum [fromEnum c .. fromEnum (maxBound::Word8)]
+    enumFromThen c d  = map toEnum [fromEnum c, fromEnum d .. fromEnum last]
+                       where 
+                        last :: Word8
+                        last 
+                         | d < c     = minBound
+                         | otherwise = maxBound
 
 instance Read Word8 where
-    readsPrec p = readDec
+    readsPrec _ = readDec
 
 instance Show Word8 where
-    showsPrec p = showInt
+    showsPrec _ = showInt
 
 --
 -- Word8s are represented by an (unboxed) 32-bit Word.
@@ -275,6 +348,10 @@ instance Bits Word8 where
 pow2# :: Int# -> Int#
 pow2# x# = word2Int# (shiftL# (int2Word# 1#) x#)
 
+word2Integer :: Word# -> Integer
+word2Integer w = case word2Integer# w of
+                       (# a, s, d #) -> J# a s d
+
 pow2_64# :: Int# -> Int64#
 pow2_64# x# = word64ToInt64# (shiftL64# (wordToWord64# (int2Word# 1#)) x#)
 
@@ -299,6 +376,7 @@ instance CCallable Word16
 instance CReturnable Word16
 
 word16ToWord32 (W16# x) = W32# x
+word16ToWord8  (W16# x) = W8# (wordToWord8# x)
 word32ToWord16 (W32# x) = W16# (wordToWord16# x)
 
 -- mask out upper 16 bits.
@@ -349,37 +427,63 @@ instance Real Word16 where
   toRational x = toInteger x % 1
 
 instance Integral Word16 where
-  div  (W16# x)  (W16# y)   = W16# (x `quotWord#` y)
-  quot (W16# x)  (W16# y)   = W16# (x `quotWord#` y)
-  rem  (W16# x)  (W16# y)   = W16# (x `remWord#` y)
-  mod  (W16# x)  (W16# y)   = W16# (x `remWord#` y)
+  div  x@(W16# x#)  (W16# y#)
+   | y# `neWord#` (int2Word# 0#) = W16# (x# `quotWord#` y#)
+   | otherwise                   = divZeroError "div{Word16}" x
+
+  quot x@(W16# x#) (W16# y#)
+   | y# `neWord#`(int2Word# 0#)  = W16# (x# `quotWord#` y#)
+   | otherwise                   = divZeroError "quot{Word16}" x
+
+  rem  x@(W16# x#) (W16# y#)
+   | y# `neWord#` (int2Word# 0#) = W16# (x# `remWord#` y#)
+   | otherwise                   = divZeroError "rem{Word16}" x
+
+  mod  x@(W16# x#)  (W16# y#)
+   | y# `neWord#` (int2Word# 0#) = W16# (x# `remWord#` y#)
+   | otherwise                  = divZeroError "mod{Word16}" x
+
   quotRem (W16# x) (W16# y) = (W16# (x `quotWord#` y), W16# (x `remWord#` y))
   divMod  (W16# x) (W16# y) = (W16# (x `quotWord#` y), W16# (x `remWord#` y))
-  toInteger (W16# x)        = word2Integer# x
+
+  toInteger (W16# x)        = word2Integer x
   toInt x                   = word16ToInt x
 
 instance Ix Word16 where
   range (m,n)          = [m..n]
-  index b@(m,n) i
+  index b@(m,_) i
          | inRange b i = word16ToInt (i - m)
-         | otherwise   = error (showString "Ix{Word16}.index: Index " .
-                               showParen True (showsPrec 0 i) .
-                                showString " out of range " $
-                               showParen True (showsPrec 0 b) "")
+         | otherwise   = indexError i b "Word16"
   inRange (m,n) i      = m <= i && i <= n
 
 instance Enum Word16 where
-  toEnum    (I# i)   = W16# (intToWord16# i)
-  fromEnum  (W16# w) = I# (word2Int# w)
-  enumFrom c       = map toEnum [fromEnum c .. fromEnum (maxBound::Word16)]
-  enumFromThen c d = map toEnum [fromEnum c, fromEnum d .. fromEnum (last::Word16)]
-                      where last = if d < c then minBound else maxBound
+    succ w         
+      | w == maxBound = succError "Word16"
+      | otherwise     = w+1
+    pred w
+      | w == minBound = predError "Word16"
+      | otherwise     = w-1
+
+    toEnum   i@(I# i#)  
+      | i >= toInt (minBound::Word16) && i <= toInt (maxBound::Word16)
+      = W16# (intToWord16# i#)
+      | otherwise
+      = toEnumError "Word16" i (minBound::Word16,maxBound::Word16)
+
+    fromEnum  (W16# w) = I# (word2Int# w)
+    enumFrom c       = map toEnum [fromEnum c .. fromEnum (maxBound::Word16)]
+    enumFromThen c d = map toEnum [fromEnum c, fromEnum d .. fromEnum last]
+                      where 
+                        last :: Word16
+                        last 
+                         | d < c     = minBound
+                         | otherwise = maxBound
 
 instance Read Word16 where
-  readsPrec p = readDec
+  readsPrec _ = readDec
 
 instance Show Word16 where
-  showsPrec p = showInt
+  showsPrec _ = showInt
 
 instance Bits Word16 where
   (W16# x)  .&.  (W16# y)  = W16# (x `and#` y)
@@ -477,8 +581,9 @@ intToWord32#  :: Int#  -> Word#
 wordToWord32# :: Word# -> Word#
 
 #if WORD_SIZE_IN_BYTES == 8
-intToWord32#  i# = (int2Word# i#) `and#` (int2Word# 0xffffffff)
-wordToWord32# w# = w# `and#` (int2Word# 0xffffffff)
+intToWord32#  i#  = (int2Word# i#) `and#` (int2Word# 0xffffffff#)
+wordToWord32# w#  = w# `and#` (int2Word# 0xffffffff#)
+wordToWord64# w#  = w#
 #else
 intToWord32#  i# = int2Word# i#
 wordToWord32# w# = w#
@@ -497,60 +602,109 @@ instance Real Word32 where
     toRational x = toInteger x % 1
 
 instance Integral Word32 where
-    div  x y           =  quotWord32 x y
-    quot x y           =  quotWord32 x y
-    rem         x y           =  remWord32 x y
-    mod  x y           =  remWord32 x y
+    div  x y 
+      | y /= 0         = quotWord32 x y
+      | otherwise      = divZeroError "div{Word32}" x
+
+    quot x y
+      | y /= 0         = quotWord32 x y
+      | otherwise      = divZeroError "quot{Word32}" x
+
+    rem         x y
+      | y /= 0         = remWord32 x y
+      | otherwise      = divZeroError "rem{Word32}" x
+
+    mod  x y
+      | y /= 0         = remWord32 x y
+      | otherwise      = divZeroError "mod{Word32}" x
+
     quotRem a b        = (a `quotWord32` b, a `remWord32` b)
     divMod x y         = quotRem x y
-    toInteger (W32# x) = word2Integer# x
+
+    toInteger (W32# x) = word2Integer x
     toInt     (W32# x) = I# (word2Int# x)
 
 {-# INLINE quotWord32 #-}
 {-# INLINE remWord32  #-}
+remWord32, quotWord32 :: Word32 -> Word32 -> Word32
 (W32# x) `quotWord32` (W32# y) = W32# (x `quotWord#` y)
 (W32# x) `remWord32`  (W32# y) = W32# (x `remWord#`  y)
 
 instance Ix Word32 where
     range (m,n)          = [m..n]
-    index b@(m,n) i
+    index b@(m,_) i
           | inRange b i = word32ToInt (i - m)
-          | otherwise   = error (showString "Ix{Word32}.index: Index " .
-                                 showParen True (showsPrec 0 i) .
-                                  showString " out of range " $
-                                 showParen True (showsPrec 0 b) "")
+          | otherwise   = indexError i b "Word32"
     inRange (m,n) i      = m <= i && i <= n
 
 instance Enum Word32 where
-    toEnum                  = intToWord32
-    fromEnum                = word32ToInt   -- lossy, don't use.
-    enumFrom w              = eft32 w 1
-    enumFromTo   w1 w2      = eftt32 w1 1 (> w2)
-    enumFromThen w1 w2      = eftt32 w1 (w2 - w1) (>last)
-        where 
+    succ w         
+      | w == maxBound = succError "Word32"
+      | otherwise     = w+1
+    pred w         
+      | w == minBound = predError "Word32"
+      | otherwise     = w-1
+
+     -- the toEnum/fromEnum will fail if the mapping isn't legal,
+     -- use the intTo* & *ToInt coercion functions to 'bypass' these range checks.
+    toEnum   x
+      | x >= 0    = intToWord32 x
+      | otherwise
+      = toEnumError "Word32" x (minBound::Word32,maxBound::Word32)
+
+    fromEnum   x
+      | x <= intToWord32 (maxBound::Int)
+      = word32ToInt x
+      | otherwise
+      = fromEnumError "Word32" x
+
+    enumFrom w           = [w .. maxBound]
+    enumFromTo   w1 w2
+       | w1 <= w2        = eftt32 True{-increasing-} w1 diff_f last
+       | otherwise      = []
+       where
+         last = (> w2)
+        diff_f x = x + 1 
+         
+    enumFromThen w1 w2   = [w1,w2 .. last]
+       where
+        last :: Word32
         last
-         | w1 < w2   = maxBound::Word32
+         | w1 <=w2   = maxBound
          | otherwise = minBound
 
-eftt32 :: Word32 -> Word32 -> (Word32->Bool) -> [Word32]
-eftt32 now step done = go now
+    enumFromThenTo w1 w2 wend  = eftt32 increasing w1 step_f last
+     where
+       increasing = w1 <= w2
+       diff1 = w2 - w1
+       diff2 = w1 - w2
+       
+       last
+        | increasing = (> wend)
+       | otherwise  = (< wend)
+
+       step_f 
+        | increasing = \ x -> x + diff1
+        | otherwise  = \ x -> x - diff2
+
+
+eftt32 :: Bool -> Word32 -> (Word32 -> Word32) -> (Word32-> Bool) -> [Word32]
+eftt32 increasing init stepper done = go init
   where
-   go now
-     | done now  = []
-     | otherwise = now : go (now+step)
+    go now
+     | done now                    = []
+     | increasing     && now > nxt = [now] -- oflow
+     | not increasing && now < nxt = [now] -- uflow
+     | otherwise                   = now : go nxt
+     where
+      nxt = stepper now 
 
-eft32 :: Word32 -> Word32 -> [Word32]
-eft32 now step = go now
-  where 
-   go x
-    | x == maxBound = [x]
-    | otherwise     = x:go (x+step)
 
 instance Read Word32 where
-    readsPrec p = readDec
+    readsPrec _ = readDec
 
 instance Show Word32 where
-    showsPrec p = showInt
+    showsPrec _ = showInt
 
 instance Bits Word32 where
   (W32# x)  .&.  (W32# y)  = W32# (x `and#` y)
@@ -594,11 +748,23 @@ sizeofWord32 = 4
 
 \begin{code}
 #if WORD_SIZE_IN_BYTES == 8
-data Word64 = W64# Word#
+--data Word64 = W64# Word#
 
 word32ToWord64 :: Word32 -> Word64
 word32ToWord64 (W32 w#) = W64# w#
 
+word8ToWord64 :: Word8 -> Word64
+word8ToWord64 (W8# w#) = W64# w#
+
+word64ToWord8 :: Word64 -> Word8
+word64ToWord8 (W64# w#) = W8# (w# `and#` (int2Word# 0xff#))
+
+word16ToWord64 :: Word16 -> Word64
+word16ToWord64 (W16# w#) = W64# w#
+
+word64ToWord16 :: Word64 -> Word16
+word64ToWord16 (W64# w#) = W16# (w# `and#` (int2Word# 0xffff#))
+
 wordToWord32# :: Word# -> Word#
 wordToWord32# w# = w# `and#` (case (maxBound::Word32) of W# x# -> x#)
 
@@ -641,51 +807,30 @@ instance Num Word64 where
   fromInteger (J# a# s# d#) = W64# (integer2Word# a# s# d#)
   fromInt       = intToWord64
 
-instance Bounded Word64 where
-  minBound = 0
-  maxBound = minBound - 1
-
-instance Real Word64 where
-  toRational x = toInteger x % 1
-
 -- Note: no need to mask results here 
 -- as they cannot overflow.
 instance Integral Word64 where
-  div  (W64# x)  (W64# y)   = W64# (x `quotWord#` y)
-  quot (W64# x)  (W64# y)   = W64# (x `quotWord#` y)
-  rem  (W64# x)  (W64# y)   = W64# (x `remWord#` y)
-  mod  (W64# x)  (W64# y)   = W64# (x `remWord#` y)
-  quotRem (W64# x) (W64# y) = (W64# (x `quotWord#` y), W64# (x `remWord#` y))
-  divMod  (W64# x) (W64# y) = (W64# (x `quotWord#` y), W64# (x `remWord#` y))
-  toInteger (W64# x)        = word2Integer# x
-  toInt x                   = word64ToInt x
+  div  x@(W64# x#)  (W64# y#)
+    | y# `neWord#` (int2Word# 0#)  = W64# (x# `quotWord#` y#)
+    | otherwise                    = divZeroError "div{Word64}" x
 
-instance Ix Word64 where
-    range (m,n)          = [m..n]
-    index b@(m,n) i
-          | inRange b i = word64ToInt (i-m)
-          | otherwise   = error (showString "Ix{Word64}.index: Index " .
-                                 showParen True (showsPrec 0 i) .
-                                  showString " out of range " $
-                                 showParen True (showsPrec 0 b) "")
-    inRange (m,n) i      = m <= i && i <= n
+  quot x@(W64# x#)  (W64# y#)
+    | y# `neWord#` (int2Word# 0#)  = W64# (x# `quotWord#` y#)
+    | otherwise                    = divZeroError "quot{Word64}" x
 
-instance Enum Word64 where
-    toEnum    (I# i)        = W64# (intToWord# i)
-    fromEnum  (W64# w)      = I# (word2Int# w)    -- lossy, don't use.
-    enumFrom w              = eft64 w 1
-    enumFromTo   w1 w2      = eftt64 w1 1 (> w2)
-    enumFromThen w1 w2      = eftt64 w1 (w2 - w1) (>last)
-        where 
-        last
-         | w1 < w2   = maxBound::Word64
-         | otherwise = minBound
+  rem  x@(W64# x#)  (W64# y#)
+    | y# `neWord#` (int2Word# 0#)  = W64# (x# `remWord#` y#)
+    | otherwise                    = divZeroError "rem{Word64}" x
 
-instance Read Word64 where
-    readsPrec p = readDec
+  mod  (W64# x)  (W64# y)   
+    | y# `neWord#` (int2Word# 0#)  = W64# (x `remWord#` y)
+    | otherwise                    = divZeroError "mod{Word64}" x
 
-instance Show Word64 where
-    showsPrec p = showInt
+  quotRem (W64# x) (W64# y) = (W64# (x `quotWord#` y), W64# (x `remWord#` y))
+  divMod  (W64# x) (W64# y) = (W64# (x `quotWord#` y), W64# (x `remWord#` y))
+
+  toInteger (W64# x)        = word2Integer# x
+  toInt x                   = word64ToInt x
 
 
 instance Bits Word64 where
@@ -734,13 +879,28 @@ word32ToWord64 (W32# w#) = W64# (wordToWord64# w#)
 word64ToWord32 :: Word64 -> Word32
 word64ToWord32 (W64# w#) = W32# (word64ToWord# w#)
 
+word8ToWord64 :: Word8 -> Word64
+word8ToWord64 (W8# w#) = W64# (wordToWord64# w#)
+
+word64ToWord8 :: Word64 -> Word8
+word64ToWord8 (W64# w#) = W8# ((word64ToWord# w#) `and#` (int2Word# 0xff#))
+
+word16ToWord64 :: Word16 -> Word64
+word16ToWord64 (W16# w#) = W64# (wordToWord64# w#)
+
+word64ToWord16 :: Word64 -> Word16
+word64ToWord16 (W64# w#) = W16# ((word64ToWord# w#) `and#` (int2Word# 0xffff#))
+
+
 word64ToInteger :: Word64 -> Integer
-word64ToInteger (W64# w#) = word64ToInteger# w#
+word64ToInteger (W64# w#) = 
+  case word64ToInteger# w# of
+    (# a#, s#, p# #) -> J# a# s# p#
 
 word64ToInt :: Word64 -> Int
 word64ToInt w = 
    case w `quotRem` 0x100000000 of 
-     (h,l) -> toInt (word64ToWord32 l)
+     (_,l) -> toInt (word64ToWord32 l)
 
 intToWord64# :: Int# -> Word64#
 intToWord64# i# = wordToWord64# (int2Word# i#)
@@ -751,12 +911,6 @@ intToWord64 (I# i#) = W64# (intToWord64# i#)
 integerToWord64 :: Integer -> Word64
 integerToWord64 (J# a# s# d#) = W64# (integerToWord64# a# s# d#)
 
-instance Show Word64 where
-  showsPrec p x = showsPrec p (word64ToInteger x)
-
-instance Read Word64 where
-  readsPrec p s = [ (integerToWord64 x,r) | (x,r) <- readDec s ]
-
 instance Eq  Word64     where 
   (W64# x) == (W64# y) = x `eqWord64#` y
   (W64# x) /= (W64# y) = not (x `eqWord64#` y)
@@ -788,15 +942,9 @@ instance Num Word64 where
   fromInteger i = integerToWord64 i
   fromInt       = intToWord64
 
-instance Bounded Word64 where
-  minBound = 0
-  maxBound = minBound - 1
-
-instance Real Word64 where
-  toRational x = toInteger x % 1
-
 -- Note: no need to mask results here 
 -- as they cannot overflow.
+-- ToDo: protect against div by zero.
 instance Integral Word64 where
   div  (W64# x)  (W64# y)   = W64# (x `quotWord64#` y)
   quot (W64# x)  (W64# y)   = W64# (x `quotWord64#` y)
@@ -808,27 +956,6 @@ instance Integral Word64 where
   toInt x                   = word64ToInt x
 
 
-instance Ix Word64 where
-    range (m,n)          = [m..n]
-    index b@(m,n) i
-          | inRange b i = word64ToInt (i-m)
-          | otherwise   = error (showString "Ix{Word64}.index: Index " .
-                                 showParen True (showsPrec 0 i) .
-                                  showString " out of range " $
-                                 showParen True (showsPrec 0 b) "")
-    inRange (m,n) i      = m <= i && i <= n
-
-instance Enum Word64 where
-    toEnum    (I# i)        = W64# (intToWord64# i)
-    fromEnum  (W64# w)      = I# (word2Int# (word64ToWord# w))  -- lossy, don't use.
-    enumFrom w              = eft64 w 1
-    enumFromTo   w1 w2      = eftt64 w1 1 (> w2)
-    enumFromThen w1 w2      = eftt64 w1 (w2 - w1) (>last)
-        where 
-        last
-         | w1 < w2   = maxBound::Word64
-         | otherwise = minBound
-
 instance Bits Word64 where
   (W64# x)  .&.  (W64# y)    = W64# (x `and64#` y)
   (W64# x)  .|.  (W64# y)    = W64# (x `or64#` y)
@@ -866,6 +993,7 @@ instance Bits Word64 where
   bitSize  _    = 64
   isSigned _    = False
 
+compareWord64# :: Word64# -> Word64# -> Ordering
 compareWord64# i# j# 
  | i# `ltWord64#` j# = LT
  | i# `eqWord64#` j# = EQ
@@ -976,50 +1104,85 @@ shiftRL64# a# b# =
     W64# w# -> w#
 
 word64ToWord# :: Word64# -> Word#
-word64ToWord# w# =
-  case (unsafePerformIO (_ccall_ stg_word64ToWord w#)) of
+word64ToWord# w64# =
+  case (unsafePerformIO (_ccall_ stg_word64ToWord w64#)) of
     W# w# -> w#
       
 wordToWord64# :: Word# -> Word64#
 wordToWord64# w# =
   case (unsafePerformIO (_ccall_ stg_wordToWord64 w#)) of
-    W64# w# -> w#
+    W64# w64# -> w64#
 
 word64ToInt64# :: Word64# -> Int64#
-word64ToInt64# w# =
-  case (unsafePerformIO (_ccall_ stg_word64ToInt64 w#)) of
+word64ToInt64# w64# =
+  case (unsafePerformIO (_ccall_ stg_word64ToInt64 w64#)) of
     I64# i# -> i#
 
 int64ToWord64# :: Int64# -> Word64#
-int64ToWord64# w# =
-  case (unsafePerformIO (_ccall_ stg_int64ToWord64 w#)) of
+int64ToWord64# i64# =
+  case (unsafePerformIO (_ccall_ stg_int64ToWord64 i64#)) of
     W64# w# -> w#
 
 intToInt64# :: Int# -> Int64#
 intToInt64# i# =
   case (unsafePerformIO (_ccall_ stg_intToInt64 i#)) of
-    I64# i# -> i#
+    I64# i64# -> i64#
       
 #endif
 
+instance Enum Word64 where
+    succ w         
+      | w == maxBound = succError "Word64"
+      | otherwise     = w+1
+    pred w         
+      | w == minBound = predError "Word64"
+      | otherwise     = w-1
+
+    toEnum i
+      | i >= 0    = intToWord64 i
+      | otherwise 
+      = toEnumError "Word64" i (minBound::Word64,maxBound::Word64)
+
+    fromEnum w
+      | w <= intToWord64 (maxBound::Int)
+      = word64ToInt w
+      | otherwise
+      = fromEnumError "Word64" w
+
+    enumFrom e1        = map integerToWord64 [word64ToInteger e1 .. word64ToInteger maxBound]
+    enumFromTo e1 e2   = map integerToWord64 [word64ToInteger e1 .. word64ToInteger e2]
+    enumFromThen e1 e2 = map integerToWord64 [word64ToInteger e1, word64ToInteger e2 .. word64ToInteger last]
+                      where 
+                         last :: Word64
+                         last 
+                          | e2 < e1   = minBound
+                          | otherwise = maxBound
+
+    enumFromThenTo e1 e2 e3 = map integerToWord64 [word64ToInteger e1, word64ToInteger e2 .. word64ToInteger e3]
+
+instance Show Word64 where
+  showsPrec p x = showsPrec p (word64ToInteger x)
+
+instance Read Word64 where
+  readsPrec _ s = [ (integerToWord64 x,r) | (x,r) <- readDec s ]
+
+instance Ix Word64 where
+    range (m,n)          = [m..n]
+    index b@(m,_) i
+          | inRange b i = word64ToInt (i-m)
+          | otherwise   = indexError i b "Word64"
+    inRange (m,n) i      = m <= i && i <= n
+
+instance Bounded Word64 where
+  minBound = 0
+  maxBound = minBound - 1
+
+instance Real Word64 where
+  toRational x = toInteger x % 1
+
 sizeofWord64 :: Word32
 sizeofWord64 = 8
 
--- Enum Word64 helper funs:
-
-eftt64 :: Word64 -> Word64 -> (Word64->Bool) -> [Word64]
-eftt64 now step done = go now
-  where
-   go now
-     | done now  = []
-     | otherwise = now : go (now+step)
-
-eft64 :: Word64 -> Word64 -> [Word64]
-eft64 now step = go now
-  where 
-   go x
-    | x == maxBound = [x]
-    | otherwise     = x:go (x+step)
 \end{code}
 
 
@@ -1030,19 +1193,30 @@ the GHC specific Word type:
 
 \begin{code}
 wordToWord8  :: Word -> Word8
-word8ToWord  :: Word8 -> Word
 wordToWord16 :: Word -> Word16
-word16ToWord :: Word16 -> Word
 wordToWord32 :: Word -> Word32
+
+word8ToWord  :: Word8 -> Word
+word16ToWord :: Word16 -> Word
 word32ToWord :: Word32 -> Word
 
-word8ToWord (W8# w#)   = W# w#
+word8ToWord#   :: Word8 -> Word#
+word16ToWord#  :: Word16 -> Word#
+word32ToWord#  :: Word32 -> Word#
+
+word8ToWord  (W8# w#)   = W# w#
+word8ToWord# (W8# w#)   = w#
+
 wordToWord8 (W# w#)    = W8# (w# `and#` (case (maxBound::Word8) of W8# x# -> x#))
-word16ToWord (W16# w#) = W# w#
+word16ToWord  (W16# w#) = W# w#
+word16ToWord# (W16# w#) = w#
+
 wordToWord16 (W# w#)   = W16# (w# `and#` (case (maxBound::Word16) of W16# x# -> x#))
-word32ToWord (W32# w#) = W# w#
 wordToWord32 (W# w#)   = W32# (w# `and#` (case (maxBound::Word32) of W32# x# -> x#))
 
+word32ToWord  (W32# w#) = W# w#
+word32ToWord# (W32# w#) = w#
+
 wordToWord64  :: Word -> Word64
 wordToWord64 (W# w#) = W64# (wordToWord64# w#)
 
@@ -1059,6 +1233,7 @@ The remainder of this file consists of definitions which are only
 used in the implementation.
 
 \begin{code}
+signumReal :: (Ord a, Num a) => a -> a
 signumReal x | x == 0    =  0
             | x > 0     =  1
             | otherwise = -1
@@ -1145,36 +1320,36 @@ Read words out of mutable memory:
 
 \begin{code}
 readWord8OffAddr :: Addr -> Int -> IO Word8
-readWord8OffAddr a i = _casm_ `` %r=(StgWord8)(((StgWord8*)%0)[(StgInt)%1]); '' a i
+readWord8OffAddr a i = _casm_ `` %r=(StgNat8)(((StgNat8*)%0)[(StgInt)%1]); '' a i
 
 readWord16OffAddr  :: Addr -> Int -> IO Word16
-readWord16OffAddr a i = _casm_ `` %r=(StgWord16)(((StgWord16*)%0)[(StgInt)%1]); '' a i
+readWord16OffAddr a i = _casm_ `` %r=(StgNat16)(((StgNat16*)%0)[(StgInt)%1]); '' a i
 
 readWord32OffAddr  :: Addr -> Int -> IO Word32
-readWord32OffAddr a i = _casm_ `` %r=(StgWord32)(((StgWord32*)%0)[(StgInt)%1]); '' a i
+readWord32OffAddr a i = _casm_ `` %r=(StgNat32)(((StgNat32*)%0)[(StgInt)%1]); '' a i
 
 readWord64OffAddr  :: Addr -> Int -> IO Word64
 #if WORD_SIZE_IN_BYTES==8
 readWord64OffAddr a i = _casm_ `` %r=(StgWord)(((StgWord*)%0)[(StgInt)%1]); '' a i
 #else
-readWord64OffAddr a i = _casm_ `` %r=(StgWord64)(((StgWord64*)%0)[(StgInt)%1]); '' a i
+readWord64OffAddr a i = _casm_ `` %r=(StgNat64)(((StgNat64*)%0)[(StgInt)%1]); '' a i
 #endif
 
 #ifndef __PARALLEL_HASKELL__
 readWord8OffForeignObj :: ForeignObj -> Int -> IO Word8
-readWord8OffForeignObj fo i = _casm_ `` %r=(StgWord8)(((StgWord8*)%0)[(StgInt)%1]); '' fo i
+readWord8OffForeignObj fo i = _casm_ `` %r=(StgNat8)(((StgNat8*)%0)[(StgInt)%1]); '' fo i
 
 readWord16OffForeignObj  :: ForeignObj -> Int -> IO Word16
-readWord16OffForeignObj fo i = _casm_ `` %r=(StgWord16)(((StgWord16*)%0)[(StgInt)%1]); '' fo i
+readWord16OffForeignObj fo i = _casm_ `` %r=(StgNat16)(((StgNat16*)%0)[(StgInt)%1]); '' fo i
 
 readWord32OffForeignObj  :: ForeignObj -> Int -> IO Word32
-readWord32OffForeignObj fo i = _casm_ `` %r=(StgWord32)(((StgWord32*)%0)[(StgInt)%1]); '' fo i
+readWord32OffForeignObj fo i = _casm_ `` %r=(StgNat32)(((StgNat32*)%0)[(StgInt)%1]); '' fo i
 
 readWord64OffForeignObj  :: ForeignObj -> Int -> IO Word64
 #if WORD_SIZE_IN_BYTES==8
 readWord64OffForeignObj fo i = _casm_ `` %r=(StgWord)(((StgWord*)%0)[(StgInt)%1]); '' fo i
 #else
-readWord64OffForeignObj fo i = _casm_ `` %r=(StgWord64)(((StgWord64*)%0)[(StgInt)%1]); '' fo i
+readWord64OffForeignObj fo i = _casm_ `` %r=(StgNat64)(((StgNat64*)%0)[(StgInt)%1]); '' fo i
 #endif
 
 #endif 
@@ -1187,14 +1362,14 @@ in the IO implementation (a place where we *really* do care about cycles.)
 \begin{code}
 writeWord8OffAddr  :: Addr -> Int -> Word8  -> IO ()
 writeWord8OffAddr (A# a#) (I# i#) (W8# w#) = IO $ \ s# ->
-      case (writeCharOffAddr# a# i# (chr# (word2Int# w#)) s#) of s2# -> IOok s2# () 
+      case (writeCharOffAddr# a# i# (chr# (word2Int# w#)) s#) of s2# -> (# s2#, () #)
 
 writeWord16OffAddr :: Addr -> Int -> Word16 -> IO ()
-writeWord16OffAddr a i e = _casm_ `` (((StgWord16*)%0)[(StgInt)%1])=(StgWord16)%2; '' a i e
+writeWord16OffAddr a i e = _casm_ `` (((StgNat16*)%0)[(StgInt)%1])=(StgNat16)%2; '' a i e
 
 writeWord32OffAddr :: Addr -> Int -> Word32 -> IO ()
-writeWord32OffAddr (A# a#) i@(I# i#) (W32# w#) = IO $ \ s# ->
-      case (writeWordOffAddr#  a# i'# w# s#) of s2# -> IOok s2# () 
+writeWord32OffAddr (A# a#) i (W32# w#) = IO $ \ s# ->
+      case (writeWordOffAddr#  a# i'# w# s#) of s2# -> (# s2#, () #)
  where
    -- adjust index to be in Word units, not Word32 ones.
   (I# i'#) 
@@ -1207,22 +1382,22 @@ writeWord32OffAddr (A# a#) i@(I# i#) (W32# w#) = IO $ \ s# ->
 writeWord64OffAddr :: Addr -> Int -> Word64 -> IO ()
 #if WORD_SIZE_IN_BYTES==8
 writeWord64OffAddr (A# a#) (I# i#) (W64# w#) = IO $ \ s# ->
-      case (writeWordOffAddr#  a# i# w# s#) of s2# -> IOok s2# () 
+      case (writeWordOffAddr#  a# i# w# s#) of s2# -> (# s2#, () #)
 #else
 writeWord64OffAddr (A# a#) (I# i#) (W64# w#) = IO $ \ s# ->
-      case (writeWord64OffAddr#  a# i# w# s#) of s2# -> IOok s2# () 
+      case (writeWord64OffAddr#  a# i# w# s#) of s2# -> (# s2#, () #)
 #endif
 
 #ifndef __PARALLEL_HASKELL__
 
 writeWord8OffForeignObj  :: ForeignObj -> Int -> Word8  -> IO ()
-writeWord8OffForeignObj fo i w = _casm_ `` (((StgWord16*)%0)[(StgInt)%1])=(StgWord16)%2; '' fo i w
+writeWord8OffForeignObj fo i w = _casm_ `` (((StgNat16*)%0)[(StgInt)%1])=(StgNat16)%2; '' fo i w
 
 writeWord16OffForeignObj :: ForeignObj -> Int -> Word16 -> IO ()
-writeWord16OffForeignObj fo i w = _casm_ `` (((StgWord16*)%0)[(StgInt)%1])=(StgWord16)%2; '' fo i w
+writeWord16OffForeignObj fo i w = _casm_ `` (((StgNat16*)%0)[(StgInt)%1])=(StgNat16)%2; '' fo i w
 
 writeWord32OffForeignObj :: ForeignObj -> Int -> Word32 -> IO ()
-writeWord32OffForeignObj fo i w = _casm_ `` (((StgWord16*)%0)[(StgInt)%1])=(StgWord16)%2; '' fo i' w
+writeWord32OffForeignObj fo i w = _casm_ `` (((StgNat16*)%0)[(StgInt)%1])=(StgNat16)%2; '' fo i' w
  where
    -- adjust index to be in Word units, not Word32 ones.
   i' 
@@ -1233,12 +1408,51 @@ writeWord32OffForeignObj fo i w = _casm_ `` (((StgWord16*)%0)[(StgInt)%1])=(StgW
 #endif
 
 writeWord64OffForeignObj :: ForeignObj -> Int -> Word64 -> IO ()
-#if WORD_SIZE_IN_BYTES==8
+# if WORD_SIZE_IN_BYTES==8
 writeWord64OffForeignObj fo i e = _casm_ `` (((StgWord*)%0)[(StgInt)%1])=(StgWord)%2; '' fo i e
-#else
-writeWord64OffForeignObj fo i e = _casm_ `` (((StgWord64*)%0)[(StgInt)%1])=(StgWord64)%2; '' fo i e
-#endif
+# else
+writeWord64OffForeignObj fo i e = _casm_ `` (((StgNat64*)%0)[(StgInt)%1])=(StgNat64)%2; '' fo i e
+# endif
 
 #endif
 
 \end{code}
+
+Utils for generating friendly error messages.
+
+\begin{code}
+{-# NOINLINE indexError #-}
+indexError :: (Show a) => a -> (a,a) -> String -> b
+indexError i rng tp
+  = error (showString "Ix{" . showString tp . showString "}.index: Index " .
+           showParen True (showsPrec 0 i) .
+          showString " out of range " $
+          showParen True (showsPrec 0 rng) "")
+
+toEnumError :: (Show a,Show b) => String -> a -> (b,b) -> c
+toEnumError inst_ty tag bnds
+  = error ("Enum.toEnum{" ++ inst_ty ++ "}: tag " ++
+           (showParen True (showsPrec 0 tag) $
+            " is outside of bounds " ++
+            show bnds))
+
+fromEnumError :: (Show a,Show b) => String -> a -> b
+fromEnumError inst_ty tag
+  = error ("Enum.fromEnum{" ++ inst_ty ++ "}: value " ++
+           (showParen True (showsPrec 0 tag) $
+            " is outside of Int's bounds " ++
+            show (minBound::Int,maxBound::Int)))
+
+succError :: String -> a
+succError inst_ty
+  = error ("Enum.succ{" ++ inst_ty ++ "}: tried to take `succ' of maxBound")
+
+predError :: String -> a
+predError inst_ty
+  = error ("Enum.pred{" ++ inst_ty ++ "}: tried to take `pred' of minBound")
+
+divZeroError :: (Show a) => String -> a -> b
+divZeroError meth v 
+  = error ("Integral." ++ meth ++ ": divide by 0 (" ++ show v ++ " / 0)")
+
+\end{code}