Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Binary XGCD #761

Draft
wants to merge 158 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
158 commits
Select commit Hold shift + click to select a range
e8d8f4f
Impl `new_inv_mod_odd`
erik-3milabs Jan 27, 2025
f46213d
Modify `new_inv_mod_odd` algorithm
erik-3milabs Jan 27, 2025
378e2ee
Make `as_limbs_mut` const
erik-3milabs Jan 27, 2025
45fc11d
Introduce const `conditional_swap`
erik-3milabs Jan 27, 2025
4ba745c
Improve `Int::checked_mul` notation
erik-3milabs Jan 27, 2025
02ceb4f
Introduce new_gcd
erik-3milabs Jan 27, 2025
c6891f4
Get bingcd working
erik-3milabs Jan 28, 2025
b9fb154
Fix fmt
erik-3milabs Jan 29, 2025
ffe7bb2
65mus U1024::gcd
erik-3milabs Jan 29, 2025
dc6f517
Clean up
erik-3milabs Jan 29, 2025
a3253d8
Clean
erik-3milabs Jan 29, 2025
6b95681
Remove `DOUBLE` requirement
erik-3milabs Jan 29, 2025
b5c9951
Extract restricted xgcd.
erik-3milabs Jan 29, 2025
09b9ee7
Introduce `const_min` and `const_max`
erik-3milabs Jan 29, 2025
fbd39e6
Clean up `summarize`
erik-3milabs Jan 29, 2025
a7f8dae
Clean up `compact`
erik-3milabs Jan 29, 2025
41d32f6
Update `ExtendedInt`
erik-3milabs Jan 29, 2025
e445ceb
Impl `Matrix`
erik-3milabs Jan 29, 2025
30aabf1
Make `new_odd_gcd` constant time
erik-3milabs Jan 29, 2025
51b93f0
Replace `shr` by proper `div_2k`
erik-3milabs Jan 29, 2025
714d608
Remove `ExtendedInt::abs`
erik-3milabs Jan 29, 2025
6d9a3fe
Update `restricted_extended_gcd`
erik-3milabs Jan 29, 2025
32b8e9f
Annotate `new_gcd`
erik-3milabs Jan 29, 2025
cf064a4
Refactor `IntMatrix`
erik-3milabs Jan 29, 2025
e4f4359
Refactor `ExtendedInt` into `ExtendedInt` and `ExtendeUint`
erik-3milabs Jan 29, 2025
4b84597
Fix bug
erik-3milabs Jan 29, 2025
e822db1
Inline `ExtendedUint` and `ExtendedInt`
erik-3milabs Jan 29, 2025
a1ff0a8
Expand `Uint::gcd` benchmarking
erik-3milabs Jan 29, 2025
46211cf
Expand `Uint::new_gcd` testing
erik-3milabs Jan 29, 2025
a824a4d
Annotate `new_gcd.rs`
erik-3milabs Jan 29, 2025
6e76ec9
Prevent matrix overflow; cap `k` at 62
erik-3milabs Jan 30, 2025
64f0821
Make `Int::wrapping_sub` a const function
erik-3milabs Jan 30, 2025
625cc0c
Have new_gcd deal with extreme cases.
erik-3milabs Jan 30, 2025
28284c0
Deprecate `new_inv_mod_odd`
erik-3milabs Jan 30, 2025
0e93f8d
Deprecate `Limb::eq`
erik-3milabs Jan 30, 2025
a8deb20
Fix clippy
erik-3milabs Jan 30, 2025
1012084
Re-enable `Uint` benchmarks
erik-3milabs Jan 30, 2025
b3bab22
Fix
erik-3milabs Jan 30, 2025
4aa0a34
Revert `Int::mul` modifications
erik-3milabs Jan 30, 2025
8b1ec76
Improve testing
erik-3milabs Jan 30, 2025
0ddbf02
Fix doc
erik-3milabs Jan 30, 2025
00c9402
Refactor; move `ExtendedXXX` to separate file
erik-3milabs Jan 31, 2025
ecdd3be
Refactor; move `IntMatrix` to separate file
erik-3milabs Jan 31, 2025
b9e1af2
Remove prefix from `const_*` functions
erik-3milabs Jan 31, 2025
7ab1b86
Rename to `bingcd`
erik-3milabs Jan 31, 2025
6677727
Introduce `odd_bingcd_small`
erik-3milabs Jan 31, 2025
1ae482e
Major code refactor
erik-3milabs Jan 31, 2025
018ecf3
Clarify `used_increments` as `log_upper_bound`
erik-3milabs Jan 31, 2025
1871093
Tweak small/large bingcd threshold
erik-3milabs Jan 31, 2025
1972914
Refactor `IntMatrix`
erik-3milabs Feb 3, 2025
ef08afc
Clean up `restricted_extended_gcd`
erik-3milabs Feb 3, 2025
a74442f
Expand `gcd` benchmarking
erik-3milabs Feb 3, 2025
1a97070
Fix issues
erik-3milabs Feb 3, 2025
4c699d2
Fix `IntMatrix::conditional_swap` bug
erik-3milabs Jan 31, 2025
2fee828
Fix `IntMatrix::conditional_double` bug
erik-3milabs Feb 3, 2025
9781b87
Fix `restricted_extended_gcd` bug
erik-3milabs Feb 3, 2025
39a4e88
Align gcd return values with their type
erik-3milabs Feb 3, 2025
0897439
Remove sneaky swap operation
erik-3milabs Feb 3, 2025
4007347
Expand bingcd testing
erik-3milabs Feb 4, 2025
3f28258
Refactor bingcd test suite
erik-3milabs Feb 4, 2025
76f2e00
Introduce const `Int::checked_mul`
erik-3milabs Jan 31, 2025
29a11af
Implement `Matrix::checked_mul`
erik-3milabs Jan 31, 2025
0015329
Rename `restricted_extended_gcd` as `partial_binxgcd`
erik-3milabs Feb 4, 2025
2b7f5d3
Fix fmt
erik-3milabs Feb 4, 2025
1b7c18e
Introduce `ExtendedInt::checked_add`
erik-3milabs Feb 4, 2025
4fb8c4d
attempt
erik-3milabs Feb 4, 2025
9a941da
Minor optimization; bingcd can always divide b by two; a is always no…
erik-3milabs Feb 4, 2025
d4dbc42
Attempt to fix Bezout coefficients
erik-3milabs Feb 4, 2025
37eef78
Fix bug
erik-3milabs Feb 4, 2025
1cd84a6
Make `binxgcd` constant time
erik-3milabs Feb 5, 2025
21345e9
Introduce xgcd benchmarks
erik-3milabs Feb 5, 2025
4a88f8c
Minor optimization; bingcd can always divide b by two; a is always no…
erik-3milabs Feb 4, 2025
ce20fe2
Extract the `bingcd_step` subroutine.
erik-3milabs Feb 5, 2025
a89a93a
Extract the `binxgcd_step` subroutine.
erik-3milabs Feb 5, 2025
50d5ed0
Fix fmt
erik-3milabs Feb 5, 2025
cd470a8
Make binxgcd work upto Int::MAX
erik-3milabs Feb 6, 2025
dd1d308
Remove `ExtendedInt::checked_add`
erik-3milabs Feb 6, 2025
daa64cb
Fix clippy
erik-3milabs Feb 6, 2025
d1347e3
Improve `bingcd` annotation
erik-3milabs Feb 6, 2025
87d8ee7
Split `optimized_bingcd` in two parts.
erik-3milabs Feb 6, 2025
23a8dd5
Tune `optimized_bingcd` parameters
erik-3milabs Feb 6, 2025
2d3df09
Make `compact` generic in `K`
erik-3milabs Feb 6, 2025
30189d1
Annotate the use of `shl_vartime` and `shr_vartime`
erik-3milabs Feb 6, 2025
2e93021
Take `iterations` out of the `optimized_bingcd_` loop
erik-3milabs Feb 6, 2025
d464a02
Indicate `restricted_extended_gcd` as `_vartime` in `iterations`
erik-3milabs Feb 6, 2025
579d93e
Revert "Remove sneaky swap operation"
erik-3milabs Feb 6, 2025
89d4d29
Annotate `partial_binxgcd_vartime`
erik-3milabs Feb 6, 2025
fc686d1
Fix clippy
erik-3milabs Feb 6, 2025
b782790
Fix docstring `Matrix::conditional_double_bottom_row`
erik-3milabs Feb 7, 2025
859bbb9
Optimize conditional sub operation in `classic_bingcd`
erik-3milabs Feb 7, 2025
6880ac8
Merge branch 'bingcd' into binxgcd
erik-3milabs Feb 7, 2025
909ab91
Fix binxgcd bug
erik-3milabs Feb 7, 2025
3bb5b95
Introduce `classic_binxgcd`
erik-3milabs Feb 7, 2025
4282204
Fix doc
erik-3milabs Feb 7, 2025
8401968
Expand binxgcd functions
erik-3milabs Feb 7, 2025
02ba25b
Introduce `Int::binxgcd`
erik-3milabs Feb 7, 2025
beb46dd
Attempt to get binxgcd to work for even numbers
erik-3milabs Feb 10, 2025
422c1a3
Attempt to fix
erik-3milabs Feb 10, 2025
2e32d45
Fix wrong import
erik-3milabs Feb 12, 2025
d35f814
More binxgcd
erik-3milabs Feb 12, 2025
52ab014
Remove illegal test
erik-3milabs Feb 12, 2025
54ccd69
Fix `NonZero<Int>::binxgcd`
erik-3milabs Feb 12, 2025
c7286fc
Fully functional binxgcd (?)
erik-3milabs Feb 12, 2025
439cde8
Expand bingcd testing
erik-3milabs Feb 12, 2025
b024d61
Simplify bingcd
erik-3milabs Feb 12, 2025
2473cdf
Passes all tests
erik-3milabs Feb 13, 2025
2a0a60b
Fix optimized_binxgcd bug
erik-3milabs Feb 13, 2025
b1f23c5
Improve `partial_binxgcd_vartime`
erik-3milabs Feb 13, 2025
a261f9b
Fix fmt
erik-3milabs Feb 13, 2025
ba61286
Improve `partial_binxgcd_vartime`
erik-3milabs Feb 13, 2025
8726621
Clean up tests
erik-3milabs Feb 13, 2025
31e108b
Add xgcd restriction warnings
erik-3milabs Feb 13, 2025
4e67445
Clean up
erik-3milabs Feb 13, 2025
62a53be
Fmt
erik-3milabs Feb 13, 2025
975b784
Refactor `Int::binxgcd`
erik-3milabs Feb 13, 2025
99940f1
Refactor `NonZero::<Int>::binxgcd`
erik-3milabs Feb 13, 2025
3388908
Refactor `Odd::<Int>::binxgcd`
erik-3milabs Feb 13, 2025
7c17a68
Improve `optimized_bingcd` readability
erik-3milabs Feb 13, 2025
00b3597
Fix typo
erik-3milabs Feb 13, 2025
209b8c2
Fix fmt
erik-3milabs Feb 13, 2025
27c3dd4
Remove superfluous `DOUBLE` const generic.
erik-3milabs Feb 13, 2025
32657bb
Fix ref.
erik-3milabs Feb 13, 2025
b4df88e
Fix fmt
erik-3milabs Feb 13, 2025
5b5c49e
Improvements
erik-3milabs Feb 13, 2025
82be975
Update `drop_extension` to `wrapping_drop_extension`
erik-3milabs Feb 13, 2025
4c16399
Improve readability
erik-3milabs Feb 13, 2025
5bb8677
Replace `IntMatrix::checked_mul_right` with `wrapping_mul_right`
erik-3milabs Feb 14, 2025
4d16027
Move `div_2k_mod_q` ops
erik-3milabs Feb 14, 2025
177aabc
Remove asserts from `IntMatrix::extended_apply_to`
erik-3milabs Feb 14, 2025
28ad399
Fix xgcd benchmarks
erik-3milabs Feb 14, 2025
63f9727
Make `iterations` a constant
erik-3milabs Feb 14, 2025
eb5b1d1
Refactor
erik-3milabs Feb 14, 2025
fd3f61c
Minor `optimized_bingcd_` optimization
erik-3milabs Feb 14, 2025
016d3a8
Introduce `bingcd` for `Int`
erik-3milabs Feb 14, 2025
7664f5f
Fix clippy
erik-3milabs Feb 14, 2025
237b0e0
Move `Odd::BITS` to better spot
erik-3milabs Feb 14, 2025
c3d72fb
Introduce `const MINIMAL_BINGCD_ITERATIONS`
erik-3milabs Feb 14, 2025
81c8c46
Polish bingcd test suite
erik-3milabs Feb 14, 2025
11af836
Polish binxgcd test suite
erik-3milabs Feb 14, 2025
3061a8c
Tweak bingcd threshold
erik-3milabs Feb 14, 2025
58dee9e
Fix assert
erik-3milabs Feb 14, 2025
d2e863f
Optimize xgcd threshold
erik-3milabs Feb 14, 2025
2ab41b0
Test `binxgcd_nz`
erik-3milabs Feb 21, 2025
efc3fa0
Fix fmt
erik-3milabs Feb 21, 2025
d162477
Introduce `extract_bezout_coefficients_vartime`
erik-3milabs Feb 21, 2025
c0fd905
Patch bug
erik-3milabs Feb 21, 2025
a6a9c92
Introduce `extract_quotients`
erik-3milabs Feb 21, 2025
ee4ee4b
Introduce `RawBinXgcdOutput`
erik-3milabs Feb 21, 2025
ac327f0
Introduce `OddBinXgcdOutput` in preparation for quotients
erik-3milabs Feb 21, 2025
4f9a7bb
Test quotients
erik-3milabs Feb 21, 2025
10055e5
Update docs
erik-3milabs Feb 21, 2025
0dee8a0
minimal bezout coefficients
erik-3milabs Feb 21, 2025
1e8a0a3
Refactor `Odd<Int>::Binxgcd`
erik-3milabs Feb 21, 2025
438d3f6
Refactor `NonZero<Int>::Binxgcd`
erik-3milabs Feb 21, 2025
79e6527
Refactor `Int::binxgcd`
erik-3milabs Feb 21, 2025
f0bdb39
Introduce `BinXgcdOutput::minimal_bezout_coefficients`
erik-3milabs Feb 21, 2025
c2df6c0
Clean up `xgcd.rs`
erik-3milabs Feb 21, 2025
7631a24
Fix clippy
erik-3milabs Feb 21, 2025
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
1 change: 0 additions & 1 deletion benches/int.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use std::ops::Div;

use criterion::{black_box, criterion_group, criterion_main, BatchSize, Criterion};
use num_traits::WrappingSub;
use rand_core::OsRng;

use crypto_bigint::{NonZero, Random, I1024, I128, I2048, I256, I4096, I512};
Expand Down
120 changes: 107 additions & 13 deletions benches/uint.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
use criterion::{black_box, criterion_group, criterion_main, BatchSize, Criterion};
use criterion::measurement::WallTime;
use criterion::{
black_box, criterion_group, criterion_main, BatchSize, BenchmarkGroup, BenchmarkId, Criterion,
};
use crypto_bigint::modular::SafeGcdInverter;
use crypto_bigint::{
Limb, NonZero, Odd, Random, RandomBits, RandomMod, Reciprocal, Uint, U1024, U128, U2048, U256,
U4096, U512,
Int, Limb, NonZero, Odd, PrecomputeInverter, Random, RandomBits, RandomMod, Reciprocal, Uint,
U1024, U128, U16384, U192, U2048, U256, U320, U384, U4096, U448, U512, U64, U8192,
};
use rand_chacha::ChaCha8Rng;
use rand_core::{OsRng, RngCore, SeedableRng};
Expand Down Expand Up @@ -302,32 +306,121 @@ fn bench_division(c: &mut Criterion) {
group.finish();
}

