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
26 changes: 12 additions & 14 deletions src/int/gcd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ impl<const LIMBS: usize> Xgcd for OddInt<LIMBS> {
#[cfg(all(test, not(miri)))]
mod tests {
use crate::int::gcd::{IntXgcdOutput, NonZeroIntXgcdOutput, OddIntXgcdOutput};
use crate::{ConcatMixed, Gcd, Int, Uint};
use crate::{Concat, Gcd, Int, Uint};

impl<const LIMBS: usize> From<NonZeroIntXgcdOutput<LIMBS>> for IntXgcdOutput<LIMBS> {
fn from(value: NonZeroIntXgcdOutput<LIMBS>) -> Self {
Expand Down Expand Up @@ -419,7 +419,7 @@ mod tests {
rhs: Int<LIMBS>,
output: IntXgcdOutput<LIMBS>,
) where
Uint<LIMBS>: ConcatMixed<Uint<LIMBS>, MixedOutput = Uint<DOUBLE>>,
Uint<LIMBS>: Concat<LIMBS, Output = Uint<DOUBLE>>,
{
let gcd = lhs.gcd(&rhs);
assert_eq!(gcd, output.gcd);
Expand Down Expand Up @@ -455,21 +455,21 @@ mod tests {
mod test_int_xgcd {
use crate::int::gcd::tests::xgcd_test;
use crate::{
ConcatMixed, Gcd, Int, U64, U128, U192, U256, U384, U512, U768, U1024, U2048, U4096,
U8192, Uint,
Concat, Gcd, Int, U64, U128, U192, U256, U384, U512, U768, U1024, U2048, U4096, U8192,
Uint,
};

fn test<const LIMBS: usize, const DOUBLE: usize>(lhs: Int<LIMBS>, rhs: Int<LIMBS>)
where
Uint<LIMBS>: ConcatMixed<Uint<LIMBS>, MixedOutput = Uint<DOUBLE>>,
Uint<LIMBS>: Concat<LIMBS, Output = Uint<DOUBLE>>,
Int<LIMBS>: Gcd<Output = Uint<LIMBS>>,
{
xgcd_test(lhs, rhs, lhs.xgcd(&rhs));
}

fn run_tests<const LIMBS: usize, const DOUBLE: usize>()
where
Uint<LIMBS>: ConcatMixed<Uint<LIMBS>, MixedOutput = Uint<DOUBLE>>,
Uint<LIMBS>: Concat<LIMBS, Output = Uint<DOUBLE>>,
Int<LIMBS>: Gcd<Output = Uint<LIMBS>>,
{
test(Int::MIN, Int::MIN);
Expand Down Expand Up @@ -516,21 +516,20 @@ mod tests {
mod test_nonzero_int_xgcd {
use crate::int::gcd::tests::xgcd_test;
use crate::{
ConcatMixed, Int, U64, U128, U192, U256, U384, U512, U768, U1024, U2048, U4096, U8192,
Uint,
Concat, Int, U64, U128, U192, U256, U384, U512, U768, U1024, U2048, U4096, U8192, Uint,
};

fn test<const LIMBS: usize, const DOUBLE: usize>(lhs: Int<LIMBS>, rhs: Int<LIMBS>)
where
Uint<LIMBS>: ConcatMixed<Uint<LIMBS>, MixedOutput = Uint<DOUBLE>>,
Uint<LIMBS>: Concat<LIMBS, Output = Uint<DOUBLE>>,
{
let output = lhs.to_nz().unwrap().xgcd(&rhs.to_nz().unwrap());
xgcd_test(lhs, rhs, output.into());
}

fn run_tests<const LIMBS: usize, const DOUBLE: usize>()
where
Uint<LIMBS>: ConcatMixed<Uint<LIMBS>, MixedOutput = Uint<DOUBLE>>,
Uint<LIMBS>: Concat<LIMBS, Output = Uint<DOUBLE>>,
{
test(Int::MIN, Int::MIN);
test(Int::MIN, Int::MINUS_ONE);
Expand Down Expand Up @@ -567,21 +566,20 @@ mod tests {
mod test_odd_int_xgcd {
use crate::int::gcd::tests::xgcd_test;
use crate::{
ConcatMixed, Int, U64, U128, U192, U256, U384, U512, U768, U1024, U2048, U4096, U8192,
Uint,
Concat, Int, U64, U128, U192, U256, U384, U512, U768, U1024, U2048, U4096, U8192, Uint,
};

fn test<const LIMBS: usize, const DOUBLE: usize>(lhs: Int<LIMBS>, rhs: Int<LIMBS>)
where
Uint<LIMBS>: ConcatMixed<Uint<LIMBS>, MixedOutput = Uint<DOUBLE>>,
Uint<LIMBS>: Concat<LIMBS, Output = Uint<DOUBLE>>,
{
let output = lhs.to_odd().unwrap().xgcd(&rhs.to_nz().unwrap());
xgcd_test(lhs, rhs, output.into());
}

fn run_tests<const LIMBS: usize, const DOUBLE: usize>()
where
Uint<LIMBS>: ConcatMixed<Uint<LIMBS>, MixedOutput = Uint<DOUBLE>>,
Uint<LIMBS>: Concat<LIMBS, Output = Uint<DOUBLE>>,
{
let neg_max = Int::MAX.wrapping_neg();
test(neg_max, neg_max);
Expand Down
6 changes: 3 additions & 3 deletions src/int/mul.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! [`Int`] multiplication operations.

use crate::{
Checked, CheckedMul, Choice, ConcatMixed, CtOption, Int, Mul, MulAssign, Uint, WrappingMul,
Checked, CheckedMul, Choice, Concat, CtOption, Int, Mul, MulAssign, Uint, WrappingMul,
};

impl<const LIMBS: usize> Int<LIMBS> {
Expand Down Expand Up @@ -54,7 +54,7 @@ impl<const LIMBS: usize> Int<LIMBS> {
rhs: &Int<RHS_LIMBS>,
) -> Int<WIDE_LIMBS>
where
Uint<LIMBS>: ConcatMixed<Uint<RHS_LIMBS>, MixedOutput = Uint<WIDE_LIMBS>>,
Uint<LIMBS>: Concat<RHS_LIMBS, Output = Uint<WIDE_LIMBS>>,
{
let (lhs_abs, lhs_sign) = self.abs_sign();
let (rhs_abs, rhs_sign) = rhs.abs_sign();
Expand Down Expand Up @@ -112,7 +112,7 @@ impl<const LIMBS: usize> Int<LIMBS> {
#[must_use]
pub fn widening_square<const WIDE_LIMBS: usize>(&self) -> Uint<WIDE_LIMBS>
where
Uint<LIMBS>: ConcatMixed<Uint<LIMBS>, MixedOutput = Uint<WIDE_LIMBS>>,
Uint<LIMBS>: Concat<LIMBS, Output = Uint<WIDE_LIMBS>>,
{
self.abs().widening_square()
}
Expand Down
4 changes: 2 additions & 2 deletions src/int/mul_unsigned.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{CheckedMul, Choice, ConcatMixed, CtOption, Int, Uint};
use crate::{CheckedMul, Choice, Concat, CtOption, Int, Uint};
use core::ops::Mul;

impl<const LIMBS: usize> Int<LIMBS> {
Expand Down Expand Up @@ -81,7 +81,7 @@ impl<const LIMBS: usize> Int<LIMBS> {
rhs: &Uint<RHS_LIMBS>,
) -> Int<WIDE_LIMBS>
where
Uint<LIMBS>: ConcatMixed<Uint<RHS_LIMBS>, MixedOutput = Uint<WIDE_LIMBS>>,
Uint<LIMBS>: Concat<RHS_LIMBS, Output = Uint<WIDE_LIMBS>>,
{
let (lhs_abs, lhs_sign) = self.abs_sign();
let product_abs = lhs_abs.concatenating_mul(rhs);
Expand Down
25 changes: 11 additions & 14 deletions src/modular/bingcd/xgcd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@ impl<const LIMBS: usize> Uint<LIMBS> {
#[cfg(all(test, not(miri)))]
mod tests {
use crate::modular::bingcd::xgcd::PatternXgcdOutput;
use crate::{ConcatMixed, Uint};
use crate::{Concat, Uint};
use core::ops::Div;

mod test_extract_quotients {
Expand Down Expand Up @@ -570,7 +570,7 @@ mod tests {
rhs: Uint<LIMBS>,
output: PatternXgcdOutput<LIMBS>,
) where
Uint<LIMBS>: ConcatMixed<Uint<LIMBS>, MixedOutput = Uint<DOUBLE>>,
Uint<LIMBS>: Concat<LIMBS, Output = Uint<DOUBLE>>,
{
// Test the gcd
assert_eq!(lhs.gcd(&rhs), output.gcd, "{lhs} {rhs}");
Expand Down Expand Up @@ -599,23 +599,22 @@ mod tests {
mod test_binxgcd_nz {
use crate::modular::bingcd::xgcd::tests::test_xgcd;
use crate::{
ConcatMixed, Int, U64, U128, U192, U256, U384, U512, U768, U1024, U2048, U4096, U8192,
Uint,
Concat, Int, U64, U128, U192, U256, U384, U512, U768, U1024, U2048, U4096, U8192, Uint,
};

fn binxgcd_nz_test<const LIMBS: usize, const DOUBLE: usize>(
lhs: Uint<LIMBS>,
rhs: Uint<LIMBS>,
) where
Uint<LIMBS>: ConcatMixed<Uint<LIMBS>, MixedOutput = Uint<DOUBLE>>,
Uint<LIMBS>: Concat<LIMBS, Output = Uint<DOUBLE>>,
{
let output = lhs.to_odd().unwrap().binxgcd_nz(&rhs.to_nz().unwrap());
test_xgcd(lhs, rhs, output);
}

fn binxgcd_nz_tests<const LIMBS: usize, const DOUBLE: usize>()
where
Uint<LIMBS>: ConcatMixed<Uint<LIMBS>, MixedOutput = Uint<DOUBLE>>,
Uint<LIMBS>: Concat<LIMBS, Output = Uint<DOUBLE>>,
{
let max_int = *Int::MAX.as_uint();
let int_abs_min = Int::MIN.abs();
Expand Down Expand Up @@ -651,15 +650,14 @@ mod tests {
mod test_classic_binxgcd {
use crate::modular::bingcd::xgcd::tests::test_xgcd;
use crate::{
ConcatMixed, Int, U64, U128, U192, U256, U384, U512, U768, U1024, U2048, U4096, U8192,
Uint,
Concat, Int, U64, U128, U192, U256, U384, U512, U768, U1024, U2048, U4096, U8192, Uint,
};

fn classic_binxgcd_test<const LIMBS: usize, const DOUBLE: usize>(
lhs: Uint<LIMBS>,
rhs: Uint<LIMBS>,
) where
Uint<LIMBS>: ConcatMixed<Uint<LIMBS>, MixedOutput = Uint<DOUBLE>>,
Uint<LIMBS>: Concat<LIMBS, Output = Uint<DOUBLE>>,
{
let output = lhs
.to_odd()
Expand All @@ -671,7 +669,7 @@ mod tests {

fn classic_binxgcd_tests<const LIMBS: usize, const DOUBLE: usize>()
where
Uint<LIMBS>: ConcatMixed<Uint<LIMBS>, MixedOutput = Uint<DOUBLE>>,
Uint<LIMBS>: Concat<LIMBS, Output = Uint<DOUBLE>>,
{
let max_int = *Int::MAX.as_uint();

Expand Down Expand Up @@ -704,13 +702,12 @@ mod tests {
use crate::modular::bingcd::xgcd::tests::test_xgcd;
use crate::modular::bingcd::xgcd::{DOUBLE_SUMMARY_LIMBS, SUMMARY_BITS, SUMMARY_LIMBS};
use crate::{
ConcatMixed, Int, U64, U128, U192, U256, U384, U512, U768, U1024, U2048, U4096, U8192,
Uint,
Concat, Int, U64, U128, U192, U256, U384, U512, U768, U1024, U2048, U4096, U8192, Uint,
};

fn test<const LIMBS: usize, const DOUBLE: usize>(lhs: Uint<LIMBS>, rhs: Uint<LIMBS>)
where
Uint<LIMBS>: ConcatMixed<Uint<LIMBS>, MixedOutput = Uint<DOUBLE>>,
Uint<LIMBS>: Concat<LIMBS, Output = Uint<DOUBLE>>,
{
let output = lhs
.to_odd()
Expand All @@ -722,7 +719,7 @@ mod tests {

fn run_tests<const LIMBS: usize, const DOUBLE: usize>()
where
Uint<LIMBS>: ConcatMixed<Uint<LIMBS>, MixedOutput = Uint<DOUBLE>>,
Uint<LIMBS>: Concat<LIMBS, Output = Uint<DOUBLE>>,
{
let upper_bound = *Int::MAX.as_uint();
test(Uint::ONE, Uint::ONE);
Expand Down
57 changes: 19 additions & 38 deletions src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -664,49 +664,24 @@ pub trait CheckedSub<Rhs = Self>: Sized {
fn checked_sub(&self, rhs: &Rhs) -> CtOption<Self>;
}

/// Concatenate two numbers into a "wide" double-width value, using the `hi` value as the most
/// significant portion of the resulting value.
pub trait Concat: ConcatMixed<Self, MixedOutput = Self::Output> {
/// Concatenated output: twice the width of `Self`.
/// Define the result of concatenating two numbers into a "wide" value.
pub trait Concat<const HI: usize> {
/// Concatenated output: having the width of `Self` plus `HI`.
type Output: Integer;

/// Concatenate the two halves, with `self` as least significant and `hi` as the most significant.
#[must_use]
fn concat(&self, hi: &Self) -> Self::Output {
self.concat_mixed(hi)
}
}

/// Concatenate two numbers into a "wide" combined-width value, using the `hi` value as the most
/// significant value.
pub trait ConcatMixed<Hi: ?Sized = Self> {
/// Concatenated output: combination of `Self` and `Hi`.
type MixedOutput: Integer;

/// Concatenate the two values, with `self` as least significant and `hi` as the most
/// significant.
#[must_use]
fn concat_mixed(&self, hi: &Hi) -> Self::MixedOutput;
}

/// Split a number in half, returning the least significant half followed by the most significant.
pub trait Split: SplitMixed<Self::Output, Self::Output> {
/// Split output: low/high components of the value.
type Output;

/// Split this number in half, returning its low and high components respectively.
#[must_use]
fn split(&self) -> (Self::Output, Self::Output) {
self.split_mixed()
}
/// Define the result of splitting a number into two parts, with the
/// first part having the width `LO`.
pub trait Split<const LO: usize> {
/// High limbs of output: having the width of `Self` minus `LO`.
type Output: Integer;
}

/// Split a number into parts, returning the least significant part followed by the most
/// significant.
pub trait SplitMixed<Lo, Hi> {
/// Split this number into parts, returning its low and high components respectively.
#[must_use]
fn split_mixed(&self) -> (Lo, Hi);
/// Define the result of splitting a number into two parts, with
/// each part having an equal width.
pub trait SplitEven {
/// Split output: each component having half the width of `Self`.
type Output: Integer;
}

/// Encoding support.
Expand Down Expand Up @@ -735,6 +710,12 @@ pub trait Encoding: Sized {
fn to_le_bytes(&self) -> Self::Repr;
}

/// A trait mapping between encoded representations of integers.
pub trait EncodedSize {
/// The equivalent encoded representation.
type Target;
}

/// Possible errors in variable-time integer decoding methods.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum DecodeError {
Expand Down
59 changes: 28 additions & 31 deletions src/uint/concat.rs
Original file line number Diff line number Diff line change
@@ -1,52 +1,38 @@
use crate::{Concat, ConcatMixed, Limb, Uint};
use crate::{Concat, Uint};

impl<const L: usize> Uint<L> {
impl<const LIMBS: usize> Uint<LIMBS> {
/// Concatenate the two values, with `self` as least significant and `hi` as the most
/// significant.
/// significant, with both values having the same size.
#[must_use]
pub const fn concat<const O: usize>(&self, hi: &Self) -> Uint<O>
pub const fn concat<const WIDE_LIMBS: usize>(&self, hi: &Self) -> Uint<WIDE_LIMBS>
where
Self: Concat<Output = Uint<O>>,
Self: Concat<LIMBS, Output = Uint<WIDE_LIMBS>>,
{
Uint::concat_mixed(self, hi)
}

/// Concatenate the two values, with `lo` as least significant and `hi`
/// Concatenate the two values, with `self` as least significant and `hi`
/// as the most significant.
#[inline]
#[must_use]
pub const fn concat_mixed<const H: usize, const O: usize>(lo: &Uint<L>, hi: &Uint<H>) -> Uint<O>
pub const fn concat_mixed<const HI_LIMBS: usize, const WIDE_LIMBS: usize>(
&self,
hi: &Uint<HI_LIMBS>,
) -> Uint<WIDE_LIMBS>
where
Self: ConcatMixed<Uint<H>, MixedOutput = Uint<O>>,
Self: Concat<HI_LIMBS, Output = Uint<WIDE_LIMBS>>,
{
let top = L + H;
let top = if top < O { top } else { O };
let mut limbs = [Limb::ZERO; O];
let mut i = 0;

while i < top {
if i < L {
limbs[i] = lo.limbs[i];
} else {
limbs[i] = hi.limbs[i - L];
}
i += 1;
}

Uint { limbs }
let mut res = Uint::ZERO;
let (res_lo, res_hi) = res.as_mut_uint_ref().split_at_mut(LIMBS);
res_lo.copy_from(self.as_uint_ref());
res_hi.copy_from(hi.as_uint_ref());
res
}
}

impl<T> Concat for T
where
T: ConcatMixed<T>,
{
type Output = Self::MixedOutput;
}

#[cfg(test)]
mod tests {
use crate::{ConcatMixed, U64, U128, U192};
use crate::{BitOps, U64, U128, U192, Uint};

#[test]
fn concat() {
Expand Down Expand Up @@ -80,4 +66,15 @@ mod tests {
let res: U128 = U64::ONE.square_wide().into();
assert_eq!(res, U128::ONE);
}

#[test]
fn infer_sizes() {
let wide = U64::ONE.concat(&Uint::ZERO);
assert_eq!(wide.bits_precision(), 128);
assert_eq!(wide, Uint::ONE);

let wide = U64::ONE.concat_mixed(&U128::ZERO);
assert_eq!(wide.bits_precision(), 192);
assert_eq!(wide, Uint::ONE);
}
}
Loading