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

Int - two's complement #695

Merged
merged 88 commits into from
Nov 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
88 commits
Select commit Hold shift + click to select a range
4bc098c
Create `Int` core struct
erik-3milabs Sep 23, 2024
31e3577
Introduce `Int::add`
erik-3milabs Oct 15, 2024
cfb1ec4
Introduce `Int::mul`
erik-3milabs Oct 15, 2024
01a07f7
Introduce `Int::div`
erik-3milabs Oct 15, 2024
000c007
Implement `Div` for `Int`
erik-3milabs Oct 16, 2024
39b08bb
Clean up
erik-3milabs Oct 16, 2024
7b0fbab
Implement `Sub` for `Int`
erik-3milabs Oct 16, 2024
66b4639
Fix typo in `Uint::sub`
erik-3milabs Oct 16, 2024
02d9d5c
Implement `WrappingSub` for `Int`
erik-3milabs Oct 16, 2024
e614cd5
Implement `cmp` for `Int`
erik-3milabs Oct 16, 2024
da13a4f
Implement `rand` for `Int`
erik-3milabs Oct 16, 2024
69b7236
Implement `expand` for `Int`
erik-3milabs Oct 16, 2024
20cdb5f
Update `Int::encoding`
erik-3milabs Oct 16, 2024
4ab45f5
Add `Int` aliases
erik-3milabs Oct 16, 2024
57000c5
Impl some more `Int` traits
erik-3milabs Oct 16, 2024
e29e425
Add `Int` benchmarks
erik-3milabs Oct 16, 2024
869a8e7
Remove superfluous tests
erik-3milabs Oct 16, 2024
f6ef7ed
Fix fmt
erik-3milabs Oct 16, 2024
c610b08
Introduce `Int::new_from_uint`
erik-3milabs Oct 16, 2024
0669c1b
Feature lock `Int::rand`
erik-3milabs Oct 16, 2024
d7029e2
Add `Int::cmp` tests
erik-3milabs Oct 16, 2024
a653375
Fix `Int::expand` bug
erik-3milabs Oct 16, 2024
57f65f8
Attach `Int` benchmark
erik-3milabs Oct 16, 2024
b23483d
Improve `Int` benchmarks
erik-3milabs Oct 16, 2024
30b4676
Speed up `Int::negate_unsafe`
erik-3milabs Oct 16, 2024
580e0a5
Improve `Int::sign_bit`
erik-3milabs Oct 16, 2024
220d329
Remove useless conversion
erik-3milabs Oct 16, 2024
c762307
Fix `Int::as_uint` return type
erik-3milabs Oct 17, 2024
98075bb
Rename `Uint::wrapping_negc` to `wrapping_neg_with_carry`
erik-3milabs Oct 17, 2024
a064fea
Make `Int::sign_bit` `const`
erik-3milabs Oct 17, 2024
8bcf5ef
Rename `Int::sign_bit` to `Int::is_negative`
erik-3milabs Oct 17, 2024
8e598b6
Move `Int`'s negation operations to `int::neg`
erik-3milabs Oct 17, 2024
22582a2
Expand `int::neg` tests
erik-3milabs Oct 17, 2024
74b377b
Some cleaning up
erik-3milabs Oct 17, 2024
8fad5d4
Introduce `ConstChoice::as_word_mask`
erik-3milabs Oct 17, 2024
d8a6a91
Introduce `Uint::wrapping_neg_if`
erik-3milabs Oct 17, 2024
2033850
Refactor `Int::negate_if_unsafe`, make `split_mul` `const` in the pro…
erik-3milabs Oct 17, 2024
cff448c
Make `Int::new_from_sign_and_magnitude` `const`
erik-3milabs Oct 17, 2024
d326432
Make `Int::checked_add_internal` `const`
erik-3milabs Oct 17, 2024
cb9967f
Rename `Int::checked_add_internal` to `Int::checked_add`
erik-3milabs Oct 17, 2024
0a7155b
Refactor `Int::expand` to `Int::resize`
erik-3milabs Oct 17, 2024
9d7b1d9
Rename `Uint::wrapping_neg_with_carry` to `Uint::negc`
erik-3milabs Oct 17, 2024
93f9a45
Rename `Int`'s negation functions.
erik-3milabs Oct 17, 2024
0f2009f
Rename `Int::is_minimal` to `Int::is_min`
erik-3milabs Oct 17, 2024
e182faf
Rename `Int::is_maximal` to `Int::is_max`
erik-3milabs Oct 17, 2024
2fa8bc1
Rename `Int::SIGN_BIT_MASK` to `Int::SIGN_MASK`
erik-3milabs Oct 17, 2024
6050c7e
Satisfy clippy
erik-3milabs Oct 17, 2024
e9ad737
Fix carry on `Uint::negc`
erik-3milabs Oct 17, 2024
6bffaed
Impl serde for `Int`
erik-3milabs Oct 17, 2024
33b94cf
Fix serde for `Int`
erik-3milabs Oct 17, 2024
7c70799
Fix serde for `Int` attempt 2
erik-3milabs Oct 17, 2024
c7642e5
Implement `Int::from`
erik-3milabs Oct 18, 2024
080c6c8
Fix `Int::resize` bug
erik-3milabs Oct 18, 2024
d53a0ef
Fix `Int::from`
erik-3milabs Oct 18, 2024
8947396
Impl `Int::div_floor` and `Int::div_mod_floor`
erik-3milabs Oct 18, 2024
35fe35d
Fix problems
erik-3milabs Oct 18, 2024
8ec01c3
Attempt to fix from_i64 for x86 platform
erik-3milabs Oct 18, 2024
3378cbb
Attempt #2
erik-3milabs Oct 18, 2024
d2e5692
Introduce `lte` and `gte` for `Uint`
erik-3milabs Oct 21, 2024
6e04109
Introduce `lte` and `gte` for `Int`
erik-3milabs Oct 21, 2024
34290de
Update `Int::div_rem`
erik-3milabs Oct 21, 2024
cb67265
Add widening_mul, group absolute value operations, reformat.
lleoha Oct 17, 2024
3773bb7
bench
lleoha Oct 18, 2024
e218afa
Address review remarks, add benchmarks.
lleoha Oct 18, 2024
e61537f
Update src/int/sign.rs
erik-3milabs Oct 21, 2024
2624a8a
Refine.
lleoha Oct 21, 2024
23f1f4a
reformat
lleoha Oct 21, 2024
c8edd3d
Merge pull request #1 from lleoha/widening-mul
erik-3milabs Oct 22, 2024
6543016
Deprecate `Uint::gte`
erik-3milabs Oct 22, 2024
51f269a
Clean `Int::div`
erik-3milabs Oct 22, 2024
fd85876
Clean .gitignore
erik-3milabs Oct 28, 2024
62bd676
Update `cmp` comments
erik-3milabs Oct 28, 2024
62764a7
Remove `dead_code` in `int::cmp`
erik-3milabs Oct 28, 2024
badae25
Fix `int::div::div_rem_base` docstring
erik-3milabs Oct 28, 2024
76be4dc
Introduce `NonZero::<Int<LIMBS>>::abs_sign`
erik-3milabs Oct 28, 2024
2260fa7
Rename `negc` to `carrying_neg`
erik-3milabs Oct 28, 2024
dd91617
Deprecate more `int::cmp` dead code.
erik-3milabs Oct 28, 2024
e53a261
Remove dead `int::cmp` tests
erik-3milabs Oct 28, 2024
7c3ae9e
Simplify `uint::wrapping_neg_if` implementation, preventing potential…
erik-3milabs Oct 28, 2024
0be0e57
Refactor `int::new_from_uint`; make it crate-restricted.
erik-3milabs Oct 28, 2024
92cf876
Make `Int::as_uint` return a ref.
erik-3milabs Oct 28, 2024
2c8af9c
Fix broken tests
erik-3milabs Oct 28, 2024
84466dd
yank `Int::Encoding`; save it for a later PR
erik-3milabs Oct 29, 2024
7a667f6
Fix clippy
erik-3milabs Oct 29, 2024
0067207
Add missing type
erik-3milabs Oct 29, 2024
7688826
Fix `carrying_neg` docstring
erik-3milabs Oct 29, 2024
0719d31
Make `Int::neg` const
erik-3milabs Oct 29, 2024
223a79e
Update negation operations
erik-3milabs Oct 30, 2024
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
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,7 @@ harness = false
[[bench]]
name = "uint"
harness = false

