Skip to content

Instantly share code, notes, and snippets.

@andrewthad
Created December 21, 2016 15:55
Show Gist options
  • Save andrewthad/87abd7a9b6f27c51165f33f16e85123f to your computer and use it in GitHub Desktop.
Save andrewthad/87abd7a9b6f27c51165f33f16e85123f to your computer and use it in GitHub Desktop.
Bit twiddling for fast decimal conversion
{-# LANGUAGE MagicHash #-}
import Data.Bits
import GHC.Prim
import GHC.Word
import Text.Printf
import Data.Char (ord)
hasBetween# :: Word# -> Word# -> Word# -> Word#
hasBetween# x m n =
and#
( minusWord#
( timesWord# alternating (plusWord# 127## n) )
( and# x ( timesWord# alternating 127## ) )
)
( and# (not# x)
( and#
( plusWord#
( and# x (timesWord# alternating 127## ) )
( timesWord# alternating (minusWord# 127## m) )
)
( timesWord# alternating 128## )
)
)
where
alternating :: Word#
alternating = quotWord# (not# 0##) 255##
hasLess# :: Word# -> Word# -> Word#
hasLess# x n =
and#
(minusWord# x (timesWord# alternating n))
(and#
(not# x)
(timesWord# alternating 128##)
)
where
alternating :: Word#
alternating = quotWord# (not# 0##) 255##
-- ((~0UL/255*(127+(n))-((x)&~0UL/255*127)&~(x)&((x)&~0UL/255*127)+~0UL/255*(127-(m)))&~0UL/255*128)
-- hasless(x,n) (((x)-~0UL/255*(n))&~(x)&~0UL/255*128)
hasBetween :: Word -> Word -> Word -> Word
hasBetween (W# a) (W# b) (W# c) = W# (hasBetween# a b c)
hasLess :: Word -> Word -> Word
hasLess (W# a) (W# b) = W# (hasLess# a b)
c2w :: Char -> Word
c2w = fromIntegral . ord
stringToWord :: Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Word
stringToWord a b c d e f g h =
shiftL (c2w a) 56
.|. shiftL (c2w b) 48
.|. shiftL (c2w c) 40
.|. shiftL (c2w d) 32
.|. shiftL (c2w e) 24
.|. shiftL (c2w f) 16
.|. shiftL (c2w g) 8
.|. shiftL (c2w h) 0
main :: IO ()
main = do
let w = stringToWord 'a' '0' 'X' '9' 'p' 'B' 'N' 'r'
printf "%064b\n" w
printf "%064b\n" (hasLess w 58)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment