Created
December 21, 2016 15:55
-
-
Save andrewthad/87abd7a9b6f27c51165f33f16e85123f to your computer and use it in GitHub Desktop.
Bit twiddling for fast decimal conversion
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{-# 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