[[bench]]
name = "int"
harness = false
344 changes: 344 additions & 0 deletions benches/int.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,344 @@
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};

fn bench_mul(c: &mut Criterion) {
let mut group = c.benchmark_group("wrapping ops");

group.bench_function("split_mul, I128xI128", |b| {
b.iter_batched(
|| (I256::random(&mut OsRng), I256::random(&mut OsRng)),
|(x, y)| black_box(x.split_mul(&y)),
BatchSize::SmallInput,
)
});

group.bench_function("split_mul, I256xI256", |b| {
b.iter_batched(
|| (I256::random(&mut OsRng), I256::random(&mut OsRng)),
|(x, y)| black_box(x.split_mul(&y)),
BatchSize::SmallInput,
)
});

group.bench_function("split_mul, I512xI512", |b| {
b.iter_batched(
|| (I512::random(&mut OsRng), I512::random(&mut OsRng)),
|(x, y)| black_box(x.split_mul(&y)),
BatchSize::SmallInput,
)
});

group.bench_function("split_mul, I1024xI1024", |b| {
b.iter_batched(
|| (I1024::random(&mut OsRng), I1024::random(&mut OsRng)),
|(x, y)| black_box(x.split_mul(&y)),
BatchSize::SmallInput,
)
});

group.bench_function("split_mul, I2048xI2048", |b| {
b.iter_batched(
|| (I2048::random(&mut OsRng), I2048::random(&mut OsRng)),
|(x, y)| black_box(x.split_mul(&y)),
BatchSize::SmallInput,
)
});

group.bench_function("split_mul, I4096xI4096", |b| {
b.iter_batched(
|| (I4096::random(&mut OsRng), I4096::random(&mut OsRng)),
|(x, y)| black_box(x.split_mul(&y)),
BatchSize::SmallInput,
)
});
}

