ppad-fixed-0.1.3: 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 !Limb4 

Instances

Instances details
Num Wider Source #

Note that fromInteger necessarily runs in variable time due to conversion from the variable-size, potentially heap-allocated Integer type.

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 -> () #

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_vartime :: Integer -> Wider Source #

Convert an Integer to a Wider word.

>>> to_vartime 1
1

from_vartime :: Wider -> Integer Source #

Convert a Wider word to an Integer.

>>> from_vartime 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_vartime :: Wider -> Wider -> Ordering Source #

Variable-time comparison between Wider words.

The actual comparison here is performed in constant time, but we must branch to return an Ordering.

>>> cmp_vartime 1 2
LT
>>> cmp_vartime 2 1
GT
>>> cmp_vartime 2 2
EQ

lt :: Wider -> Wider -> Choice Source #

Constant-time less-than comparison between Wider values.

>>> import qualified Data.Choice as CT
>>> CT.decide (lt 1 2)
True
>>> CT.decide (lt 1 1)
False

gt :: Wider -> Wider -> Choice Source #

Constant-time greater-than comparison between Wider values.

>>> import qualified Data.Choice as CT
>>> CT.decide (gt 1 2)
False
>>> CT.decide (gt 2 1)
True

Parity

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

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

and Source #

Arguments

:: Wider

a

-> Wider

b

-> Wider

a & b

Binary and.

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

or Source #

Arguments

:: Wider

a

-> Wider

b

-> Wider

a | b

Binary or.

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

xor Source #

Arguments

:: Wider

a

-> Wider

b

-> Wider

a ^ b

Binary xor.

>>> xor 1 1
0
>>> xor 1 0
1

not Source #

Arguments

:: Wider

value

-> Wider

not value

Binary not.

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

Arithmetic

add_o Source #

Arguments

:: Wider

augend

-> Wider

addend

-> (Wider, Word)

(sum, carry bit)

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 :: 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_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

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_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_c# Source #

Arguments

:: Limb4

minuend

-> Limb

carry bit

-> Limb4

subtrahend

-> Limb4

modulus

-> Limb4

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)

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

Widening square.

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