Skip to content

Commit ad2e286

Browse files
committed
add Zero impl for BigInt
Signed-off-by: Andrew Tretyakov <42178850+0xAndoroid@users.noreply.github.com>
1 parent 7b02a67 commit ad2e286

File tree

4 files changed

+59
-32
lines changed

4 files changed

+59
-32
lines changed

ff-asm/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ pub fn x86_64_asm_mul(input: TokenStream) -> TokenStream {
5959
} else {
6060
panic!("The number of limbs must be a literal");
6161
};
62+
#[allow(clippy::redundant_comparisons)]
6263
if num_limbs <= 6 && num_limbs <= 3 * MAX_REGS {
6364
let impl_block = generate_impl(num_limbs, true);
6465

@@ -110,6 +111,7 @@ pub fn x86_64_asm_square(input: TokenStream) -> TokenStream {
110111
} else {
111112
panic!("The number of limbs must be a literal");
112113
};
114+
#[allow(clippy::redundant_comparisons)]
113115
if num_limbs <= 6 && num_limbs <= 3 * MAX_REGS {
114116
let impl_block = generate_impl(num_limbs, false);
115117

ff/src/biginteger/mod.rs

Lines changed: 43 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,16 @@ use ark_std::{
1414
fmt::{Debug, Display, UpperHex},
1515
io::{Read, Write},
1616
ops::{
17-
BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not, Shl, ShlAssign, Shr,
18-
ShrAssign, Add, Sub, AddAssign, SubAssign,
17+
Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not, Shl,
18+
ShlAssign, Shr, ShrAssign, Sub, SubAssign,
1919
},
2020
rand::{
2121
distributions::{Distribution, Standard},
2222
Rng,
2323
},
2424
str::FromStr,
2525
vec::*,
26+
Zero,
2627
};
2728
use num_bigint::BigUint;
2829
use zeroize::Zeroize;
@@ -346,13 +347,19 @@ impl<const N: usize> BigInt<N> {
346347
#[inline]
347348
#[unroll_for_loops(9)]
348349
pub fn add_assign_trunc<const M: usize>(&mut self, other: &BigInt<M>) {
349-
debug_assert!(M <= N, "add_assign_trunc: right operand wider than self width N");
350+
debug_assert!(
351+
M <= N,
352+
"add_assign_trunc: right operand wider than self width N"
353+
);
350354
let mut carry = 0u64;
351355
for i in 0..N {
352356
let rhs = if i < M { other.0[i] } else { 0 };
353357
self.0[i] = adc!(self.0[i], rhs, &mut carry);
354358
}
355-
debug_assert!(carry == 0, "add_assign_trunc overflow: carry beyond N limbs");
359+
debug_assert!(
360+
carry == 0,
361+
"add_assign_trunc overflow: carry beyond N limbs"
362+
);
356363
}
357364

358365
/// Truncated-width subtraction that mutates self: self -= other, keeping N limbs (self's width).
@@ -363,13 +370,19 @@ impl<const N: usize> BigInt<N> {
363370
#[inline]
364371
#[unroll_for_loops(9)]
365372
pub fn sub_assign_trunc<const M: usize>(&mut self, other: &BigInt<M>) {
366-
debug_assert!(M <= N, "sub_assign_trunc: right operand wider than self width N");
373+
debug_assert!(
374+
M <= N,
375+
"sub_assign_trunc: right operand wider than self width N"
376+
);
367377
let mut borrow = 0u64;
368378
for i in 0..N {
369379
let rhs = if i < M { other.0[i] } else { 0 };
370380
self.0[i] = sbb!(self.0[i], rhs, &mut borrow);
371381
}
372-
debug_assert!(borrow == 0, "sub_assign_trunc underflow: borrow beyond N limbs");
382+
debug_assert!(
383+
borrow == 0,
384+
"sub_assign_trunc underflow: borrow beyond N limbs"
385+
);
373386
}
374387

375388
/// Truncated-width multiplication that mutates self: self = (self * other) mod 2^(64*N).
@@ -378,12 +391,16 @@ impl<const N: usize> BigInt<N> {
378391
pub fn mul_assign_trunc<const M: usize>(&mut self, other: &BigInt<M>) {
379392
// Fast paths
380393
if self.is_zero() || other.is_zero() {
381-
for i in 0..N { self.0[i] = 0; }
394+
for i in 0..N {
395+
self.0[i] = 0;
396+
}
382397
return;
383398
}
384399
let left = *self; // snapshot original multiplicand
385-
// zero self to use as accumulator buffer
386-
for i in 0..N { self.0[i] = 0; }
400+
// zero self to use as accumulator buffer
401+
for i in 0..N {
402+
self.0[i] = 0;
403+
}
387404
// Accumulate left * other directly into self within width N; propagate carries within N
388405
left.fm_limbs_into::<M, N>(&other.0, self, true);
389406
}
@@ -512,14 +529,29 @@ impl<const N: usize> BigInt<N> {
512529
/// Debug-asserts that M <= N.
513530
#[inline]
514531
pub fn zero_extend_from<const M: usize>(smaller: &BigInt<M>) -> BigInt<N> {
515-
debug_assert!(M <= N, "cannot zero-extend: source has more limbs than destination");
532+
debug_assert!(
533+
M <= N,
534+
"cannot zero-extend: source has more limbs than destination"
535+
);
516536
let mut limbs = [0u64; N];
517537
let copy_len = if M < N { M } else { N };
518538
limbs[..copy_len].copy_from_slice(&smaller.0[..copy_len]);
519539
BigInt::<N>(limbs)
520540
}
521541
}
522542

543+
impl<const N: usize> Zero for BigInt<N> {
544+
#[inline]
545+
fn zero() -> Self {
546+
Self::zero()
547+
}
548+
549+
#[inline]
550+
fn is_zero(&self) -> bool {
551+
self.0.iter().all(|&limb| limb == 0)
552+
}
553+
}
554+
523555
impl<const N: usize> From<[u64; N]> for BigInt<N> {
524556
fn from(limbs: [u64; N]) -> Self {
525557
BigInt(limbs)
@@ -795,11 +827,6 @@ impl<const N: usize> BigInteger for BigInt<N> {
795827
!self.is_odd()
796828
}
797829

798-
#[inline]
799-
fn is_zero(&self) -> bool {
800-
self.0.iter().all(|&e| e == 0)
801-
}
802-
803830
#[inline]
804831
fn num_bits(&self) -> u32 {
805832
let mut ret = N as u32 * 64;
@@ -1308,6 +1335,7 @@ pub trait BigInteger:
13081335
+ 'static
13091336
+ UniformRand
13101337
+ Zeroize
1338+
+ Zero
13111339
+ AsMut<[u64]>
13121340
+ AsRef<[u64]>
13131341
+ From<u128>
@@ -1572,17 +1600,6 @@ pub trait BigInteger:
15721600
/// ```
15731601
fn is_even(&self) -> bool;
15741602

1575-
/// Returns true iff this number is zero.
1576-
/// # Example
1577-
///
1578-
/// ```
1579-
/// use ark_ff::{biginteger::BigInteger64 as B, BigInteger as _};
1580-
///
1581-
/// let mut zero = B::from(0u64);
1582-
/// assert!(zero.is_zero());
1583-
/// ```
1584-
fn is_zero(&self) -> bool;
1585-
15861603
/// Compute the minimum number of bits needed to encode this number.
15871604
/// # Example
15881605
/// ```

ff/src/biginteger/signed.rs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use ark_serialize::{
44
CanonicalDeserialize, CanonicalSerialize, Compress, Read, SerializationError, Valid, Validate,
55
Write,
66
};
7+
use ark_std::Zero;
78
use core::cmp::Ordering;
89
use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
910

@@ -27,6 +28,18 @@ impl<const N: usize> Default for SignedBigInt<N> {
2728
}
2829
}
2930

31+
impl<const N: usize> Zero for SignedBigInt<N> {
32+
#[inline]
33+
fn zero() -> Self {
34+
Self::zero()
35+
}
36+
37+
#[inline]
38+
fn is_zero(&self) -> bool {
39+
self.magnitude.is_zero()
40+
}
41+
}
42+
3043
pub type S64 = SignedBigInt<1>;
3144
pub type S128 = SignedBigInt<2>;
3245
pub type S192 = SignedBigInt<3>;
@@ -87,12 +100,6 @@ impl<const N: usize> SignedBigInt<N> {
87100
}
88101
}
89102

90-
/// Return true if magnitude is zero (sign is not considered).
91-
#[inline]
92-
pub fn is_zero(&self) -> bool {
93-
self.magnitude.is_zero()
94-
}
95-
96103
/// Borrow the magnitude (absolute value).
97104
#[inline]
98105
pub fn as_magnitude(&self) -> &BigInt<N> {

ff/src/biginteger/tests.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ pub mod tests {
55
biginteger::{BigInteger, SignedBigInt},
66
UniformRand,
77
};
8+
use ark_std::Zero;
89
use num_bigint::BigUint;
910

1011
// Test elementary math operations for BigInteger.

0 commit comments

Comments
 (0)