fn bench_widening_mul(c: &mut Criterion) {
let mut group = c.benchmark_group("widening ops");

group.bench_function("widening_mul, I128xI128", |b| {
b.iter_batched(
|| (I128::random(&mut OsRng), I128::random(&mut OsRng)),
|(x, y)| black_box(x.widening_mul(&y)),
BatchSize::SmallInput,
)
});

group.bench_function("widening_mul, I256xI256", |b| {
b.iter_batched(
|| (I256::random(&mut OsRng), I256::random(&mut OsRng)),
|(x, y)| black_box(x.widening_mul(&y)),
BatchSize::SmallInput,
)
});

group.bench_function("widening_mul, I512xI512", |b| {
b.iter_batched(
|| (I512::random(&mut OsRng), I512::random(&mut OsRng)),
|(x, y)| black_box(x.widening_mul(&y)),
BatchSize::SmallInput,
)
});

group.bench_function("widening_mul, I1024xI1024", |b| {
b.iter_batched(
|| (I1024::random(&mut OsRng), I1024::random(&mut OsRng)),
|(x, y)| black_box(x.widening_mul(&y)),
BatchSize::SmallInput,
)
});

group.bench_function("widening_mul, I2048xI2048", |b| {
b.iter_batched(
|| (I2048::random(&mut OsRng), I2048::random(&mut OsRng)),
|(x, y)| black_box(x.widening_mul(&y)),
BatchSize::SmallInput,
)
});

group.bench_function("widening_mul, I4096xI4096", |b| {
b.iter_batched(
|| (I4096::random(&mut OsRng), I4096::random(&mut OsRng)),
|(x, y)| black_box(x.widening_mul(&y)),
BatchSize::SmallInput,
)
});
}