fn bench_gcd(c: &mut Criterion) {
let mut group = c.benchmark_group("greatest common divisor");
fn gcd_bench<const LIMBS: usize, const UNSAT_LIMBS: usize>(
g: &mut BenchmarkGroup<WallTime>,
_x: Uint<LIMBS>,
) where
Odd<Uint<LIMBS>>: PrecomputeInverter<Inverter = SafeGcdInverter<LIMBS, UNSAT_LIMBS>>,
{
g.bench_function(BenchmarkId::new("gcd", LIMBS), |b| {
b.iter_batched(
|| {
let f = Uint::<LIMBS>::random(&mut OsRng);
let g = Uint::<LIMBS>::random(&mut OsRng);
(f, g)
},
|(f, g)| black_box(Uint::gcd(&f, &g)),
BatchSize::SmallInput,
)
});
g.bench_function(BenchmarkId::new("bingcd", LIMBS), |b| {
b.iter_batched(
|| {
let f = Uint::<LIMBS>::random(&mut OsRng);
let g = Uint::<LIMBS>::random(&mut OsRng);
(f, g)
},
|(f, g)| black_box(Uint::bingcd(&f, &g)),
BatchSize::SmallInput,
)
});

group.bench_function("gcd, U256", |b| {
g.bench_function(BenchmarkId::new("bingcd_small", LIMBS), |b| {
b.iter_batched(
|| {
let f = Uint::<LIMBS>::random(&mut OsRng)
.bitor(&Uint::ONE)
.to_odd()
.unwrap();
let g = Uint::<LIMBS>::random(&mut OsRng);
(f, g)
},
|(f, g)| black_box(f.classic_bingcd(&g)),
BatchSize::SmallInput,
)
});
g.bench_function(BenchmarkId::new("bingcd_large", LIMBS), |b| {
b.iter_batched(
|| {
let f = U256::random(&mut OsRng);
let g = U256::random(&mut OsRng);
let f = Uint::<LIMBS>::random(&mut OsRng)
.bitor(&Uint::ONE)
.to_odd()
.unwrap();
let g = Uint::<LIMBS>::random(&mut OsRng);
(f, g)
},
|(f, g)| black_box(f.gcd(&g)),
|(f, g)| black_box(f.optimized_bingcd(&g)),
BatchSize::SmallInput,
)
});
}

fn bench_gcd(c: &mut Criterion) {
let mut group = c.benchmark_group("greatest common divisor");

gcd_bench(&mut group, U64::ZERO);
gcd_bench(&mut group, U128::ZERO);
gcd_bench(&mut group, U192::ZERO);
gcd_bench(&mut group, U256::ZERO);
gcd_bench(&mut group, U320::ZERO);
gcd_bench(&mut group, U384::ZERO);
gcd_bench(&mut group, U448::ZERO);
gcd_bench(&mut group, U512::ZERO);
gcd_bench(&mut group, U1024::ZERO);
gcd_bench(&mut group, U2048::ZERO);
gcd_bench(&mut group, U4096::ZERO);
gcd_bench(&mut group, U8192::ZERO);
gcd_bench(&mut group, U16384::ZERO);

group.finish();
}

group.bench_function("gcd_vartime, U256", |b| {
fn xgcd_bench<const LIMBS: usize, const UNSAT_LIMBS: usize>(
g: &mut BenchmarkGroup<WallTime>,
_x: Uint<LIMBS>,
) where
Odd<Uint<LIMBS>>: PrecomputeInverter<Inverter = SafeGcdInverter<LIMBS, UNSAT_LIMBS>>,
{
g.bench_function(BenchmarkId::new("binxgcd", LIMBS), |b| {
b.iter_batched(
|| {
let f = Odd::<U256>::random(&mut OsRng);
let g = U256::random(&mut OsRng);
let modulus = Int::MIN.as_uint().wrapping_add(&Uint::ONE).to_nz().unwrap();
let f = Uint::<LIMBS>::random_mod(&mut OsRng, &modulus).as_int();
let g = Uint::<LIMBS>::random_mod(&mut OsRng, &modulus).as_int();
(f, g)
},
|(f, g)| black_box(f.gcd_vartime(&g)),
|(f, g)| black_box(f.binxgcd(&g)),
BatchSize::SmallInput,
)
});
}

fn bench_xgcd(c: &mut Criterion) {
let mut group = c.benchmark_group("greatest common divisor");

xgcd_bench(&mut group, U64::ZERO);
xgcd_bench(&mut group, U128::ZERO);
xgcd_bench(&mut group, U192::ZERO);
xgcd_bench(&mut group, U256::ZERO);
xgcd_bench(&mut group, U320::ZERO);
xgcd_bench(&mut group, U384::ZERO);
xgcd_bench(&mut group, U448::ZERO);
xgcd_bench(&mut group, U512::ZERO);
xgcd_bench(&mut group, U1024::ZERO);
xgcd_bench(&mut group, U2048::ZERO);
xgcd_bench(&mut group, U4096::ZERO);
xgcd_bench(&mut group, U8192::ZERO);
xgcd_bench(&mut group, U16384::ZERO);

group.finish();
}
Expand Down Expand Up @@ -491,6 +584,7 @@ criterion_group!(
bench_mul,
bench_division,
bench_gcd,
bench_xgcd,
bench_shl,
bench_shr,
bench_inv_mod,
Expand Down
42 changes: 42 additions & 0 deletions src/const_choice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,20 @@ impl<const LIMBS: usize> ConstCtOption<(Uint<LIMBS>, Uint<LIMBS>)> {
}
}

impl<const LIMBS: usize> ConstCtOption<(Uint<LIMBS>, ConstChoice)> {
/// Returns the contained value, consuming the `self` value.
///
/// # Panics
///
/// Panics if the value is none with a custom panic message provided by
/// `msg`.
#[inline]
pub const fn expect(self, msg: &str) -> (Uint<LIMBS>, ConstChoice) {
assert!(self.is_some.is_true_vartime(), "{}", msg);
self.value
}
}

impl<const LIMBS: usize> ConstCtOption<NonZero<Uint<LIMBS>>> {
/// Returns the contained value, consuming the `self` value.
///
Expand Down Expand Up @@ -461,6 +475,34 @@ impl<const LIMBS: usize> ConstCtOption<Int<LIMBS>> {
}
}

impl<const LIMBS: usize> ConstCtOption<NonZero<Int<LIMBS>>> {
/// Returns the contained value, consuming the `self` value.
///
/// # Panics
///
/// Panics if the value is none with a custom panic message provided by
/// `msg`.
#[inline]
pub const fn expect(self, msg: &str) -> NonZero<Int<LIMBS>> {
assert!(self.is_some.is_true_vartime(), "{}", msg);
self.value
}
}

impl<const LIMBS: usize> ConstCtOption<Odd<Int<LIMBS>>> {
/// Returns the contained value, consuming the `self` value.
///
/// # Panics
///
/// Panics if the value is none with a custom panic message provided by
/// `msg`.
#[inline]
pub const fn expect(self, msg: &str) -> Odd<Int<LIMBS>> {
assert!(self.is_some.is_true_vartime(), "{}", msg);
self.value
}
}

impl ConstCtOption<NonZero<Limb>> {
/// Returns the contained value, consuming the `self` value.
///
Expand Down
3 changes: 2 additions & 1 deletion src/int.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use crate::Encoding;
use crate::{Bounded, ConstChoice, ConstCtOption, Constants, Limb, NonZero, Odd, Uint, Word};

mod add;
mod bingcd;
mod bit_and;
mod bit_not;
mod bit_or;
Expand Down Expand Up @@ -119,7 +120,7 @@ impl<const LIMBS: usize> Int<LIMBS> {
}

/// Borrow the limbs of this [`Int`] mutably.
pub fn as_limbs_mut(&mut self) -> &mut [Limb; LIMBS] {
pub const fn as_limbs_mut(&mut self) -> &mut [Limb; LIMBS] {
self.0.as_limbs_mut()
}

Expand Down
Loading