Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 1 addition & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ edition = "2024"
rust-version = "1.85"

[dependencies]
ctutils = { version = "0.1.1", features = ["subtle"] }
ctutils = { version = "0.1.2", features = ["subtle"] }
subtle = { version = "2.6", default-features = false }

# optional dependencies
Expand Down Expand Up @@ -86,6 +86,3 @@ harness = false

[profile.dev]
opt-level = 2

[patch.crates-io.ctutils]
git = "https://github.com/RustCrypto/utils"
104 changes: 57 additions & 47 deletions src/word.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,70 @@ use crate::ConstChoice;
#[cfg(not(any(target_pointer_width = "32", target_pointer_width = "64")))]
compile_error!("this crate builds on 32-bit and 64-bit platforms only");

//
// 32-bit definitions
//

/// Inner integer type that the [`Limb`] newtype wraps.
/// 32-bit definitions
#[cfg(target_pointer_width = "32")]
pub type Word = u32;
mod word32 {
use crate::ConstChoice;

/// Unsigned wide integer type: double the width of [`Word`].
#[cfg(target_pointer_width = "32")]
pub type WideWord = u64;
/// Inner integer type that the [`Limb`] newtype wraps.
pub type Word = u32;

/// Unsigned wide integer type: double the width of [`Word`].
pub type WideWord = u64;

/// Returns the truthy value if `x <= y` and the falsy value otherwise.
#[inline]
pub(crate) const fn from_word_le(x: Word, y: Word) -> ConstChoice {
ConstChoice::from_u32_le(x, y)
}

//
// 64-bit definitions
//
/// Returns the truthy value if `x < y`, and the falsy value otherwise.
#[inline]
pub(crate) const fn from_word_lt(x: Word, y: Word) -> ConstChoice {
ConstChoice::from_u32_lt(x, y)
}

/// Returns the truthy value if `x <= y` and the falsy value otherwise.
#[inline]
pub(crate) const fn from_wide_word_le(x: WideWord, y: WideWord) -> ConstChoice {
ConstChoice::from_u64_le(x, y)
}
}

/// Unsigned integer type that the [`Limb`][`crate::Limb`] newtype wraps.
/// 64-bit definitions
#[cfg(target_pointer_width = "64")]
pub type Word = u64;
mod word64 {
use crate::ConstChoice;

/// Unsigned integer type that the [`Limb`][`crate::Limb`] newtype wraps.
pub type Word = u64;

/// Wide integer type: double the width of [`Word`].
pub type WideWord = u128;

/// Returns the truthy value if `x <= y` and the falsy value otherwise.
#[inline]
pub(crate) const fn from_word_le(x: Word, y: Word) -> ConstChoice {
ConstChoice::from_u64_le(x, y)
}

/// Returns the truthy value if `x < y`, and the falsy value otherwise.
#[inline]
pub(crate) const fn from_word_lt(x: Word, y: Word) -> ConstChoice {
ConstChoice::from_u64_lt(x, y)
}

/// Returns the truthy value if `x <= y` and the falsy value otherwise.
#[inline]
pub(crate) const fn from_wide_word_le(x: WideWord, y: WideWord) -> ConstChoice {
ConstChoice::from_u128_le(x, y)
}
}

/// Wide integer type: double the width of [`Word`].
#[cfg(target_pointer_width = "32")]
pub use word32::*;
#[cfg(target_pointer_width = "64")]
pub type WideWord = u128;
pub use word64::*;

/// Returns the truthy value if `x == y`, and the falsy value otherwise.
#[inline]
Expand All @@ -42,29 +83,13 @@ pub(crate) const fn from_word_gt(x: Word, y: Word) -> ConstChoice {
from_word_lt(y, x)
}

/// Returns the truthy value if `x <= y` and the falsy value otherwise.
#[inline]
pub(crate) const fn from_word_le(x: Word, y: Word) -> ConstChoice {
// See "Hacker's Delight" 2nd ed, section 2-12 (Comparison predicates)
let bit = (((!x) | y) & ((x ^ y) | !(y.wrapping_sub(x)))) >> (Word::BITS - 1);
from_word_lsb(bit)
}

/// Returns the truthy value if `value == 1`, and the falsy value if `value == 0`.
/// Panics for other values.
#[inline]
pub(crate) const fn from_word_lsb(value: Word) -> ConstChoice {
ConstChoice::new((value & 1) as u8)
}

/// Returns the truthy value if `x < y`, and the falsy value otherwise.
#[inline]
pub(crate) const fn from_word_lt(x: Word, y: Word) -> ConstChoice {
// See "Hacker's Delight" 2nd ed, section 2-12 (Comparison predicates)
let bit = (((!x) & y) | (((!x) | y) & (x.wrapping_sub(y)))) >> (Word::BITS - 1);
from_word_lsb(bit)
}

/// Returns the truthy value if `value == Word::MAX`, and the falsy value if `value == 0`.
/// Panics for other values.
#[inline]
Expand All @@ -85,21 +110,6 @@ pub(crate) const fn from_word_nonzero(value: Word) -> ConstChoice {
from_word_lsb((value | value.wrapping_neg()) >> (Word::BITS - 1))
}

/// Returns the truthy value if `x <= y` and the falsy value otherwise.
#[inline]
pub(crate) const fn from_wide_word_le(x: WideWord, y: WideWord) -> ConstChoice {
// See "Hacker's Delight" 2nd ed, section 2-12 (Comparison predicates)
let bit = (((!x) | y) & ((x ^ y) | !(y.wrapping_sub(x)))) >> (WideWord::BITS - 1);
from_wide_word_lsb(bit)
}

/// Returns the truthy value if `value == 1`, and the falsy value if `value == 0`.
/// Panics for other values.
#[inline]
pub(crate) const fn from_wide_word_lsb(value: WideWord) -> ConstChoice {
ConstChoice::new((value & 1) as u8)
}

/// Return `b` if `self` is truthy, otherwise return `a`.
#[inline]
pub(crate) const fn select_word(choice: ConstChoice, a: Word, b: Word) -> Word {
Expand Down