ppad-fixed-0.1.0: Large fixed-width words and constant-time arithmetic.
Copyright(c) 2025 Jared Tobin
LicenseMIT
MaintainerJared Tobin <jared@ppad.tech>
Safe HaskellNone
LanguageHaskell2010

Data.Word.Wider

Description

Wider words, consisting of four Limbs.

Synopsis

Four-limb words

data Wider Source #

Little-endian wider words, consisting of four Limbs.

>>> 1 :: Wider
1

Constructors

Wider !(# Limb, Limb, Limb, Limb #) 

Instances

Instances details
Num Wider Source # 
Instance details

Defined in Data.Word.Wider

Show Wider Source # 
Instance details

Defined in Data.Word.Wider

Methods

showsPrec :: Int -> Wider -> ShowS #

show :: Wider -> String #

showList :: [Wider] -> ShowS #

NFData Wider Source # 
Instance details

Defined in Data.Word.Wider

Methods

rnf :: Wider -> () #

Eq Wider Source # 
Instance details

Defined in Data.Word.Wider

Methods

(==) :: Wider -> Wider -> Bool #

(/=) :: Wider -> Wider -> Bool #

Ord Wider Source # 
Instance details

Defined in Data.Word.Wider

Methods

compare :: Wider -> Wider -> Ordering #

(<) :: Wider -> Wider -> Bool #

(<=) :: Wider -> Wider -> Bool #

(>) :: Wider -> Wider -> Bool #

(>=) :: Wider -> Wider -> Bool #

max :: Wider -> Wider -> Wider #

min :: Wider -> Wider -> Wider #

wider :: Word -> Word -> Word -> Word -> Wider Source #

Construct a Wider word from four Words, provided in little-endian order.

>>> wider 1 0 0 0
1

to :: Integer -> Wider Source #

Convert an Integer to a Wider word.

>>> to 1
1

from :: Wider -> Integer Source #

Convert a Wider word to an Integer.

>>> from 1
1

Comparison

eq_vartime :: Wider -> Wider -> Bool Source #

Compare Wider words for equality in variable time.

>>> eq_vartime 1 0
False
>>> eq_vartime 1 1
True

cmp :: Wider -> Wider -> Ordering Source #

Constant-time comparison between Wider words.

>>> cmp 1 2
LT
>>> cmp 2 1
GT
>>> cmp 2 2
EQ

cmp# :: (# Limb, Limb, Limb, Limb #) -> (# Limb, Limb, Limb, Limb #) -> Int# Source #

eq# :: (# Limb, Limb, Limb, Limb #) -> (# Limb, Limb, Limb, Limb #) -> Choice Source #

lt# :: (# Limb, Limb, Limb, Limb #) -> (# Limb, Limb, Limb, Limb #) -> Choice Source #

gt# :: (# Limb, Limb, Limb, Limb #) -> (# Limb, Limb, Limb, Limb #) -> Choice Source #

Parity

odd# :: (# Limb, Limb, Limb, Limb #) -> Choice Source #

odd :: Wider -> Choice Source #

Check if a Wider is odd, returning a Choice.

Constant-time selection

select Source #

Arguments

:: Wider

a

-> Wider

b

-> Choice

c

-> Wider

result

Return a if c is truthy, otherwise return b.

>>> import qualified Data.Choice as C
>>> select 0 1 (C.true# ())
1

select# Source #

Arguments

:: (# Limb, Limb, Limb, Limb #)

a

-> (# Limb, Limb, Limb, Limb #)

b

-> Choice

c

-> (# Limb, Limb, Limb, Limb #)

result

Bit manipulation

shl1 :: Wider -> Wider Source #

Constant-time 1-bit shift-left.

>>> shl1 1
2
>>> shl1 (2 ^ (255 :: Word))
0

shr1 :: Wider -> Wider Source #

Constant-time 1-bit shift-right.

>>> shr1 2
1
>>> shr1 1
0

shl1_c :: Wider -> (# Wider, Choice #) Source #

Constant-time 1-bit shift-left with carry, with a Choice indicating whether the highest bit was set.

shr1_c :: Wider -> (# Wider, Choice #) Source #

Constant-time 1-bit shift-right with carry, with a Choice indicating whether the lowest bit was set.

shr_limb Source #

Arguments

:: Wider

value

-> Int

right-shift amount (0 < s < WORD_SIZE)

-> Wider

right-shifted value

Shift right by less than the number of bits in a Limb (e.g., by a maximum of 63 bits on 64-bit architectures). The shift amount is unchecked.

>>> shr_limb 2 1
1

shl_limb Source #

Arguments

:: Wider

value

-> Int

left-shift amount (0 < s < WORD_SIZE)

-> Wider

left-shifted value

Shift left by less than the number of bits in a Limb (e.g., by a maximum of 63 bits on 64-bit architectures). The shift amount is unchecked.

>>> shl_limb 2 1
1
>>> shl_limb 1 63
9223372036854775808

shl1_c# Source #

Arguments

:: (# Limb, Limb, Limb, Limb #)

argument

-> (# (# Limb, Limb, Limb, Limb #), Choice #)

result, carry

shr1_c# Source #

Arguments

:: (# Limb, Limb, Limb, Limb #)

argument

-> (# (# Limb, Limb, Limb, Limb #), Choice #)

result, carry

shr_limb# :: (# Limb, Limb, Limb, Limb #) -> Int# -> (# (# Limb, Limb, Limb, Limb #), Limb #) Source #

shl_limb# :: (# Limb, Limb, Limb, Limb #) -> Int# -> (# (# Limb, Limb, Limb, Limb #), Limb #) Source #

and Source #

Arguments

:: Wider

a

-> Wider

b

-> Wider

a & b

Binary and.

>>> and 1 1
1
>>> and 1 0
0

and_w# :: (# Limb, Limb, Limb, Limb #) -> (# Limb, Limb, Limb, Limb #) -> (# Limb, Limb, Limb, Limb #) Source #

or Source #

Arguments

:: Wider

a

-> Wider

b

-> Wider

a | b

Binary or.

>>> or 1 1
1
>>> or 1 0
1

or_w# :: (# Limb, Limb, Limb, Limb #) -> (# Limb, Limb, Limb, Limb #) -> (# Limb, Limb, Limb, Limb #) Source #

not Source #

Arguments

:: Wider

value

-> Wider

not value

Binary not.

>>> not 0
115792089237316195423570985008687907853269984665640564039457584007913129639935
>>> not (not 0)
0

not# :: (# Limb, Limb, Limb, Limb #) -> (# Limb, Limb, Limb, Limb #) Source #

Arithmetic

add_o :: Wider -> Wider -> (Wider, Word) Source #

Overflowing addition, computing 'a + b', returning the sum and a carry bit.

>>> add_o 1 1
(2,0)
>>> add_o 1 (2 ^ (256 :: Word) - 1)
(0,1)

add_o# Source #

Arguments

:: (# Limb, Limb, Limb, Limb #)

augend

-> (# Limb, Limb, Limb, Limb #)

addend

-> (# (# Limb, Limb, Limb, Limb #), Limb #)

(# sum, carry bit #)

add :: Wider -> Wider -> Wider Source #

Wrapping addition, computing 'a + b'.

Note that as Wider is an instance of Num, you can use + to apply this function.

>>> add 1 (2 ^ (256 :: Word) - 1)
0

add_w# Source #

Arguments

:: (# Limb, Limb, Limb, Limb #)

augend

-> (# Limb, Limb, Limb, Limb #)

addend

-> (# Limb, Limb, Limb, Limb #)

sum

add_mod Source #

Arguments

:: Wider

augend

-> Wider

addend

-> Wider

modulus

-> Wider

sum

Modular addition.

Assumes that the sum is less than twice the modulus; this is not checked.

>>> add_mod 1 1 3
2
>>> add_mod 1 2 3
0

add_mod# Source #

Arguments

:: (# Limb, Limb, Limb, Limb #)

augend

-> (# Limb, Limb, Limb, Limb #)

addend

-> (# Limb, Limb, Limb, Limb #)

modulus

-> (# Limb, Limb, Limb, Limb #)

sum

sub Source #

Arguments

:: Wider

minuend

-> Wider

subtrahend

-> Wider

difference

Wrapping subtraction, computing 'a - b' and returning the difference.

Note that as Wider is an instance of Num, you can use - to apply this function.

>>> sub 1 1
0
>>> sub 0 (2 ^ (256 :: Word) - 1)
1

sub_b Source #

Arguments

:: Wider

minuend

-> Wider

subtrahend

-> (Wider, Word)

(difference, borrow mask)

Borrowing subtraction, computing 'a - b' and returning the difference with a borrow mask.

>>> sub_b 1 1
(0,0)
>>> sub_b 0 (2 ^ (256 :: Word) - 1)
(1,18446744073709551615)

sub_b# Source #

Arguments

:: (# Limb, Limb, Limb, Limb #)

minuend

-> (# Limb, Limb, Limb, Limb #)

subtrahend

-> (# (# Limb, Limb, Limb, Limb #), Limb #)

(# diff, borrow mask #)

sub_mod :: Wider -> Wider -> Wider -> Wider Source #

Modular subtraction. Computes a - b mod m.

Assumes that the magnitude of the difference is less than the modulus (this is unchecked).

>>> sub_mod 1 1 4
0
>>> sub_mod 2 3 4
3

sub_mod# Source #

Arguments

:: (# Limb, Limb, Limb, Limb #)

minuend

-> (# Limb, Limb, Limb, Limb #)

subtrahend

-> (# Limb, Limb, Limb, Limb #)

modulus

-> (# Limb, Limb, Limb, Limb #)

difference

sub_mod_c# Source #

Arguments

:: (# Limb, Limb, Limb, Limb #)

minuend

-> Limb

carry bit

-> (# Limb, Limb, Limb, Limb #)

subtrahend

-> (# Limb, Limb, Limb, Limb #)

modulus

-> (# Limb, Limb, Limb, Limb #)

difference

Modular subtraction with carry. Computes (# a, c #) - b mod m.

mul :: Wider -> Wider -> Wider Source #

Wrapping multiplication.

Note that as Wider is an instance of Num, you can use * to apply this function.

>>> mul 1 1
1
>>> mul 1 2
2

mul_c :: Wider -> Wider -> (Wider, Wider) Source #

Widening multiplication.

Returns the low and high Wider words of the product, in that order.

>>> mul_c 2 3
(6,0)
>>> mul_c (2 ^ (256 :: Word) - 1)  2
(115792089237316195423570985008687907853269984665640564039457584007913129639934,1)

mul_c# :: (# Limb, Limb, Limb, Limb #) -> (# Limb, Limb, Limb, Limb #) -> (# (# Limb, Limb, Limb, Limb #), (# Limb, Limb, Limb, Limb #) #) Source #

sqr :: Wider -> (Wider, Wider) Source #

Widening square.

>>> sqr 2
(4,0)
>>> sqr (2 ^ (256 :: Word) - 1)
(1,115792089237316195423570985008687907853269984665640564039457584007913129639934)

sqr# :: (# Limb, Limb, Limb, Limb #) -> (# (# Limb, Limb, Limb, Limb #), (# Limb, Limb, Limb, Limb #) #) Source #