[internal] random little changes to keep faster toHex from cryptohash as compiled code for later use

This commit is contained in:
Vincent Hanquez 2015-05-06 11:39:46 +01:00
parent e89031c6d6
commit d18900c2e0
2 changed files with 56 additions and 2 deletions

View File

@ -14,21 +14,37 @@
{-# LANGUAGE CPP #-} {-# LANGUAGE CPP #-}
{-# LANGUAGE BangPatterns #-} {-# LANGUAGE BangPatterns #-}
{-# LANGUAGE MagicHash #-} {-# LANGUAGE MagicHash #-}
{-# LANGUAGE UnboxedTuples #-}
module Crypto.Internal.CompatPrim module Crypto.Internal.CompatPrim
( be32Prim ( be32Prim
, le32Prim
, byteswap32Prim , byteswap32Prim
, booleanPrim , booleanPrim
, convert4To32
) where ) where
import GHC.Prim import GHC.Prim
#ifdef ARCH_IS_LITTLE_ENDIAN -- | byteswap Word# to or from Big Endian
--
-- on a big endian machine, this function is a nop.
be32Prim :: Word# -> Word# be32Prim :: Word# -> Word#
#ifdef ARCH_IS_LITTLE_ENDIAN
be32Prim = byteswap32Prim be32Prim = byteswap32Prim
#else #else
be32Prim w = w be32Prim w = w
#endif #endif
-- | byteswap Word# to or from Little Endian
--
-- on a little endian machine, this function is a nop.
le32Prim :: Word# -> Word#
#ifdef ARCH_IS_LITTLE_ENDIAN
le32Prim w = w
#else
le32Prim = byteswap32Prim
#endif
byteswap32Prim :: Word# -> Word# byteswap32Prim :: Word# -> Word#
#if __GLASGOW_HASKELL__ >= 708 #if __GLASGOW_HASKELL__ >= 708
byteswap32Prim w = byteSwap32# w byteswap32Prim w = byteSwap32# w
@ -41,6 +57,22 @@ byteswap32Prim w =
in or# a (or# b (or# c d)) in or# a (or# b (or# c d))
#endif #endif
-- | combine 4 word8 [a,b,c,d] to a word32 representing [a,b,c,d]
convert4To32 :: (# Word#, Word#, Word#, Word# #) -> Word#
convert4To32 (# a, b, c, d #) = or# (or# c1 c2) (or# c3 c4)
where
#ifdef ARCH_IS_LITTLE_ENDIAN
!c1 = uncheckedShiftL# a 24#
!c2 = uncheckedShiftL# b 16#
!c3 = uncheckedShiftL# c 8#
!c4 = d
#else
!c1 = uncheckedShiftL# d 24#
!c2 = uncheckedShiftL# c 16#
!c3 = uncheckedShiftL# b 8#
!c4 = a
#endif
#if __GLASGOW_HASKELL__ >= 708 #if __GLASGOW_HASKELL__ >= 708
booleanPrim :: Int# -> Bool booleanPrim :: Int# -> Bool
booleanPrim v = tagToEnum# v booleanPrim v = tagToEnum# v

View File

@ -15,16 +15,18 @@
module Crypto.Internal.Hex module Crypto.Internal.Hex
( showHexadecimal ( showHexadecimal
, toHexadecimal , toHexadecimal
, toHexadecimal4
) where ) where
import Crypto.Internal.Compat import Crypto.Internal.Compat
import Crypto.Internal.CompatPrim
import Data.Word import Data.Word
import GHC.Prim import GHC.Prim
import GHC.Types import GHC.Types
import GHC.Word import GHC.Word
import Control.Monad import Control.Monad
import Foreign.Storable import Foreign.Storable
import Foreign.Ptr (Ptr) import Foreign.Ptr (Ptr, plusPtr)
showHexadecimal :: (forall a . (Ptr Word8 -> IO a) -> IO a) -> Int -> String showHexadecimal :: (forall a . (Ptr Word8 -> IO a) -> IO a) -> Int -> String
showHexadecimal withPtr = doChunks 0 showHexadecimal withPtr = doChunks 0
@ -70,6 +72,26 @@ toHexadecimal bout bin n = loop 0
pokeByteOff bout (i * 2 + 1) (W8# w2) pokeByteOff bout (i * 2 + 1) (W8# w2)
loop (i+1) loop (i+1)
-- | convert to hexadecimal going 2 by 2
--
-- experimental. untested
toHexadecimal4 :: Ptr Word32 -> Ptr Word8 -> Int -> IO ()
toHexadecimal4 bout bin n = loop 0
where loop i
| i == n = return ()
| otherwise = do
(W8# w1) <- peekByteOff bin i
(W8# w2) <- peekByteOff bin (i+1)
let r = W32# (convertByte4 w1 w2)
poke (bout `plusPtr` (i * 2)) r
loop (i+2)
convertByte4 :: Word# -> Word# -> Word#
convertByte4 a b = convert4To32 (# b2, b1, a2, a1 #)
where
!(# a1, a2 #) = convertByte a
!(# b1, b2 #) = convertByte b
convertByte :: Word# -> (# Word#, Word# #) convertByte :: Word# -> (# Word#, Word# #)
convertByte b = (# r tableHi b, r tableLo b #) convertByte b = (# r tableHi b, r tableLo b #)
where where