module Data.Repa.Scalar.Int
(
readInt
, readIntFromByteString
, loadInt
, loadInt#
, loadIntWith#
, showInt
, showIntToByteString
, showIntPad
, showIntPadToByteString
, storeInt
, storeInt#
, storeIntWith#
, storeIntPad
, storeIntPad#
, storeIntPadWith#)
where
import Data.Word
import Data.Char
import GHC.Exts
import qualified Data.ByteString.Char8 as BS
import qualified Data.ByteString.Internal as BS
import qualified Foreign.Ptr as F
import qualified Foreign.ForeignPtr as F
import qualified Foreign.Storable as F
import qualified Foreign.Marshal.Alloc as F
import System.IO.Unsafe
readInt :: String -> Maybe Int
readInt str
= readIntFromByteString $ BS.pack str
{-# INLINE readInt #-}
readIntFromByteString
:: BS.ByteString -> Maybe Int
readIntFromByteString (BS.PS fptr offset len)
= unsafePerformIO
$ F.withForeignPtr fptr
$ \ptr -> return
$ loadInt (F.plusPtr ptr offset) len
Nothing
(\val n -> if n == len
then Just val
else Nothing)
{-# INLINE readIntFromByteString #-}
loadInt :: Ptr Word8
-> Int
-> b
-> (Int -> Int -> b)
-> b
loadInt (Ptr addr) (I# len) fails eat
= case loadInt# addr len of
(# 0#, _, _ #) -> fails
(# _, n, ix #) -> eat (I# n) (I# ix)
{-# INLINE loadInt #-}
loadInt#
:: Addr#
-> Int#
-> (# Int#, Int#, Int# #)
loadInt# addr len
= let
buf :: Ptr Word8
= Ptr addr
peek8 ix
= case BS.accursedUnutterablePerformIO (F.peekByteOff buf (I# ix)) of
(w8 :: Word8) -> case fromIntegral w8 of
I# i -> i
{-# INLINE peek8 #-}
in loadIntWith# len peek8
{-# NOINLINE loadInt# #-}
loadIntWith#
:: Int#
-> (Int# -> Int#)
-> (# Int#, Int#, Int# #)
loadIntWith# !len get
= start 0#
where
start !ix
| 1# <- ix >=# len = (# 0#, 0#, 0# #)
| otherwise = sign ix
{-# INLINE start #-}
sign !ix
| !s <- get 0#
= case chr $ fromIntegral (I# s) of
'-' -> loop 1# (ix +# 1#) 0#
'+' -> loop 2# (ix +# 1#) 0#
_ -> loop 0# ix 0#
{-# INLINE sign #-}
loop !neg !ix !n
| 1# <- ix >=# len
= end neg ix n
| otherwise
= case get ix of
w | 1# <- w >=# 0x30#
, 1# <- w <=# 0x039#
-> loop neg ( ix +# 1#)
((n *# 10#) +# (w -# 0x30#))
| otherwise
-> end neg ix n
end !neg !ix !n
| 1# <- ix ==# 0#
, 1# <- neg ==# 0#
= (# 0#, 0#, 0# #)
| 1# <- ix ==# 1#
, 1# <- neg /=# 0#
= (# 0#, 0#, 0# #)
| 1# <- neg ==# 1#
, I# n' <- negate (I# n)
= (# 1#, n', ix #)
| otherwise
= (# 1#, n, ix #)
{-# NOINLINE end #-}
{-# INLINE loadIntWith# #-}
showInt :: Int -> String
showInt i
= BS.unpack $ showIntToByteString i
{-# INLINE showInt #-}
showIntToByteString :: Int -> BS.ByteString
showIntToByteString (I# i)
= unsafePerformIO
$ let
alloc len
= F.mallocBytes (I# len)
{-# INLINE alloc #-}
write ptr ix val
= F.pokeByteOff ptr (I# ix) (fromIntegral (I# val) :: Word8)
{-# INLINE write #-}
make ptr len
= do fptr <- F.newForeignPtr F.finalizerFree ptr
return $ BS.PS fptr 0 (I# len)
{-# INLINE make #-}
in storeIntWith# alloc write i make
{-# NOINLINE showIntToByteString #-}
storeInt :: Ptr Word8
-> Int
-> IO Int
storeInt (Ptr addr) (I# val)
= storeInt# addr val
{-# INLINE storeInt #-}
storeInt#
:: Addr#
-> Int#
-> IO Int
storeInt# addr val
= let
alloc _
= return $ Ptr addr
{-# INLINE alloc #-}
write _ ix byte
= F.pokeByteOff (Ptr addr) (I# ix) (fromIntegral (I# byte) :: Word8)
{-# INLINE write #-}
make _ len
= return $ I# len
{-# INLINE make #-}
in do
storeIntWith# alloc write val make
{-# NOINLINE storeInt# #-}
storeIntWith#
:: (Int# -> IO buf)
-> (buf -> Int# -> Int# -> IO ())
-> Int#
-> (buf -> Int# -> IO b)
-> IO b
storeIntWith# alloc write val k
= F.allocaBytes 32 $ \(buf :: Ptr Word8)
-> let
!start
| 1# <- val <# 0# = digits (0# -# val) 0#
| otherwise = digits val 0#
{-# INLINE start #-}
digits !mag !ix
= do F.pokeByteOff buf (I# ix)
(fromIntegral (I# (0x030# +# mag `remInt#` 10#)) :: Word8)
let !ix' = ix +# 1#
let !mag' = mag `quotInt#` 10#
(case mag' ==# 0# of
1# -> sign ix'
_ -> digits mag' ix')
{-# NOINLINE digits #-}
sign !ix
= case val <# 0# of
1# -> do F.pokeByteOff buf (I# ix)
(fromIntegral (I# 0x02d#) :: Word8)
create (ix +# 1#)
_ -> create ix
{-# INLINE sign #-}
create len
= do out <- alloc len
output len out 0#
{-# NOINLINE create #-}
output len out ix0
= go ix0
where go ix
| 1# <- ix <# len
= do x :: Word8 <- F.peekByteOff buf (I# ((len -# 1#) -# ix))
let !(I# i) = fromIntegral x
write out ix i
go (ix +# 1#)
| otherwise
= k out len
{-# INLINE output #-}
in start
{-# INLINE storeIntWith# #-}
showIntPad :: Int -> Int -> String
showIntPad i pad
= BS.unpack $ showIntPadToByteString i pad
{-# INLINE showIntPad #-}
showIntPadToByteString :: Int -> Int -> BS.ByteString
showIntPadToByteString (I# i) pad'
= unsafePerformIO
$ let
!(I# pad)
= max 0 pad'
alloc len
= F.mallocBytes (I# len)
{-# INLINE alloc #-}
write ptr ix val
= F.pokeByteOff ptr (I# ix) (fromIntegral (I# val) :: Word8)
{-# INLINE write #-}
make ptr len
= do fptr <- F.newForeignPtr F.finalizerFree ptr
return $ BS.PS fptr 0 (I# len)
{-# INLINE make #-}
in storeIntPadWith# alloc write i pad make
{-# NOINLINE showIntPadToByteString #-}
storeIntPad
:: Ptr Word8
-> Int
-> Int
-> IO Int
storeIntPad (Ptr addr) (I# val) (I# pad)
= storeIntPad# addr val pad
{-# INLINE storeIntPad #-}
storeIntPad#
:: Addr#
-> Int#
-> Int#
-> IO Int
storeIntPad# addr val pad
= let
alloc _
= return $ Ptr addr
{-# INLINE alloc #-}
write _ ix byte
= F.pokeByteOff (Ptr addr) (I# ix) (fromIntegral (I# byte) :: Word8)
{-# INLINE write #-}
make _ len
= return $ I# len
{-# INLINE make #-}
in do
storeIntPadWith# alloc write val pad make
{-# NOINLINE storeIntPad# #-}
storeIntPadWith#
:: (Int# -> IO buf)
-> (buf -> Int# -> Int# -> IO ())
-> Int#
-> Int#
-> (buf -> Int# -> IO b)
-> IO b
storeIntPadWith# alloc write val pad k
= F.allocaBytes (I# (32# +# pad)) $ \(buf :: Ptr Word8)
-> let
!start
| 1# <- val <# 0# = digits (0# -# val) 0#
| otherwise = digits val 0#
{-# INLINE start #-}
digits !mag !ix
= do F.pokeByteOff buf (I# ix)
(fromIntegral (I# (0x030# +# mag `remInt#` 10#)) :: Word8)
let !ix' = ix +# 1#
let !mag' = mag `quotInt#` 10#
(case mag' ==# 0# of
1# -> padder ix'
_ -> digits mag' ix')
{-# NOINLINE digits #-}
padder !ix
| 1# <- ix >=# pad
= sign ix
| otherwise
= do F.pokeByteOff buf (I# ix)
(fromIntegral (I# 0x030#) :: Word8)
padder (ix +# 1#)
sign !ix
= case val <# 0# of
1# -> do F.pokeByteOff buf (I# ix)
(fromIntegral (I# 0x02d#) :: Word8)
create (ix +# 1#)
_ -> create ix
{-# INLINE sign #-}
create len
= do out <- alloc len
output len out 0#
{-# NOINLINE create #-}
output len out ix0
= go ix0
where go ix
| 1# <- ix <# len
= do x :: Word8 <- F.peekByteOff buf (I# ((len -# 1#) -# ix))
let !(I# i) = fromIntegral x
write out ix i
go (ix +# 1#)
| otherwise
= k out len
{-# INLINE output #-}
in start
{-# INLINE storeIntPadWith# #-}