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
13 changes: 11 additions & 2 deletions src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ pub trait CheckedSub<Rhs = Self>: Sized {
/// value as the least significant value.
pub trait Concat: ConcatMixed<Self, MixedOutput = Self::Output> {
/// Concatenated output: twice the width of `Self`.
type Output;
type Output: Integer;

/// Concatenate the two halves, with `self` as most significant and `lo`
/// as the least significant.
Expand All @@ -285,7 +285,7 @@ pub trait Concat: ConcatMixed<Self, MixedOutput = Self::Output> {
/// value as the least significant value.
pub trait ConcatMixed<Lo: ?Sized = Self> {
/// Concatenated output: combination of `Lo` and `Self`.
type MixedOutput;
type MixedOutput: Integer;

/// Concatenate the two values, with `self` as most significant and `lo`
/// as the least significant.
Expand Down Expand Up @@ -416,3 +416,12 @@ pub trait Invert: Sized {
/// Computes the inverse.
fn invert(&self) -> Self::Output;
}

/// Widening multiply: returns a value with a number of limbs equal to the sum of the inputs.
pub trait WideningMul<Rhs = Self>: Sized {
/// Output of the widening multiplication.
type Output: Integer;

/// Perform widening multiplication.
fn widening_mul(&self, rhs: Rhs) -> Self::Output;
}
28 changes: 27 additions & 1 deletion src/uint/boxed/mul.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! [`BoxedUint`] multiplication operations.

use crate::{uint::mul::mul_limbs, BoxedUint, CheckedMul, Limb, Wrapping, Zero};
use crate::{uint::mul::mul_limbs, BoxedUint, CheckedMul, Limb, WideningMul, Wrapping, Zero};
use core::ops::{Mul, MulAssign};
use subtle::{Choice, CtOption};

Expand All @@ -26,6 +26,14 @@ impl BoxedUint {
}
}

impl CheckedMul<BoxedUint> for BoxedUint {
type Output = Self;

fn checked_mul(&self, rhs: BoxedUint) -> CtOption<Self> {
self.checked_mul(&rhs)
}
}

impl CheckedMul<&BoxedUint> for BoxedUint {
type Output = Self;

Expand All @@ -43,6 +51,24 @@ impl CheckedMul<&BoxedUint> for BoxedUint {
}
}

impl WideningMul for BoxedUint {
type Output = Self;

#[inline]
fn widening_mul(&self, rhs: BoxedUint) -> Self {
self.mul(&rhs)
}
}

impl WideningMul<&BoxedUint> for BoxedUint {
type Output = Self;

#[inline]
fn widening_mul(&self, rhs: &BoxedUint) -> Self {
self.mul(rhs)
}
}

impl Mul<Wrapping<BoxedUint>> for Wrapping<BoxedUint> {
type Output = Self;

Expand Down
39 changes: 38 additions & 1 deletion src/uint/mul.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

// TODO(tarcieri): use Karatsuba for better performance

use crate::{Checked, CheckedMul, Concat, ConcatMixed, Limb, Uint, WideWord, Word, Wrapping, Zero};
use crate::{
Checked, CheckedMul, Concat, ConcatMixed, Limb, Uint, WideWord, WideningMul, Word, Wrapping,
Zero,
};
use core::ops::{Mul, MulAssign};
use subtle::CtOption;

Expand Down Expand Up @@ -165,15 +168,49 @@ impl<const LIMBS: usize> Uint<LIMBS> {
}
}

impl<const LIMBS: usize, const HLIMBS: usize> CheckedMul<Uint<HLIMBS>> for Uint<LIMBS> {
type Output = Self;

#[inline]
fn checked_mul(&self, rhs: Uint<HLIMBS>) -> CtOption<Self> {
self.checked_mul(&rhs)
}
}

impl<const LIMBS: usize, const HLIMBS: usize> CheckedMul<&Uint<HLIMBS>> for Uint<LIMBS> {
type Output = Self;

#[inline]
fn checked_mul(&self, rhs: &Uint<HLIMBS>) -> CtOption<Self> {
let (lo, hi) = self.mul_wide(rhs);
CtOption::new(lo, hi.is_zero())
}
}

impl<const LIMBS: usize, const HLIMBS: usize> WideningMul<Uint<HLIMBS>> for Uint<LIMBS>
where
Uint<HLIMBS>: ConcatMixed<Self>,
{
type Output = <Uint<HLIMBS> as ConcatMixed<Self>>::MixedOutput;

#[inline]
fn widening_mul(&self, rhs: Uint<HLIMBS>) -> Self::Output {
self.mul(&rhs)
}
}

impl<const LIMBS: usize, const HLIMBS: usize> WideningMul<&Uint<HLIMBS>> for Uint<LIMBS>
where
Uint<HLIMBS>: ConcatMixed<Self>,
{
type Output = <Uint<HLIMBS> as ConcatMixed<Self>>::MixedOutput;

#[inline]
fn widening_mul(&self, rhs: &Uint<HLIMBS>) -> Self::Output {
self.mul(rhs)
}
}

impl<const LIMBS: usize, const HLIMBS: usize> Mul<Wrapping<Uint<HLIMBS>>>
for Wrapping<Uint<LIMBS>>
{
Expand Down