{-# LANGUAGE BangPatterns, CPP, MagicHash, UnboxedTuples #-} module Main (main) where import Data.List (group) import Data.Bits import Data.Word import Control.Monad import Unsafe.Coerce (unsafeCoerce#) import GHC.Word import GHC.Base import GHC.Num.Integer import qualified GHC.Num.Integer as I exportInteger :: Integer -> MutableByteArray# RealWorld -> Word# -> Int# -> IO Word exportInteger = I.integerToMutableByteArray exportIntegerAddr :: Integer -> Addr# -> Int# -> IO Word exportIntegerAddr = I.integerToAddr importInteger :: ByteArray# -> Word# -> Word# -> Int# -> Integer importInteger ba off sz = I.integerFromByteArray sz ba off importIntegerAddr :: Addr# -> Word# -> Int# -> IO Integer importIntegerAddr a l = I.integerFromAddr l a -- helpers data MBA = MBA { unMBA :: !(MutableByteArray# RealWorld) } data BA = BA { unBA :: !ByteArray# } newByteArray :: Word# -> IO MBA newByteArray sz = IO $ \s -> case newPinnedByteArray# (word2Int# sz) s of (# s, arr #) -> (# s, MBA arr #) indexByteArray :: ByteArray# -> Word# -> Word8 indexByteArray a# n# = W8# (indexWord8Array# a# (word2Int# n#)) -- indexMutableByteArray :: MutableByteArray# RealWorld -> Word# -> IO Word8 -- indexMutableByteArray a# n# = IO $ \s -> case readWord8Array# a# (word2Int# n#) s of (# s', v #) -> (# s', W# v #) writeByteArray :: MutableByteArray# RealWorld -> Int# -> Word8 -> IO () writeByteArray arr i (W8# w) = IO $ \s -> case writeWord8Array# arr i w s of s -> (# s, () #) lengthByteArray :: ByteArray# -> Word lengthByteArray ba = W# (int2Word# (sizeofByteArray# ba)) unpackByteArray :: ByteArray# -> [Word8] unpackByteArray ba | n == 0 = [] | otherwise = [ indexByteArray ba i | W# i <- [0 .. n-1] ] where n = lengthByteArray ba freezeByteArray :: MutableByteArray# RealWorld -> IO BA freezeByteArray arr = IO $ \s -> case unsafeFreezeByteArray# arr s of (# s, arr #) -> (# s, BA arr #) ---------------------------------------------------------------------------- main :: IO () main = do -- import/export primitives print $ [ W# (I.integerSizeInBase# 2## x) | x <- [b1024,b*e,b,e,m,x,y,-1,0,1] ] print $ [ W# (I.integerSizeInBase# 256## x) | x <- [b1024,b*e,b,e,m,x,y,-1,0,1] ] BA ba <- do MBA mba <- newByteArray 128## forM_ (zip [0..127] [0x01..]) $ \(I# i, w) -> do writeByteArray mba i w let a = byteArrayContents# (unsafeCoerce# mba) print =<< importIntegerAddr a 0## 1# print =<< importIntegerAddr a 0## 0# print =<< importIntegerAddr (plusAddr# a 22#) 1## 1# print =<< importIntegerAddr (plusAddr# a 97#) 1## 0# print =<< importIntegerAddr a 23## 1# print =<< importIntegerAddr a 23## 0# -- no-op print =<< exportIntegerAddr 0 (plusAddr# a 0#) 1# -- write into array print =<< exportIntegerAddr b (plusAddr# a 5#) 1# print =<< exportIntegerAddr e (plusAddr# a 50#) 0# print =<< exportInteger m mba 85## 1# print =<< exportInteger m mba 105## 0# print =<< importIntegerAddr (plusAddr# a 85#) 17## 1# print =<< importIntegerAddr (plusAddr# a 105#) 17## 0# -- read back full array print =<< importIntegerAddr a 128## 1# print =<< importIntegerAddr a 128## 0# freezeByteArray mba print $ importInteger ba 0## 0## 1# print $ importInteger ba 0## 0## 0# print $ importInteger ba 5## 29## 1# print $ importInteger ba 50## 29## 0# print $ importInteger ba 0## 128## 1# print $ importInteger ba 0## 128## 0# return () where b = 2988348162058574136915891421498819466320163312926952423791023078876139 e = 2351399303373464486466122544523690094744975233415544072992656881240319 m = 10^(40::Int) x = 5328841272400314897981163497728751426 y = 32052182750761975518649228050096851724 b1024 = roll (map fromIntegral (take 128 [0x80::Int .. ])) roll :: [Word8] -> Integer roll = GHC.Base.foldr (\b a -> a `shiftL` 8 .|. fromIntegral b) 0