{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE NumericUnderscores #-}
{-# LANGUAGE UnboxedSums #-}
{-# LANGUAGE UnboxedTuples #-}
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE UnliftedNewtypes #-}
module Data.Word.Limb (
Limb(..)
, render
, and#
, or#
, not#
, xor#
, bits#
, shl#
, shl1#
, shr#
, shr1#
, eq#
, ne#
, eq_vartime#
, ne_vartime#
, nonzero#
, lt#
, gt#
, select#
, cswap#
, neg#
, add_o#
, add_c#
, add_w#
, add_s#
, sub_b#
, sub_w#
, sub_s#
, mul_c#
, mul_w#
, mul_s#
, mac#
) where
import qualified Data.Bits as B
import qualified Data.Choice as C
import GHC.Exts (Word#)
import qualified GHC.Exts as Exts
newtype Limb = Limb Word#
render :: Limb -> String
render :: Limb -> String
render (Limb Word#
a) = Word -> String
forall a. Show a => a -> String
show (Word# -> Word
Exts.W# Word#
a)
eq#
:: Limb
-> Limb
-> C.Choice
eq# :: Limb -> Limb -> Choice
eq# (Limb Word#
a) (Limb Word#
b) = Word# -> Word# -> Choice
C.eq_word# Word#
a Word#
b
{-# INLINE eq# #-}
eq_vartime#
:: Limb
-> Limb
-> Bool
eq_vartime# :: Limb -> Limb -> Bool
eq_vartime# (Limb Word#
a) (Limb Word#
b) = Int# -> Bool
Exts.isTrue# (Word# -> Word# -> Int#
Exts.eqWord# Word#
a Word#
b)
{-# INLINE eq_vartime# #-}
ne#
:: Limb
-> Limb
-> C.Choice
ne# :: Limb -> Limb -> Choice
ne# Limb
a Limb
b = Choice -> Choice
C.not# (Limb -> Limb -> Choice
eq# Limb
a Limb
b)
{-# INLINE ne# #-}
ne_vartime#
:: Limb
-> Limb
-> Bool
ne_vartime# :: Limb -> Limb -> Bool
ne_vartime# Limb
a Limb
b = Bool -> Bool
not (Limb -> Limb -> Bool
eq_vartime# Limb
a Limb
b)
{-# INLINE ne_vartime# #-}
nonzero#
:: Limb
-> C.Choice
nonzero# :: Limb -> Choice
nonzero# (Limb Word#
a) = Word# -> Choice
C.from_word_nonzero# Word#
a
{-# INLINE nonzero# #-}
lt#
:: Limb
-> Limb
-> C.Choice
lt# :: Limb -> Limb -> Choice
lt# (Limb Word#
a) (Limb Word#
b) = Word# -> Word# -> Choice
C.from_word_lt# Word#
a Word#
b
{-# INLINE lt# #-}
gt#
:: Limb
-> Limb
-> C.Choice
gt# :: Limb -> Limb -> Choice
gt# (Limb Word#
a) (Limb Word#
b) = Word# -> Word# -> Choice
C.from_word_gt# Word#
a Word#
b
{-# INLINE gt# #-}
select#
:: Limb
-> Limb
-> C.Choice
-> Limb
select# :: Limb -> Limb -> Choice -> Limb
select# (Limb Word#
a) (Limb Word#
b) Choice
c = Word# -> Limb
Limb (Word# -> Word# -> Choice -> Word#
C.select_word# Word#
a Word#
b Choice
c)
{-# INLINE select# #-}
cswap#
:: Limb
-> Limb
-> C.Choice
-> (# Limb, Limb #)
cswap# :: Limb -> Limb -> Choice -> (# Limb, Limb #)
cswap# (Limb Word#
a) (Limb Word#
b) Choice
c =
let !l :: Word#
l = Word# -> Word# -> Choice -> Word#
C.select_word# Word#
a Word#
b Choice
c
!r :: Word#
r = Word# -> Word# -> Choice -> Word#
C.select_word# Word#
b Word#
a Choice
c
in (# Word# -> Limb
Limb Word#
l, Word# -> Limb
Limb Word#
r #)
{-# INLINE cswap# #-}
and#
:: Limb
-> Limb
-> Limb
and# :: Limb -> Limb -> Limb
and# (Limb Word#
a) (Limb Word#
b) = Word# -> Limb
Limb (Word# -> Word# -> Word#
Exts.and# Word#
a Word#
b)
{-# INLINE and# #-}
or#
:: Limb
-> Limb
-> Limb
or# :: Limb -> Limb -> Limb
or# (Limb Word#
a) (Limb Word#
b) = Word# -> Limb
Limb (Word# -> Word# -> Word#
Exts.or# Word#
a Word#
b)
{-# INLINE or# #-}
not#
:: Limb
-> Limb
not# :: Limb -> Limb
not# (Limb Word#
a) = Word# -> Limb
Limb (Word# -> Word#
Exts.not# Word#
a)
{-# INLINE not# #-}
xor#
:: Limb
-> Limb
-> Limb
xor# :: Limb -> Limb -> Limb
xor# (Limb Word#
a) (Limb Word#
b) = Word# -> Limb
Limb (Word# -> Word# -> Word#
Exts.xor# Word#
a Word#
b)
{-# INLINE xor# #-}
bits#
:: Limb
-> Int
bits# :: Limb -> Int
bits# (Limb Word#
a) =
let !_BITS :: Int
_BITS = Word -> Int
forall b. FiniteBits b => b -> Int
B.finiteBitSize (Word
0 :: Word)
!zs :: Int
zs = Word -> Int
forall b. FiniteBits b => b -> Int
B.countLeadingZeros (Word# -> Word
Exts.W# Word#
a)
in Int
_BITS Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
zs
{-# INLINE bits# #-}
shl#
:: Limb
-> Exts.Int#
-> Limb
shl# :: Limb -> Int# -> Limb
shl# (Limb Word#
w) Int#
s = Word# -> Limb
Limb (Word# -> Int# -> Word#
Exts.uncheckedShiftL# Word#
w Int#
s)
{-# INLINE shl# #-}
shl1#
:: Limb
-> (# Limb, Limb #)
shl1# :: Limb -> (# Limb, Limb #)
shl1# (Limb Word#
w) =
let !s :: Int#
s = case Word -> Int
forall b. FiniteBits b => b -> Int
B.finiteBitSize (Word
0 :: Word) of Exts.I# Int#
m -> Int#
m Int# -> Int# -> Int#
Exts.-# Int#
1#
!r :: Word#
r = Word# -> Int# -> Word#
Exts.uncheckedShiftL# Word#
w Int#
1#
!c :: Word#
c = Word# -> Int# -> Word#
Exts.uncheckedShiftRL# Word#
w Int#
s
in (# Word# -> Limb
Limb Word#
r, Word# -> Limb
Limb Word#
c #)
{-# INLINE shl1# #-}
shr#
:: Limb
-> Exts.Int#
-> Limb
shr# :: Limb -> Int# -> Limb
shr# (Limb Word#
w) Int#
s = Word# -> Limb
Limb (Word# -> Int# -> Word#
Exts.uncheckedShiftRL# Word#
w Int#
s)
{-# INLINE shr# #-}
shr1#
:: Limb
-> (# Limb, Limb #)
shr1# :: Limb -> (# Limb, Limb #)
shr1# (Limb Word#
w) =
let !s :: Int#
s = case Word -> Int
forall b. FiniteBits b => b -> Int
B.finiteBitSize (Word
0 :: Word) of Exts.I# Int#
m -> Int#
m Int# -> Int# -> Int#
Exts.-# Int#
1#
!r :: Word#
r = Word# -> Int# -> Word#
Exts.uncheckedShiftRL# Word#
w Int#
1#
!c :: Word#
c = Word# -> Int# -> Word#
Exts.uncheckedShiftL# Word#
w Int#
s
in (# Word# -> Limb
Limb Word#
r, Word# -> Limb
Limb Word#
c #)
{-# INLINE shr1# #-}
neg#
:: Limb
-> Limb
neg# :: Limb -> Limb
neg# (Limb Word#
x) = Word# -> Limb
Limb (Word# -> Word# -> Word#
Exts.plusWord# (Word# -> Word#
Exts.not# Word#
x) Word#
1##)
{-# INLINE neg# #-}
add_o#
:: Limb
-> Limb
-> (# Limb, Limb #)
add_o# :: Limb -> Limb -> (# Limb, Limb #)
add_o# (Limb Word#
a) (Limb Word#
b) = case Word# -> Word# -> (# Word#, Word# #)
Exts.plusWord2# Word#
a Word#
b of
(# Word#
c, Word#
s #) -> (# Word# -> Limb
Limb Word#
s, Word# -> Limb
Limb Word#
c #)
{-# INLINE add_o# #-}
add_c#
:: Limb
-> Limb
-> Limb
-> (# Limb, Limb #)
add_c# :: Limb -> Limb -> Limb -> (# Limb, Limb #)
add_c# (Limb Word#
a) (Limb Word#
b) (Limb Word#
c) =
let !(# Word#
c0, Word#
s0 #) = Word# -> Word# -> (# Word#, Word# #)
Exts.plusWord2# Word#
a Word#
b
!(# Word#
c1, Word#
s #) = Word# -> Word# -> (# Word#, Word# #)
Exts.plusWord2# Word#
s0 Word#
c
in (# Word# -> Limb
Limb Word#
s, Word# -> Limb
Limb (Word# -> Word# -> Word#
Exts.or# Word#
c0 Word#
c1) #)
{-# INLINE add_c# #-}
add_w#
:: Limb
-> Limb
-> Limb
add_w# :: Limb -> Limb -> Limb
add_w# (Limb Word#
a) (Limb Word#
b) = Word# -> Limb
Limb (Word# -> Word# -> Word#
Exts.plusWord# Word#
a Word#
b)
{-# INLINE add_w# #-}
add_s#
:: Limb
-> Limb
-> Limb
add_s# :: Limb -> Limb -> Limb
add_s# (Limb Word#
a) (Limb Word#
b) = case Word# -> Word# -> (# Word#, Int# #)
Exts.addWordC# Word#
a Word#
b of
(# Word#
s, Int#
0# #) -> Word# -> Limb
Limb Word#
s
(# Word#, Int# #)
_ -> case Word
forall a. Bounded a => a
maxBound :: Word of
Exts.W# Word#
m -> Word# -> Limb
Limb Word#
m
{-# INLINE add_s# #-}
sub_b#
:: Limb
-> Limb
-> Limb
-> (# Limb, Limb #)
sub_b# :: Limb -> Limb -> Limb -> (# Limb, Limb #)
sub_b# (Limb Word#
m) (Limb Word#
n) (Limb Word#
a) =
let !s :: Int#
s = case Word -> Int
forall b. FiniteBits b => b -> Int
B.finiteBitSize (Word
0 :: Word) of Exts.I# Int#
bs -> Int#
bs Int# -> Int# -> Int#
Exts.-# Int#
1#
!b :: Word#
b = Word# -> Int# -> Word#
Exts.uncheckedShiftRL# Word#
a Int#
s
!(# Word#
d0, Int#
b0 #) = Word# -> Word# -> (# Word#, Int# #)
Exts.subWordC# Word#
m Word#
n
!(# Word#
d, Int#
b1 #) = Word# -> Word# -> (# Word#, Int# #)
Exts.subWordC# Word#
d0 Word#
b
!c :: Word#
c = Int# -> Word#
Exts.int2Word# (Int# -> Int#
Exts.negateInt# (Int# -> Int# -> Int#
Exts.orI# Int#
b0 Int#
b1))
in (# Word# -> Limb
Limb Word#
d, Word# -> Limb
Limb Word#
c #)
{-# INLINE sub_b# #-}
sub_s#
:: Limb
-> Limb
-> Limb
sub_s# :: Limb -> Limb -> Limb
sub_s# (Limb Word#
m) (Limb Word#
n) = case Word# -> Word# -> (# Word#, Int# #)
Exts.subWordC# Word#
m Word#
n of
(# Word#
d, Int#
0# #) -> Word# -> Limb
Limb Word#
d
(# Word#, Int# #)
_ -> Word# -> Limb
Limb Word#
0##
{-# INLINE sub_s# #-}
sub_w#
:: Limb
-> Limb
-> Limb
sub_w# :: Limb -> Limb -> Limb
sub_w# (Limb Word#
m) (Limb Word#
n) = Word# -> Limb
Limb (Word# -> Word# -> Word#
Exts.minusWord# Word#
m Word#
n)
{-# INLINE sub_w# #-}
mul_c#
:: Limb
-> Limb
-> (# Limb, Limb #)
mul_c# :: Limb -> Limb -> (# Limb, Limb #)
mul_c# (Limb Word#
a) (Limb Word#
b) =
let !(# Word#
h, Word#
l #) = Word# -> Word# -> (# Word#, Word# #)
Exts.timesWord2# Word#
a Word#
b
in (# Word# -> Limb
Limb Word#
l, Word# -> Limb
Limb Word#
h #)
{-# INLINE mul_c# #-}
mul_w#
:: Limb
-> Limb
-> Limb
mul_w# :: Limb -> Limb -> Limb
mul_w# (Limb Word#
a) (Limb Word#
b) = Word# -> Limb
Limb (Word# -> Word# -> Word#
Exts.timesWord# Word#
a Word#
b)
{-# INLINE mul_w# #-}
mul_s#
:: Limb
-> Limb
-> Limb
mul_s# :: Limb -> Limb -> Limb
mul_s# (Limb Word#
a) (Limb Word#
b) = case Word# -> Word# -> (# Word#, Word# #)
Exts.timesWord2# Word#
a Word#
b of
(# Word#
0##, Word#
l #) -> Word# -> Limb
Limb Word#
l
(# Word#, Word# #)
_ -> Word# -> Limb
Limb (Word# -> Word#
Exts.not# Word#
0##)
{-# INLINE mul_s# #-}
mac#
:: Limb
-> Limb
-> Limb
-> Limb
-> (# Limb, Limb #)
mac# :: Limb -> Limb -> Limb -> Limb -> (# Limb, Limb #)
mac# (Limb Word#
a) (Limb Word#
b) (Limb Word#
m) (Limb Word#
c) =
let !(# Word#
h, Word#
l #) = Word# -> Word# -> (# Word#, Word# #)
Exts.timesWord2# Word#
a Word#
b
!(# Word#
l_0, Word#
h_0 #) = (# Word#, Word# #) -> Word# -> (# Word#, Word# #)
wadd_w# (# Word#
l, Word#
h #) Word#
m
!(# Word#
d, Word#
l_1 #) = Word# -> Word# -> (# Word#, Word# #)
Exts.plusWord2# Word#
l_0 Word#
c
!h_1 :: Word#
h_1 = Word# -> Word# -> Word#
Exts.plusWord# Word#
h_0 Word#
d
in (# Word# -> Limb
Limb Word#
l_1, Word# -> Limb
Limb Word#
h_1 #)
where
wadd_w# :: (# Word#, Word# #) -> Word# -> (# Word#, Word# #)
wadd_w# :: (# Word#, Word# #) -> Word# -> (# Word#, Word# #)
wadd_w# (# Word#
x_lo, Word#
x_hi #) Word#
y_lo =
let !(# Word#
c0, Word#
s0 #) = Word# -> Word# -> (# Word#, Word# #)
Exts.plusWord2# Word#
x_lo Word#
y_lo
!(# Word#
_, Word#
s1 #) = Word# -> Word# -> (# Word#, Word# #)
Exts.plusWord2# Word#
x_hi Word#
c0
in (# Word#
s0, Word#
s1 #)
{-# INLINE wadd_w# #-}
{-# INLINE mac# #-}