{-# LANGUAGE BangPatterns #-} {-# LANGUAGE CPP #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE MagicHash #-} {-# LANGUAGE StrictData #-} {-# LANGUAGE UnboxedTuples #-} {-# OPTIONS_GHC -funbox-strict-fields #-} ----------------------------------------------------------------------------- ---- | ---- Module : Data.WideWord.Word256 ---- ---- Maintainer : erikd@mega-nerd.com ---- Stability : experimental ---- Portability : non-portable (GHC extensions and primops) ---- ---- This module provides an opaque unsigned 256 bit value with the usual set ---- of typeclass instances one would expect for a fixed width unsigned integer ---- type. ---- Operations like addition, subtraction and multiplication etc provide a ---- "modulo 2^256" result as one would expect from a fixed width unsigned word. ------------------------------------------------------------------------------- #include module Data.WideWord.Word256 ( Word256 (..) , showHexWord256 , zeroWord256 ) where import Control.DeepSeq (NFData (..)) import Data.Bits (Bits (..), FiniteBits (..), shiftL) import Data.Data (Data, Typeable) import Data.Ix (Ix) import Foreign.Ptr (Ptr, castPtr) import Foreign.Storable (Storable (..)) import GHC.Base (Int (..), and#, int2Word#, minusWord#, not#, or#, plusWord#, plusWord2# , subWordC#, timesWord#, timesWord2#, xor#) import GHC.Enum (predError, succError) import GHC.Exts ((*#), (+#), Int#, State#, ByteArray#, MutableByteArray#, Addr#) import GHC.Real ((%)) import GHC.Word (Word64 (..), Word32) import Numeric (showHex) import Data.Primitive.Types (Prim (..), defaultSetByteArray#, defaultSetOffAddr#) data Word256 = Word256 { word256hi :: {-# UNPACK #-} !Word64 , word256m1 :: {-# UNPACK #-} !Word64 , word256m0 :: {-# UNPACK #-} !Word64 , word256lo :: {-# UNPACK #-} !Word64 } deriving (Eq, Data, Ix, Typeable) showHexWord256 :: Word256 -> String showHexWord256 (Word256 a3 a2 a1 a0) | a3 == 0 = if a2 == 0 then if a1 == 0 then showHex a0 "" else showHex a1 zeros0 ++ showHex a0 "" else showHex a2 zeros1 ++ showHex a1 zeros0 ++ showHex a0 "" | otherwise = showHex a3 zeros2 ++ showHex a2 zeros1 ++ showHex a1 zeros0 ++ showHex a0 "" where h0 = showHex a0 "" h1 = showHex a1 "" h2 = showHex a2 "" zeros0 = replicate (16 - length h0) '0' zeros1 = replicate (16 - length h1) '0' zeros2 = replicate (16 - length h2) '0' instance Show Word256 where show = show . toInteger256 instance Read Word256 where readsPrec p s = [(fromInteger256 (x :: Integer), r) | (x, r) <- readsPrec p s] instance Ord Word256 where compare = compare256 instance Bounded Word256 where minBound = zeroWord256 maxBound = Word256 maxBound maxBound maxBound maxBound instance Enum Word256 where succ = succ256 pred = pred256 toEnum = toEnum256 fromEnum = fromEnum256 instance Num Word256 where (+) = plus256 (-) = minus256 (*) = times256 negate = negate256 abs = id signum = signum256 fromInteger = fromInteger256 instance Bits Word256 where (.&.) = and256 (.|.) = or256 xor = xor256 complement = complement256 shiftL = shiftL256 unsafeShiftL = shiftL256 shiftR = shiftR256 unsafeShiftR = shiftR256 rotateL = rotateL256 rotateR = rotateR256 bitSize _ = 256 bitSizeMaybe _ = Just 256 isSigned _ = False testBit = testBit256 bit = bit256 popCount = popCount256 instance FiniteBits Word256 where finiteBitSize _ = 256 countLeadingZeros = countLeadingZeros256 countTrailingZeros = countTrailingZeros256 instance Real Word256 where toRational x = toInteger256 x % 1 instance Integral Word256 where quot n d = fst (quotRem256 n d) rem n d = snd (quotRem256 n d) div n d = fst (quotRem256 n d) mod n d = snd (quotRem256 n d) quotRem = quotRem256 divMod = quotRem256 toInteger = toInteger256 instance Storable Word256 where sizeOf _ = 4 * sizeOf (0 :: Word64) alignment _ = 4 * alignment (0 :: Word64) peek = peek256 peekElemOff = peekElemOff256 poke = poke256 pokeElemOff = pokeElemOff256 instance NFData Word256 where rnf (Word256 a3 a2 a1 a0) = rnf a3 `seq` rnf a2 `seq` rnf a1 `seq` rnf a0 instance Prim Word256 where sizeOf# = sizeOf256# alignment# = alignment256# indexByteArray# = indexByteArray256# readByteArray# = readByteArray256# writeByteArray# = writeByteArray256# setByteArray# = setByteArray256# indexOffAddr# = indexOffAddr256# readOffAddr# = readOffAddr256# writeOffAddr# = writeOffAddr256# setOffAddr# = setOffAddr256# {-# INLINE sizeOf# #-} {-# INLINE alignment# #-} {-# INLINE indexByteArray# #-} {-# INLINE readByteArray# #-} {-# INLINE writeByteArray# #-} {-# INLINE setByteArray# #-} {-# INLINE indexOffAddr# #-} {-# INLINE readOffAddr# #-} {-# INLINE writeOffAddr# #-} {-# INLINE setOffAddr# #-} -- ----------------------------------------------------------------------------- -- Rewrite rules. {-# RULES "fromIntegral :: Word256 -> Word256" fromIntegral = id :: Word256 -> Word256 "fromIntegral :: Int -> Word256" fromIntegral = \(I# i#) -> Word256 (W64# 0##) (W64# 0##) (W64# 0##) (W64# (int2Word# i#)) "fromIntegral :: Word -> Word256" fromIntegral = Word256 0 0 0 . (fromIntegral :: Word -> Word64) "fromIntegral :: Word32 -> Word256" fromIntegral = Word256 0 0 0 . (fromIntegral :: Word32 -> Word64) "fromIntegral :: Word64 -> Word256" fromIntegral = Word256 0 0 0 "fromIntegral :: Word256 -> Int" fromIntegral = \(Word256 _ _ _ w) -> fromIntegral w :: Int "fromIntegral :: Word256 -> Word" fromIntegral = \(Word256 _ _ _ w) -> fromIntegral w :: Word "fromIntegral :: Word256 -> Word32" fromIntegral = \(Word256 _ _ _ w) -> fromIntegral w :: Word32 "fromIntegral :: Word256 -> Word64" fromIntegral = \(Word256 _ _ _ w) -> w #-} -- ----------------------------------------------------------------------------- -- Functions for `Ord` instance. compare256 :: Word256 -> Word256 -> Ordering compare256 (Word256 a3 a2 a1 a0) (Word256 b3 b2 b1 b0) = case compare a3 b3 of LT -> LT GT -> GT EQ -> case compare a2 b2 of LT -> LT GT -> GT EQ -> case compare a1 b1 of LT -> LT GT -> GT EQ -> compare a0 b0 -- ----------------------------------------------------------------------------- -- Functions for `Enum` instance. succ256 :: Word256 -> Word256 succ256 (Word256 a3 a2 a1 a0) | a0 == maxBound = if a1 == maxBound then if a2 == maxBound then if a3 == maxBound then succError "Word256" else Word256 (a3 + 1) 0 0 0 else Word256 a3 (a2 + 1) 0 0 else Word256 a3 a2 (a1 + 1) 0 | otherwise = Word256 a3 a2 a1 (a0 + 1) pred256 :: Word256 -> Word256 pred256 (Word256 a3 a2 a1 a0) | a0 == 0 = if a1 == 0 then if a2 == 0 then if a3 == 0 then predError "Word256" else Word256 (a3 - 1) maxBound maxBound maxBound else Word256 a3 (a2 - 1) maxBound maxBound else Word256 a3 a2 (a1 - 1) maxBound | otherwise = Word256 a3 a2 a1 (a0 - 1) {-# INLINABLE toEnum256 #-} toEnum256 :: Int -> Word256 toEnum256 i = Word256 0 0 0 (toEnum i) {-# INLINABLE fromEnum256 #-} fromEnum256 :: Word256 -> Int fromEnum256 (Word256 _ _ _ a0) = fromEnum a0 -- ----------------------------------------------------------------------------- -- Functions for `Num` instance. {-# INLINABLE plus256 #-} plus256 :: Word256 -> Word256 -> Word256 plus256 (Word256 (W64# a3) (W64# a2) (W64# a1) (W64# a0)) (Word256 (W64# b3) (W64# b2) (W64# b1) (W64# b0)) = Word256 (W64# s3) (W64# s2) (W64# s1) (W64# s0) where !(# c1, s0 #) = plusWord2# a0 b0 !(# c2a, s1a #) = plusWord2# a1 b1 !(# c2b, s1 #) = plusWord2# s1a c1 c2 = plusWord# c2a c2b !(# c3a, s2a #) = plusWord2# a2 b2 !(# c3b, s2 #) = plusWord2# s2a c2 c3 = plusWord# c3a c3b s3 = plusWord# a3 (plusWord# b3 c3) {-# INLINABLE minus256 #-} minus256 :: Word256 -> Word256 -> Word256 minus256 (Word256 (W64# a3) (W64# a2) (W64# a1) (W64# a0)) (Word256 (W64# b3) (W64# b2) (W64# b1) (W64# b0)) = Word256 (W64# s3) (W64# s2) (W64# s1) (W64# s0) where !(# s0, v1 #) = subWordC# a0 b0 !(# s1, v2 #) = case v1 of 0# -> subWordC# a1 b1 _ -> case a1 of 0## -> (# minusWord# 0xFFFFFFFFFFFFFFFF## b1, 1# #) _ -> subWordC# (minusWord# a1 1##) b1 !(# s2, v3 #) = case v2 of 0# -> subWordC# a2 b2 _ -> case a2 of 0## -> (# minusWord# 0xFFFFFFFFFFFFFFFF## b2, 1# #) _ -> subWordC# (minusWord# a2 1##) b2 !s3 = case v3 of 0# -> minusWord# a3 b3 _ -> minusWord# (minusWord# a3 1##) b3 times256 :: Word256 -> Word256 -> Word256 times256 (Word256 (W64# a3) (W64# a2) (W64# a1) (W64# a0)) (Word256 (W64# b3) (W64# b2) (W64# b1) (W64# b0)) = Word256 (W64# r3) (W64# r2) (W64# r1) (W64# r0) where !(# c00, p00 #) = timesWord2# a0 b0 !(# c01, p01 #) = timesWord2# a0 b1 !(# c02, p02 #) = timesWord2# a0 b2 !p03 = timesWord# a0 b3 !(# c10, p10 #) = timesWord2# a1 b0 !(# c11, p11 #) = timesWord2# a1 b1 !p12 = timesWord# a1 b2 !(# c20, p20 #) = timesWord2# a2 b0 !p21 = timesWord# a2 b1 !p30 = timesWord# a3 b0 !r0 = p00 !c1 = c00 !(# c2x, r1a #) = plusWord2# p01 p10 !(# c2y, r1b #) = plusWord2# r1a c1 !(# c3w, c2 #) = plusWord2# c2x c2y !r1 = r1b !(# c3x, r2a #) = plusWord2# p11 p20 !(# c3y, r2b #) = plusWord2# p02 r2a !(# c3z, r2c #) = plusWord2# r2b c2 !(# c3s, r2d #) = plusWord2# r2c c01 !(# c3t, r2e #) = plusWord2# r2d c10 !r2 = r2e !r3 = p30 `plusWord#` p21 `plusWord#` p12 `plusWord#` p03 `plusWord#` c3w `plusWord#` c3x `plusWord#` c3y `plusWord#` c3z `plusWord#` c3s `plusWord#` c3t `plusWord#` c02 `plusWord#` c11 `plusWord#` c20 {-# INLINABLE negate256 #-} negate256 :: Word256 -> Word256 negate256 (Word256 (W64# a3) (W64# a2) (W64# a1) (W64# a0)) = case plusWord2# (not# a0) 1## of (# c1, s0 #) -> case plusWord2# (not# a1) c1 of (# c2, s1 #) -> case plusWord2# (not# a2) c2 of (# c3, s2 #) -> case plusWord# (not# a3) c3 of s3 -> Word256 (W64# s3) (W64# s2) (W64# s1) (W64# s0) {-# INLINABLE signum256 #-} signum256 :: Word256 -> Word256 signum256 (Word256 (W64# 0##) (W64# 0##) (W64# 0##) (W64# 0##)) = zeroWord256 signum256 _ = oneWord256 fromInteger256 :: Integer -> Word256 fromInteger256 i = Word256 (fromInteger $ i `shiftR` 192) (fromInteger $ i `shiftR` 128) (fromInteger $ i `shiftR` 64) (fromInteger i) -- ----------------------------------------------------------------------------- -- Functions for `Bits` instance. {-# INLINABLE and256 #-} and256 :: Word256 -> Word256 -> Word256 and256 (Word256 (W64# a3) (W64# a2) (W64# a1) (W64# a0)) (Word256 (W64# b3) (W64# b2) (W64# b1) (W64# b0)) = Word256 (W64# (and# a3 b3)) (W64# (and# a2 b2)) (W64# (and# a1 b1)) (W64# (and# a0 b0)) {-# INLINABLE or256 #-} or256 :: Word256 -> Word256 -> Word256 or256 (Word256 (W64# a3) (W64# a2) (W64# a1) (W64# a0)) (Word256 (W64# b3) (W64# b2) (W64# b1) (W64# b0)) = Word256 (W64# (or# a3 b3)) (W64# (or# a2 b2)) (W64# (or# a1 b1)) (W64# (or# a0 b0)) {-# INLINABLE xor256 #-} xor256 :: Word256 -> Word256 -> Word256 xor256 (Word256 (W64# a3) (W64# a2) (W64# a1) (W64# a0)) (Word256 (W64# b3) (W64# b2) (W64# b1) (W64# b0)) = Word256 (W64# (xor# a3 b3)) (W64# (xor# a2 b2)) (W64# (xor# a1 b1)) (W64# (xor# a0 b0)) {-# INLINABLE complement256 #-} complement256 :: Word256 -> Word256 complement256 (Word256 a3 a2 a1 a0) = Word256 (complement a3) (complement a2) (complement a1) (complement a0) -- Probably not worth inlining this. shiftL256 :: Word256 -> Int -> Word256 shiftL256 w@(Word256 a3 a2 a1 a0) s | s < 0 || s >= 256 = zeroWord256 | s == 0 = w | s > 192 = Word256 (a0 `shiftL` (s - 192)) 0 0 0 | s == 192 = Word256 a0 0 0 0 | s > 128 = Word256 (a1 `shiftL` (s - 128) + a0 `shiftR` (192 - s)) (a0 `shiftL` (s - 128)) 0 0 | s == 128 = Word256 a1 a0 0 0 | s > 64 = Word256 (a2 `shiftL` (s - 64) + a1 `shiftR` (128 - s)) (a1 `shiftL` (s - 64) + a0 `shiftR` (128 - s)) (a0 `shiftL` (s - 64)) 0 | s == 64 = Word256 a2 a1 a0 0 | otherwise = Word256 (a3 `shiftL` s + a2 `shiftR` (64 - s)) (a2 `shiftL` s + a1 `shiftR` (64 - s)) (a1 `shiftL` s + a0 `shiftR` (64 - s)) (a0 `shiftL` s) shiftR256 :: Word256 -> Int -> Word256 shiftR256 w@(Word256 a3 a2 a1 a0) s | s < 0 = zeroWord256 | s == 0 = w | s >= 256 = zeroWord256 | s > 192 = Word256 0 0 0 (a3 `shiftR` (s - 192)) | s == 192 = Word256 0 0 0 a3 | s > 128 = Word256 0 0 (a3 `shiftR` (s - 128)) (a2 `shiftR` (s - 128) + a3 `shiftL` (192 - s)) | s == 128 = Word256 0 0 a3 a2 | s > 64 = Word256 0 (a3 `shiftR` (s - 64)) (a2 `shiftR` (s - 64) + a3 `shiftL` (128 - s)) (a1 `shiftR` (s - 64) + a2 `shiftL` (128 - s)) | s == 64 = Word256 0 a3 a2 a1 | otherwise = Word256 (a3 `shiftR` s) (a2 `shiftR` s + a3 `shiftL` (64 - s)) (a1 `shiftR` s + a2 `shiftL` (64 - s)) (a0 `shiftR` s + a1 `shiftL` (64 - s)) rotateL256 :: Word256 -> Int -> Word256 rotateL256 w@(Word256 a3 a2 a1 a0) r | r < 0 = zeroWord256 | r == 0 = w | r >= 256 = rotateL256 w (r `mod` 256) | r >= 64 = rotateL256 (Word256 a2 a1 a0 a3) (r - 64) | otherwise = Word256 s3 s2 s1 s0 where s0 = a0 `shiftL` r + a3 `shiftR` (64 - r) s1 = a1 `shiftL` r + a0 `shiftR` (64 - r) s2 = a2 `shiftL` r + a1 `shiftR` (64 - r) s3 = a3 `shiftL` r + a2 `shiftR` (64 - r) rotateR256 :: Word256 -> Int -> Word256 rotateR256 w@(Word256 a3 a2 a1 a0) r | r < 0 = rotateR256 w (256 - (abs r `mod` 256)) | r == 0 = w | r >= 256 = rotateR256 w (r `mod` 256) | r >= 64 = rotateR256 (Word256 a0 a3 a2 a1) (r - 64) | otherwise = Word256 s3 s2 s1 s0 where s0 = a0 `shiftR` r + a1 `shiftL` (64 - r) s1 = a1 `shiftR` r + a2 `shiftL` (64 - r) s2 = a2 `shiftR` r + a3 `shiftL` (64 - r) s3 = a3 `shiftR` r + a0 `shiftL` (64 - r) testBit256 :: Word256 -> Int -> Bool testBit256 (Word256 a3 a2 a1 a0) i | i < 0 = False | i >= 256 = False | i >= 192 = testBit a3 (i - 192) | i >= 128 = testBit a2 (i - 128) | i >= 64 = testBit a1 (i - 64) | otherwise = testBit a0 i bit256 :: Int -> Word256 bit256 indx | indx < 0 = zeroWord256 | indx >= 256 = zeroWord256 | otherwise = shiftL256 oneWord256 indx popCount256 :: Word256 -> Int popCount256 (Word256 a3 a2 a1 a0) = popCount a3 + popCount a2 + popCount a1 + popCount a0 -- ----------------------------------------------------------------------------- -- Functions for `FiniteBits` instance. countLeadingZeros256 :: Word256 -> Int countLeadingZeros256 (Word256 a3 a2 a1 a0) = case countLeadingZeros a3 of 64 -> case countLeadingZeros a2 of 64 -> case countLeadingZeros a1 of 64 -> 192 + countLeadingZeros a0 res -> 128 + res res -> 64 + res res -> res countTrailingZeros256 :: Word256 -> Int countTrailingZeros256 (Word256 a3 a2 a1 a0) = case countTrailingZeros a0 of 64 -> case countTrailingZeros a1 of 64 -> case countTrailingZeros a2 of 64 -> 192 + countTrailingZeros a3 res -> 128 + res res -> 64 + res res -> res -- ----------------------------------------------------------------------------- -- Functions for `Integral` instance. -- TODO: This is inefficient, but the better version is rather -- tedious to write out. quotRem256 :: Word256 -> Word256 -> (Word256, Word256) quotRem256 a b = let (x,y) = quotRem (toInteger256 a) (toInteger256 b) in (fromInteger256 x, fromInteger256 y) toInteger256 :: Word256 -> Integer toInteger256 (Word256 a3 a2 a1 a0) = (toInteger a3 `shiftL` 192) + (toInteger a2 `shiftL` 128) + (toInteger a1 `shiftL` 64) + (toInteger a0) -- ----------------------------------------------------------------------------- -- Functions for `Storable` instance. peek256 :: Ptr Word256 -> IO Word256 peek256 ptr = Word256 <$> peekElemOff (castPtr ptr) index3 <*> peekElemOff (castPtr ptr) index2 <*> peekElemOff (castPtr ptr) index1 <*> peekElemOff (castPtr ptr) index0 peekElemOff256 :: Ptr Word256 -> Int -> IO Word256 peekElemOff256 ptr idx = Word256 <$> peekElemOff (castPtr ptr) (idx2 + index3) <*> peekElemOff (castPtr ptr) (idx2 + index2) <*> peekElemOff (castPtr ptr) (idx2 + index1) <*> peekElemOff (castPtr ptr) (idx2 + index0) where idx2 = 4 * idx poke256 :: Ptr Word256 -> Word256 -> IO () poke256 ptr (Word256 a3 a2 a1 a0) = do pokeElemOff (castPtr ptr) index3 a3 pokeElemOff (castPtr ptr) index2 a2 pokeElemOff (castPtr ptr) index1 a1 pokeElemOff (castPtr ptr) index0 a0 pokeElemOff256 :: Ptr Word256 -> Int -> Word256 -> IO () pokeElemOff256 ptr idx (Word256 a3 a2 a1 a0) = do pokeElemOff (castPtr ptr) (idx2 + index0) a0 pokeElemOff (castPtr ptr) (idx2 + index1) a1 pokeElemOff (castPtr ptr) (idx2 + index2) a2 pokeElemOff (castPtr ptr) (idx2 + index3) a3 where idx2 = 4 * idx -- ----------------------------------------------------------------------------- -- Functions for `Prim` instance. {-# INLINE sizeOf256# #-} sizeOf256# :: Word256 -> Int# sizeOf256# _ = 4# *# sizeOf# (undefined :: Word64) {-# INLINE alignment256# #-} alignment256# :: Word256 -> Int# alignment256# _ = alignment# (undefined :: Word64) {-# INLINE indexByteArray256# #-} indexByteArray256# :: ByteArray# -> Int# -> Word256 indexByteArray256# arr# i# = let i2# = 4# *# i# w = indexByteArray# arr# (i2# +# unInt index3) x = indexByteArray# arr# (i2# +# unInt index2) y = indexByteArray# arr# (i2# +# unInt index1) z = indexByteArray# arr# (i2# +# unInt index0) in Word256 w x y z {-# INLINE readByteArray256# #-} readByteArray256# :: MutableByteArray# s -> Int# -> State# s -> (# State# s, Word256 #) readByteArray256# arr# i# = \s0 -> case readByteArray# arr# (i2# +# unInt index3) s0 of (# s1, w #) -> case readByteArray# arr# (i2# +# unInt index2) s1 of (# s2, x #) -> case readByteArray# arr# (i2# +# unInt index1) s2 of (# s3, y #) -> case readByteArray# arr# (i2# +# unInt index0) s3 of (# s4, z #) -> (# s4, Word256 w x y z #) where i2# = 4# *# i# {-# INLINE writeByteArray256# #-} writeByteArray256# :: MutableByteArray# s -> Int# -> Word256 -> State# s -> State# s writeByteArray256# arr# i# (Word256 a b c d) = \s0 -> case writeByteArray# arr# (i2# +# unInt index3) a s0 of s1 -> case writeByteArray# arr# (i2# +# unInt index2) b s1 of s2 -> case writeByteArray# arr# (i2# +# unInt index1) c s2 of s3 -> case writeByteArray# arr# (i2# +# unInt index0) d s3 of s4 -> s4 where i2# = 4# *# i# {-# INLINE setByteArray256# #-} setByteArray256# :: MutableByteArray# s -> Int# -> Int# -> Word256 -> State# s -> State# s setByteArray256# = defaultSetByteArray# {-# INLINE indexOffAddr256# #-} indexOffAddr256# :: Addr# -> Int# -> Word256 indexOffAddr256# arr# i# = let i2# = 4# *# i# w = indexOffAddr# arr# (i2# +# unInt index3) x = indexOffAddr# arr# (i2# +# unInt index2) y = indexOffAddr# arr# (i2# +# unInt index1) z = indexOffAddr# arr# (i2# +# unInt index0) in Word256 w x y z {-# INLINE readOffAddr256# #-} readOffAddr256# :: Addr# -> Int# -> State# s -> (# State# s, Word256 #) readOffAddr256# arr# i# = \s0 -> case readOffAddr# arr# (i2# +# unInt index3) s0 of (# s1, w #) -> case readOffAddr# arr# (i2# +# unInt index2) s1 of (# s2, x #) -> case readOffAddr# arr# (i2# +# unInt index1) s2 of (# s3, y #) -> case readOffAddr# arr# (i2# +# unInt index0) s3 of (# s4, z #) -> (# s4, Word256 w x y z #) where i2# = 4# *# i# {-# INLINE writeOffAddr256# #-} writeOffAddr256# :: Addr# -> Int# -> Word256 -> State# s -> State# s writeOffAddr256# arr# i# (Word256 a b c d) = \s0 -> case writeOffAddr# arr# (i2# +# unInt index3) a s0 of s1 -> case writeOffAddr# arr# (i2# +# unInt index2) b s1 of s2 -> case writeOffAddr# arr# (i2# +# unInt index1) c s2 of s3 -> case writeOffAddr# arr# (i2# +# unInt index0) d s3 of s4 -> s4 where i2# = 4# *# i# {-# INLINE setOffAddr256# #-} setOffAddr256# :: Addr# -> Int# -> Int# -> Word256 -> State# s -> State# s setOffAddr256# = defaultSetOffAddr# -- ----------------------------------------------------------------------------- -- Constants. zeroWord256 :: Word256 zeroWord256 = Word256 0 0 0 0 oneWord256 :: Word256 oneWord256 = Word256 0 0 0 1 unInt :: Int -> Int# unInt (I# i#) = i# -- Use these indices to get the peek/poke ordering endian correct. index0, index1, index2, index3 :: Int #if WORDS_BIGENDIAN index0 = 3 index1 = 2 index2 = 1 index3 = 0 #else index0 = 0 index1 = 1 index2 = 2 index3 = 3 #endif