fn bench_div(c: &mut Criterion) {
let mut group = c.benchmark_group("wrapping ops");

group.bench_function("div, I256/I128, full size", |b| {
b.iter_batched(
|| {
let x = I256::random(&mut OsRng);
let y = I128::random(&mut OsRng).resize::<{ I256::LIMBS }>();
(x, NonZero::new(y).unwrap())
},
|(x, y)| black_box(x.div(&y)),
BatchSize::SmallInput,
)
});

group.bench_function("div, I512/I256, full size", |b| {
b.iter_batched(
|| {
let x = I512::random(&mut OsRng);
let y = I256::random(&mut OsRng).resize::<{ I512::LIMBS }>();
(x, NonZero::new(y).unwrap())
},
|(x, y)| black_box(x.div(&y)),
BatchSize::SmallInput,
)
});

group.bench_function("div, I1024/I512, full size", |b| {
b.iter_batched(
|| {
let x = I1024::random(&mut OsRng);
let y = I512::random(&mut OsRng).resize::<{ I1024::LIMBS }>();
(x, NonZero::new(y).unwrap())
},
|(x, y)| black_box(x.div(&y)),
BatchSize::SmallInput,
)
});

group.bench_function("div, I2048/I1024, full size", |b| {
b.iter_batched(
|| {
let x = I2048::random(&mut OsRng);
let y = I1024::random(&mut OsRng).resize::<{ I2048::LIMBS }>();
(x, NonZero::new(y).unwrap())
},
|(x, y)| black_box(x.div(&y)),
BatchSize::SmallInput,
)
});

group.bench_function("div, I4096/I2048, full size", |b| {
b.iter_batched(
|| {
let x = I4096::random(&mut OsRng);
let y = I2048::random(&mut OsRng).resize::<{ I4096::LIMBS }>();
(x, NonZero::new(y).unwrap())
},
|(x, y)| black_box(x.div(&y)),
BatchSize::SmallInput,
)
});

group.finish();
}

fn bench_add(c: &mut Criterion) {
let mut group = c.benchmark_group("wrapping ops");

group.bench_function("add, I128+I128", |b| {
b.iter_batched(
|| {
let x = I128::random(&mut OsRng);
let y = I128::random(&mut OsRng);
(x, y)
},
|(x, y)| black_box(x.wrapping_add(&y)),
BatchSize::SmallInput,
)
});

group.bench_function("add, I256+I256", |b| {
b.iter_batched(
|| {
let x = I256::random(&mut OsRng);
let y = I256::random(&mut OsRng);
(x, y)
},
|(x, y)| black_box(x.wrapping_add(&y)),
BatchSize::SmallInput,
)
});

group.bench_function("add, I512+I512", |b| {
b.iter_batched(
|| {
let x = I512::random(&mut OsRng);
let y = I512::random(&mut OsRng);
(x, y)
},
|(x, y)| black_box(x.wrapping_add(&y)),
BatchSize::SmallInput,
)
});

group.bench_function("add, I1024+I1024", |b| {
b.iter_batched(
|| {
let x = I1024::random(&mut OsRng);
let y = I1024::random(&mut OsRng);
(x, y)
},
|(x, y)| black_box(x.wrapping_add(&y)),
BatchSize::SmallInput,
)
});

group.bench_function("add, I2048+I2048", |b| {
b.iter_batched(
|| {
let x = I2048::random(&mut OsRng);
let y = I2048::random(&mut OsRng);
(x, y)
},
|(x, y)| black_box(x.wrapping_add(&y)),
BatchSize::SmallInput,
)
});

group.bench_function("add, I4096+I4096", |b| {
b.iter_batched(
|| {
let x = I4096::random(&mut OsRng);
let y = I4096::random(&mut OsRng);
(x, y)
},
|(x, y)| black_box(x.wrapping_add(&y)),
BatchSize::SmallInput,
)
});

group.finish();
}

