Skip to content

Commit b04f2f1

Browse files
authored
Impl PrecomputeInterver(WithAdjuster) on Odd (#500)
Moves all of the impls for these traits to `Odd<Uint<_>>`/`Odd<BoxedUint>`. They infallibly return an inverter, but previously panicked if called on even numbers. This commit replaces the panic condition with type safety instead.
1 parent 687b990 commit b04f2f1

File tree

10 files changed

+82
-54
lines changed

10 files changed

+82
-54
lines changed

src/modular/boxed_monty_form/inv.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ impl PrecomputeInverter for BoxedMontyParams {
3333

3434
fn precompute_inverter(&self) -> BoxedMontyFormInverter {
3535
BoxedMontyFormInverter {
36-
inverter: self.modulus.0.precompute_inverter_with_adjuster(&self.r2),
36+
inverter: self.modulus.precompute_inverter_with_adjuster(&self.r2),
3737
params: self.clone().into(),
3838
}
3939
}

src/modular/const_monty_form.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ pub trait ConstMontyParams<const LIMBS: usize>:
5555
/// Use [`ConstMontyFormInverter::new`] if you need `const fn` access.
5656
fn precompute_inverter<const UNSAT_LIMBS: usize>() -> ConstMontyFormInverter<Self, LIMBS>
5757
where
58-
Uint<LIMBS>: PrecomputeInverter<
58+
Odd<Uint<LIMBS>>: PrecomputeInverter<
5959
Inverter = BernsteinYangInverter<LIMBS, UNSAT_LIMBS>,
6060
Output = Uint<LIMBS>,
6161
>,

src/modular/const_monty_form/inv.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22
33
use super::{ConstMontyForm, ConstMontyParams};
44
use crate::{
5-
modular::BernsteinYangInverter, ConstCtOption, Invert, Inverter, PrecomputeInverter, Uint,
5+
modular::BernsteinYangInverter, ConstCtOption, Invert, Inverter, Odd, PrecomputeInverter, Uint,
66
};
77
use core::{fmt, marker::PhantomData};
88
use subtle::CtOption;
99

1010
impl<MOD: ConstMontyParams<SAT_LIMBS>, const SAT_LIMBS: usize, const UNSAT_LIMBS: usize>
1111
ConstMontyForm<MOD, SAT_LIMBS>
1212
where
13-
Uint<SAT_LIMBS>: PrecomputeInverter<
13+
Odd<Uint<SAT_LIMBS>>: PrecomputeInverter<
1414
Inverter = BernsteinYangInverter<SAT_LIMBS, UNSAT_LIMBS>,
1515
Output = Uint<SAT_LIMBS>,
1616
>,
@@ -21,7 +21,7 @@ where
2121
/// otherwise it is the falsy value (in which case the first element's value is unspecified).
2222
pub const fn inv(&self) -> ConstCtOption<Self> {
2323
let inverter =
24-
<Uint<SAT_LIMBS> as PrecomputeInverter>::Inverter::new(&MOD::MODULUS, &MOD::R2);
24+
<Odd<Uint<SAT_LIMBS>> as PrecomputeInverter>::Inverter::new(&MOD::MODULUS, &MOD::R2);
2525

2626
let maybe_inverse = inverter.inv(&self.montgomery_form);
2727
let (inverse, inverse_is_some) = maybe_inverse.components_ref();
@@ -38,7 +38,7 @@ where
3838
impl<MOD: ConstMontyParams<SAT_LIMBS>, const SAT_LIMBS: usize, const UNSAT_LIMBS: usize> Invert
3939
for ConstMontyForm<MOD, SAT_LIMBS>
4040
where
41-
Uint<SAT_LIMBS>: PrecomputeInverter<
41+
Odd<Uint<SAT_LIMBS>>: PrecomputeInverter<
4242
Inverter = BernsteinYangInverter<SAT_LIMBS, UNSAT_LIMBS>,
4343
Output = Uint<SAT_LIMBS>,
4444
>,
@@ -52,16 +52,16 @@ where
5252
/// Bernstein-Yang inverter which inverts [`ConstMontyForm`] types.
5353
pub struct ConstMontyFormInverter<MOD: ConstMontyParams<LIMBS>, const LIMBS: usize>
5454
where
55-
Uint<LIMBS>: PrecomputeInverter<Output = Uint<LIMBS>>,
55+
Odd<Uint<LIMBS>>: PrecomputeInverter<Output = Uint<LIMBS>>,
5656
{
57-
inverter: <Uint<LIMBS> as PrecomputeInverter>::Inverter,
57+
inverter: <Odd<Uint<LIMBS>> as PrecomputeInverter>::Inverter,
5858
phantom: PhantomData<MOD>,
5959
}
6060

6161
impl<MOD: ConstMontyParams<SAT_LIMBS>, const SAT_LIMBS: usize, const UNSAT_LIMBS: usize>
6262
ConstMontyFormInverter<MOD, SAT_LIMBS>
6363
where
64-
Uint<SAT_LIMBS>: PrecomputeInverter<
64+
Odd<Uint<SAT_LIMBS>>: PrecomputeInverter<
6565
Inverter = BernsteinYangInverter<SAT_LIMBS, UNSAT_LIMBS>,
6666
Output = Uint<SAT_LIMBS>,
6767
>,
@@ -95,7 +95,7 @@ where
9595
impl<MOD: ConstMontyParams<SAT_LIMBS>, const SAT_LIMBS: usize, const UNSAT_LIMBS: usize> Inverter
9696
for ConstMontyFormInverter<MOD, SAT_LIMBS>
9797
where
98-
Uint<SAT_LIMBS>: PrecomputeInverter<
98+
Odd<Uint<SAT_LIMBS>>: PrecomputeInverter<
9999
Inverter = BernsteinYangInverter<SAT_LIMBS, UNSAT_LIMBS>,
100100
Output = Uint<SAT_LIMBS>,
101101
>,
@@ -110,7 +110,7 @@ where
110110
impl<MOD: ConstMontyParams<SAT_LIMBS>, const SAT_LIMBS: usize, const UNSAT_LIMBS: usize> fmt::Debug
111111
for ConstMontyFormInverter<MOD, SAT_LIMBS>
112112
where
113-
Uint<SAT_LIMBS>: PrecomputeInverter<
113+
Odd<Uint<SAT_LIMBS>>: PrecomputeInverter<
114114
Inverter = BernsteinYangInverter<SAT_LIMBS, UNSAT_LIMBS>,
115115
Output = Uint<SAT_LIMBS>,
116116
>,

src/modular/monty_form/inv.rs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22
33
use super::{MontyForm, MontyParams};
44
use crate::{
5-
modular::BernsteinYangInverter, traits::Invert, ConstCtOption, Inverter, PrecomputeInverter,
6-
PrecomputeInverterWithAdjuster, Uint,
5+
modular::BernsteinYangInverter, traits::Invert, ConstCtOption, Inverter, Odd,
6+
PrecomputeInverter, PrecomputeInverterWithAdjuster, Uint,
77
};
88
use core::fmt;
99
use subtle::CtOption;
1010

1111
impl<const SAT_LIMBS: usize, const UNSAT_LIMBS: usize> MontyForm<SAT_LIMBS>
1212
where
13-
Uint<SAT_LIMBS>: PrecomputeInverter<
13+
Odd<Uint<SAT_LIMBS>>: PrecomputeInverter<
1414
Inverter = BernsteinYangInverter<SAT_LIMBS, UNSAT_LIMBS>,
1515
Output = Uint<SAT_LIMBS>,
1616
>,
@@ -20,7 +20,7 @@ where
2020
/// If the number was invertible, the second element of the tuple is the truthy value,
2121
/// otherwise it is the falsy value (in which case the first element's value is unspecified).
2222
pub const fn inv(&self) -> ConstCtOption<Self> {
23-
let inverter = <Uint<SAT_LIMBS> as PrecomputeInverter>::Inverter::new(
23+
let inverter = <Odd<Uint<SAT_LIMBS>> as PrecomputeInverter>::Inverter::new(
2424
&self.params.modulus,
2525
&self.params.r2,
2626
);
@@ -39,7 +39,7 @@ where
3939

4040
impl<const SAT_LIMBS: usize, const UNSAT_LIMBS: usize> Invert for MontyForm<SAT_LIMBS>
4141
where
42-
Uint<SAT_LIMBS>: PrecomputeInverter<
42+
Odd<Uint<SAT_LIMBS>>: PrecomputeInverter<
4343
Inverter = BernsteinYangInverter<SAT_LIMBS, UNSAT_LIMBS>,
4444
Output = Uint<SAT_LIMBS>,
4545
>,
@@ -53,7 +53,8 @@ where
5353

5454
impl<const LIMBS: usize> PrecomputeInverter for MontyParams<LIMBS>
5555
where
56-
Uint<LIMBS>: PrecomputeInverter<Output = Uint<LIMBS>> + PrecomputeInverterWithAdjuster,
56+
Odd<Uint<LIMBS>>:
57+
PrecomputeInverter<Output = Uint<LIMBS>> + PrecomputeInverterWithAdjuster<Uint<LIMBS>>,
5758
{
5859
type Inverter = MontyFormInverter<LIMBS>;
5960
type Output = MontyForm<LIMBS>;
@@ -69,15 +70,15 @@ where
6970
/// Bernstein-Yang inverter which inverts [`MontyForm`] types.
7071
pub struct MontyFormInverter<const LIMBS: usize>
7172
where
72-
Uint<LIMBS>: PrecomputeInverter<Output = Uint<LIMBS>>,
73+
Odd<Uint<LIMBS>>: PrecomputeInverter<Output = Uint<LIMBS>>,
7374
{
74-
inverter: <Uint<LIMBS> as PrecomputeInverter>::Inverter,
75+
inverter: <Odd<Uint<LIMBS>> as PrecomputeInverter>::Inverter,
7576
params: MontyParams<LIMBS>,
7677
}
7778

7879
impl<const LIMBS: usize> Inverter for MontyFormInverter<LIMBS>
7980
where
80-
Uint<LIMBS>: PrecomputeInverter<Output = Uint<LIMBS>>,
81+
Odd<Uint<LIMBS>>: PrecomputeInverter<Output = Uint<LIMBS>>,
8182
{
8283
type Output = MontyForm<LIMBS>;
8384

@@ -95,7 +96,7 @@ where
9596

9697
impl<const SAT_LIMBS: usize, const UNSAT_LIMBS: usize> fmt::Debug for MontyFormInverter<SAT_LIMBS>
9798
where
98-
Uint<SAT_LIMBS>: PrecomputeInverter<
99+
Odd<Uint<SAT_LIMBS>>: PrecomputeInverter<
99100
Inverter = BernsteinYangInverter<SAT_LIMBS, UNSAT_LIMBS>,
100101
Output = Uint<SAT_LIMBS>,
101102
>,

src/traits/sealed.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
use super::PrecomputeInverter;
44

55
/// Obtain a precomputed inverter which applies the given adjustment factor, i.e. for Montgomery form.
6-
pub trait PrecomputeInverterWithAdjuster: PrecomputeInverter {
6+
pub trait PrecomputeInverterWithAdjuster<Adjuster>: PrecomputeInverter {
77
/// Obtain a precomputed inverter for `&self` as the modulus, supplying a custom adjusting parameter (e.g. R^2 for
88
/// when computing inversions in Montgomery form).
9-
fn precompute_inverter_with_adjuster(&self, adjuster: &Self) -> Self::Inverter;
9+
fn precompute_inverter_with_adjuster(&self, adjuster: &Adjuster) -> Self::Inverter;
1010
}

src/uint/boxed/from.rs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! `From`-like conversions for [`BoxedUint`].
22
3-
use crate::{BoxedUint, Limb, Uint, Word, U128, U64};
3+
use crate::{BoxedUint, Limb, Odd, Uint, Word, U128, U64};
44
use alloc::{boxed::Box, vec::Vec};
55
use core::mem;
66

@@ -94,3 +94,31 @@ impl<const LIMBS: usize> From<&Uint<LIMBS>> for BoxedUint {
9494
Vec::from(uint.to_limbs()).into()
9595
}
9696
}
97+
98+
impl<const LIMBS: usize> From<Odd<Uint<LIMBS>>> for BoxedUint {
99+
#[inline]
100+
fn from(uint: Odd<Uint<LIMBS>>) -> BoxedUint {
101+
Self::from(&uint.0)
102+
}
103+
}
104+
105+
impl<const LIMBS: usize> From<&Odd<Uint<LIMBS>>> for BoxedUint {
106+
#[inline]
107+
fn from(uint: &Odd<Uint<LIMBS>>) -> BoxedUint {
108+
Self::from(&uint.0)
109+
}
110+
}
111+
112+
impl<const LIMBS: usize> From<Odd<Uint<LIMBS>>> for Odd<BoxedUint> {
113+
#[inline]
114+
fn from(uint: Odd<Uint<LIMBS>>) -> Odd<BoxedUint> {
115+
Odd(BoxedUint::from(&uint.0))
116+
}
117+
}
118+
119+
impl<const LIMBS: usize> From<&Odd<Uint<LIMBS>>> for Odd<BoxedUint> {
120+
#[inline]
121+
fn from(uint: &Odd<Uint<LIMBS>>) -> Odd<BoxedUint> {
122+
Odd(BoxedUint::from(&uint.0))
123+
}
124+
}

src/uint/boxed/inv_mod.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! [`BoxedUint`] modular inverse (i.e. reciprocal) operations.
22
33
use crate::{
4-
modular::BoxedBernsteinYangInverter, BoxedUint, ConstantTimeSelect, Integer,
4+
modular::BoxedBernsteinYangInverter, BoxedUint, ConstantTimeSelect, Integer, Odd,
55
PrecomputeInverter, PrecomputeInverterWithAdjuster,
66
};
77
use subtle::{Choice, ConstantTimeEq, ConstantTimeLess, CtOption};
@@ -146,22 +146,22 @@ impl BoxedUint {
146146
}
147147

148148
/// Precompute a Bernstein-Yang inverter using `self` as the modulus.
149-
///
150-
/// Panics if called on an even number!
151-
impl PrecomputeInverter for BoxedUint {
149+
impl PrecomputeInverter for Odd<BoxedUint> {
152150
type Inverter = BoxedBernsteinYangInverter;
153-
type Output = Self;
151+
type Output = BoxedUint;
154152

155153
fn precompute_inverter(&self) -> BoxedBernsteinYangInverter {
156-
Self::precompute_inverter_with_adjuster(self, &Self::one())
154+
Self::precompute_inverter_with_adjuster(self, &BoxedUint::one())
157155
}
158156
}
159157

160-
// TODO(tarcieri): only impl these traits for `Odd`?
161-
impl PrecomputeInverterWithAdjuster for BoxedUint {
162-
fn precompute_inverter_with_adjuster(&self, adjuster: &Self) -> BoxedBernsteinYangInverter {
163-
let modulus = self.to_odd().expect("modulus must be odd");
164-
BoxedBernsteinYangInverter::new(&modulus, adjuster)
158+
/// Precompute a Bernstein-Yang inverter using `self` as the modulus.
159+
impl PrecomputeInverterWithAdjuster<BoxedUint> for Odd<BoxedUint> {
160+
fn precompute_inverter_with_adjuster(
161+
&self,
162+
adjuster: &BoxedUint,
163+
) -> BoxedBernsteinYangInverter {
164+
BoxedBernsteinYangInverter::new(self, adjuster)
165165
}
166166
}
167167

src/uint/gcd.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,20 @@ use subtle::CtOption;
55

66
impl<const SAT_LIMBS: usize, const UNSAT_LIMBS: usize> Uint<SAT_LIMBS>
77
where
8-
Self: PrecomputeInverter<Inverter = BernsteinYangInverter<SAT_LIMBS, UNSAT_LIMBS>>,
8+
Odd<Self>: PrecomputeInverter<Inverter = BernsteinYangInverter<SAT_LIMBS, UNSAT_LIMBS>>,
99
{
1010
/// Compute the greatest common divisor (GCD) of this number and another.
1111
///
1212
/// Returns none in the event that `self` is even (i.e. `self` MUST be odd). However, `rhs` may be even.
1313
pub const fn gcd(&self, rhs: &Self) -> ConstCtOption<Self> {
14-
let ret = <Self as PrecomputeInverter>::Inverter::gcd(self, rhs);
14+
let ret = <Odd<Self> as PrecomputeInverter>::Inverter::gcd(self, rhs);
1515
ConstCtOption::new(ret, self.is_odd())
1616
}
1717
}
1818

1919
impl<const SAT_LIMBS: usize, const UNSAT_LIMBS: usize> Gcd for Uint<SAT_LIMBS>
2020
where
21-
Self: PrecomputeInverter<Inverter = BernsteinYangInverter<SAT_LIMBS, UNSAT_LIMBS>>,
21+
Odd<Self>: PrecomputeInverter<Inverter = BernsteinYangInverter<SAT_LIMBS, UNSAT_LIMBS>>,
2222
{
2323
type Output = CtOption<Uint<SAT_LIMBS>>;
2424

@@ -29,12 +29,12 @@ where
2929

3030
impl<const SAT_LIMBS: usize, const UNSAT_LIMBS: usize> Gcd<Uint<SAT_LIMBS>> for Odd<Uint<SAT_LIMBS>>
3131
where
32-
Self: PrecomputeInverter<Inverter = BernsteinYangInverter<SAT_LIMBS, UNSAT_LIMBS>>,
32+
Odd<Self>: PrecomputeInverter<Inverter = BernsteinYangInverter<SAT_LIMBS, UNSAT_LIMBS>>,
3333
{
3434
type Output = Uint<SAT_LIMBS>;
3535

3636
fn gcd(&self, rhs: &Uint<SAT_LIMBS>) -> Uint<SAT_LIMBS> {
37-
<Self as PrecomputeInverter>::Inverter::gcd(self, rhs)
37+
<Odd<Self> as PrecomputeInverter>::Inverter::gcd(self, rhs)
3838
}
3939
}
4040

src/uint/macros.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
/// Impl the `Inverter` trait, where we need to compute the number of unsaturated limbs for a given number of bits.
44
macro_rules! impl_precompute_inverter_trait {
55
($name:ident, $bits:expr) => {
6-
/// Precompute a Bernstein-Yang inverter using `self` as the modulus. Panics if called on an even number!
7-
impl PrecomputeInverter for $name {
6+
/// Precompute a Bernstein-Yang inverter using `self` as the modulus.
7+
impl PrecomputeInverter for Odd<$name> {
88
#[allow(trivial_numeric_casts)]
99
type Inverter = BernsteinYangInverter<
1010
{ nlimbs!($bits) },
@@ -14,15 +14,14 @@ macro_rules! impl_precompute_inverter_trait {
1414
type Output = $name;
1515

1616
fn precompute_inverter(&self) -> Self::Inverter {
17-
Self::precompute_inverter_with_adjuster(self, &Self::ONE)
17+
Self::precompute_inverter_with_adjuster(self, &Uint::ONE)
1818
}
1919
}
2020

21-
// TODO(tarcieri): only impl these traits for `Odd`?
22-
impl PrecomputeInverterWithAdjuster for $name {
23-
fn precompute_inverter_with_adjuster(&self, adjuster: &Self) -> Self::Inverter {
24-
let modulus = self.to_odd().expect("modulus must be odd");
25-
Self::Inverter::new(&modulus, adjuster)
21+
/// Precompute a Bernstein-Yang inverter using `self` as the modulus.
22+
impl PrecomputeInverterWithAdjuster<$name> for Odd<$name> {
23+
fn precompute_inverter_with_adjuster(&self, adjuster: &$name) -> Self::Inverter {
24+
Self::Inverter::new(self, adjuster)
2625
}
2726
}
2827
};

tests/bernstein_yang_proptests.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
//! Equivalence tests for Bernstein-Yang inversions.
22
3-
use crypto_bigint::{Encoding, Inverter, PrecomputeInverter, U256};
3+
use crypto_bigint::{Encoding, Inverter, Odd, PrecomputeInverter, U256};
44
use num_bigint::BigUint;
55
use num_integer::Integer;
66
use num_traits::One;
77
use proptest::prelude::*;
88

99
#[cfg(feature = "alloc")]
10-
use crypto_bigint::{BoxedUint, NonZero};
10+
use crypto_bigint::BoxedUint;
1111

1212
/// Example prime number (NIST P-256 curve order)
13-
const P: U256 =
14-
U256::from_be_hex("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551");
13+
const P: Odd<U256> =
14+
Odd::<U256>::from_be_hex("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551");
1515

1616
fn to_biguint(uint: &U256) -> BigUint {
1717
BigUint::from_bytes_le(uint.to_le_bytes().as_ref())
@@ -63,8 +63,8 @@ proptest! {
6363
#[cfg(feature = "alloc")]
6464
#[test]
6565
fn boxed_inv_mod(x in boxed_uint()) {
66-
let p = BoxedUint::from(&P);
67-
let x = x.rem_vartime(&NonZero::new(p.clone()).unwrap()).widen(p.bits_precision());
66+
let p = Odd::<BoxedUint>::from(&P);
67+
let x = x.rem_vartime(p.as_nz_ref()).widen(p.bits_precision());
6868

6969
let x_bi = to_biguint_boxed(&x);
7070
let p_bi = to_biguint(&P);

0 commit comments

Comments
 (0)