fn bench_sub(c: &mut Criterion) {
let mut group = c.benchmark_group("wrapping ops");

group.bench_function("sub, I128-I128", |b| {
b.iter_batched(
|| {
let x = I128::random(&mut OsRng);
let y = I128::random(&mut OsRng);
(x, y)
},
|(x, y)| black_box(x.wrapping_sub(&y)),
BatchSize::SmallInput,
)
});

group.bench_function("sub, I256-I256", |b| {
b.iter_batched(
|| {
let x = I256::random(&mut OsRng);
let y = I256::random(&mut OsRng);
(x, y)
},
|(x, y)| black_box(x.wrapping_sub(&y)),
BatchSize::SmallInput,
)
});

group.bench_function("sub, I512-I512", |b| {
b.iter_batched(
|| {
let x = I512::random(&mut OsRng);
let y = I512::random(&mut OsRng);
(x, y)
},
|(x, y)| black_box(x.wrapping_sub(&y)),
BatchSize::SmallInput,
)
});

group.bench_function("sub, I1024-I1024", |b| {
b.iter_batched(
|| {
let x = I1024::random(&mut OsRng);
let y = I1024::random(&mut OsRng);
(x, y)
},
|(x, y)| black_box(x.wrapping_sub(&y)),
BatchSize::SmallInput,
)
});

group.bench_function("sub, I2048-I2048", |b| {
b.iter_batched(
|| {
let x = I2048::random(&mut OsRng);
let y = I2048::random(&mut OsRng);
(x, y)
},
|(x, y)| black_box(x.wrapping_sub(&y)),
BatchSize::SmallInput,
)
});

group.bench_function("sub, I4096-I4096", |b| {
b.iter_batched(
|| {
let x = I4096::random(&mut OsRng);
let y = I4096::random(&mut OsRng);
(x, y)
},
|(x, y)| black_box(x.wrapping_sub(&y)),
BatchSize::SmallInput,
)
});

group.finish();
}

criterion_group!(
benches,
bench_mul,
bench_widening_mul,
bench_div,
bench_add,
bench_sub,
);

criterion_main!(benches);
20 changes: 19 additions & 1 deletion src/const_choice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@ impl ConstChoice {
Self(value.wrapping_neg())
}

/// Returns the truthy value if the most significant bit of `value` is `1`,
/// and the falsy value if it equals `0`.
#[inline]
pub(crate) const fn from_word_msb(value: Word) -> Self {
Self::from_word_lsb(value >> (Word::BITS - 1))
}

/// Returns the truthy value if `value == 1`, and the falsy value if `value == 0`.
/// Panics for other values.
#[inline]
Expand Down Expand Up @@ -187,6 +194,16 @@ impl ConstChoice {
Self(self.0 ^ other.0)
}

#[inline]
pub(crate) const fn ne(&self, other: Self) -> Self {
Self::xor(self, other)
}

#[inline]
pub(crate) const fn eq(&self, other: Self) -> Self {
Self::ne(self, other).not()
}

/// Return `b` if `self` is truthy, otherwise return `a`.
#[inline]
pub(crate) const fn select_word(&self, a: Word, b: Word) -> Word {
Expand Down Expand Up @@ -450,9 +467,10 @@ impl<const SAT_LIMBS: usize, const UNSAT_LIMBS: usize>

#[cfg(test)]
mod tests {
use super::ConstChoice;
use crate::{WideWord, Word};

use super::ConstChoice;

#[test]
fn from_u64_lsb() {
assert_eq!(ConstChoice::from_u64_lsb(0), ConstChoice::FALSE);
Expand Down
Loading