From b01b63bdab86345f57f9ef55e569f890f1b0d9e2 Mon Sep 17 00:00:00 2001 From: Balazs Komuves Date: Fri, 30 Jan 2026 03:04:16 +0100 Subject: [PATCH] implement Zero and One trait abstractions --- src/bin/testmain.rs | 4 ++++ src/bn254/bigint.rs | 32 ++++++++++++++++++++++++++++++++ src/bn254/field.rs | 36 +++++++++++++++++++++++++++++++++--- src/bn254/mod.rs | 1 + src/bn254/montgomery.rs | 30 ++++++++++++++++++++++++++++++ src/bn254/test/bigint.rs | 17 ++++++++++++++--- src/bn254/traits.rs | 13 +++++++++++++ 7 files changed, 127 insertions(+), 6 deletions(-) create mode 100644 src/bn254/traits.rs diff --git a/src/bin/testmain.rs b/src/bin/testmain.rs index 488ebb1..1de87c6 100644 --- a/src/bin/testmain.rs +++ b/src/bin/testmain.rs @@ -7,6 +7,7 @@ use std::time::Instant; use std::ops::{RangeFull}; use std::random::{Distribution,DefaultRandomSource,random}; +use rust_poseidon_bn254_pure::bn254::traits::*; use rust_poseidon_bn254_pure::bn254::bigint::*; use rust_poseidon_bn254_pure::bn254::constant::*; use rust_poseidon_bn254_pure::bn254::montgomery::*; @@ -236,5 +237,8 @@ fn main() { let out4 = poseidon::hash4( Felt::from_u32(1) , Felt::from_u32(2) , Felt::from_u32(3) , Felt::from_u32(4) ); println!("compress(4) = {}", Felt::to_decimal_string(out4) ); + //---------------------------------------------------------------------------- + + println!("{}" , Mont::one() == Mont::convert_from_u32(1) ); } diff --git a/src/bn254/bigint.rs b/src/bn254/bigint.rs index b02bc3f..76900a4 100644 --- a/src/bn254/bigint.rs +++ b/src/bn254/bigint.rs @@ -17,6 +17,7 @@ use std::random::{RandomSource,Distribution}; use unroll::unroll_for_loops; +use crate::bn254::traits::*; use crate::bn254::platform::*; use crate::bn254::constant::{PRIME_ARRAY}; @@ -73,6 +74,19 @@ impl Ord for BigInt { fn cmp(&self, other: &Self) -> Ordering { BigInt::cmp(*self, *other) } } +//-------------------------------------- +// (non-standard ones, too...) + +impl Zero for BigInt { + fn zero() -> Self { BigInt::zero() } + fn is_zero(x: Self) -> bool { BigInt::is_zero(x) } +} + +impl One for BigInt { + fn one() -> Self { BigInt::one() } + fn is_one(x: Self) -> bool { BigInt::is_one(x) } +} + //------------------------------------------------------------------------------ // conversion traits @@ -210,6 +224,10 @@ impl BigInt { BigInt([0; N]) } + pub fn one() -> BigInt { + BigInt::from_u32(1) + } + pub fn from_u32(x: u32) -> BigInt { let mut xs = [0; N]; xs[0] = x; @@ -223,6 +241,20 @@ impl BigInt { big.0.iter().all(|&x| x == 0) } + pub fn is_one(big: BigInt) -> bool { + let limbs: [u32; N] = big.0; + let mut ok: bool = limbs[0] == 1; + if ok { + for i in 1..N { + if limbs[i] != 0 { + ok = false; + break; + } + } + } + ok + } + pub fn cmp(big1: BigInt, big2: BigInt) -> Ordering { let mut res : Ordering = Ordering::Equal; for i in (0..N).rev() { diff --git a/src/bn254/field.rs b/src/bn254/field.rs index a38a834..06aab21 100644 --- a/src/bn254/field.rs +++ b/src/bn254/field.rs @@ -14,6 +14,7 @@ use std::ops::{Neg,Add,Sub,Mul,RangeFull}; use std::random::{RandomSource,Distribution}; +use crate::bn254::traits::*; use crate::bn254::bigint::*; use crate::bn254::constant::*; use crate::bn254::montgomery::*; @@ -63,6 +64,19 @@ impl Mul for Felt { fn mul(self, other: Self) -> Self { Felt::mul(self, other) } } +//-------------------------------------- +// (non-standard ones, too...) + +impl Zero for Felt { + fn zero() -> Self { Felt::zero() } + fn is_zero(x: Self) -> bool { Felt::is_zero(x) } +} + +impl One for Felt { + fn one() -> Self { Felt::one() } + fn is_one(x: Self) -> bool { Felt::is_one(x) } +} + //------------------------------------------------------------------------------ // conversion traits @@ -111,10 +125,16 @@ impl Felt { felt.0 } + #[inline(always)] pub const fn unsafe_make( xs: [u32; 8] ) -> Felt { Felt(BigInt::from_limbs(xs)) } + #[inline(always)] + pub fn from_u32(x: u32) -> Felt { + Felt(BigInt::from_u32(x)) + } + pub fn checked_make( xs: [u32; 8] ) -> Felt { let big: Big = BigInt::make(xs); if BigInt::is_lt_prime(big) { @@ -178,16 +198,26 @@ impl Felt { } //------------------------------------ - // basic operations pub fn zero() -> Felt { Felt(BigInt::zero()) } - pub fn from_u32(x: u32) -> Felt { - Felt(BigInt::from_u32(x)) + pub fn one() -> Felt { + Felt(BigInt::one()) } + pub fn is_zero(x: Felt) -> bool { + BigInt::is_zero(x.0) + } + + pub fn is_one(x: Felt) -> bool { + BigInt::is_one(x.0) + } + + //------------------------------------ + // basic operations + pub fn neg(fld: Felt) -> Felt { if BigInt::is_zero(fld.0) { Felt::zero() diff --git a/src/bn254/mod.rs b/src/bn254/mod.rs index 1e0841c..4942ff8 100644 --- a/src/bn254/mod.rs +++ b/src/bn254/mod.rs @@ -1,6 +1,7 @@ mod platform; +pub mod traits; pub mod bigint; pub mod constant; pub mod montgomery; diff --git a/src/bn254/montgomery.rs b/src/bn254/montgomery.rs index 9ce7dcf..5755f3d 100644 --- a/src/bn254/montgomery.rs +++ b/src/bn254/montgomery.rs @@ -13,6 +13,7 @@ use std::random::{RandomSource,Distribution}; use unroll::unroll_for_loops; +use crate::bn254::traits::*; use crate::bn254::platform::*; use crate::bn254::bigint::*; use crate::bn254::constant::*; @@ -72,6 +73,19 @@ impl Mul for Mont { fn mul(self, other: Self) -> Self { Mont::mul(self, other) } } +//-------------------------------------- +// (non-standard ones, too...) + +impl Zero for Mont { + fn zero() -> Self { Mont::zero() } + fn is_zero(x: Self) -> bool { Mont::is_zero(x) } +} + +impl One for Mont { + fn one() -> Self { Mont::one() } + fn is_one(x: Self) -> bool { Mont::is_one(x) } +} + //------------------------------------------------------------------------------ // small values @@ -154,6 +168,22 @@ impl Mont { Mont(BigInt::zero()) } + #[inline(always)] + pub fn one() -> Mont { + Mont(BIG_R1) + } + + #[inline(always)] + pub fn is_zero(x: Mont) -> bool { + BigInt::is_zero(x.0) + } + + pub fn is_one(x: Mont) -> bool { + x.0 == BIG_R1 + } + + //------------------------------------ + pub fn neg(mont: Mont) -> Mont { if BigInt::is_zero(mont.0) { Mont::zero() diff --git a/src/bn254/test/bigint.rs b/src/bn254/test/bigint.rs index f61b66d..c0c43d2 100644 --- a/src/bn254/test/bigint.rs +++ b/src/bn254/test/bigint.rs @@ -6,6 +6,7 @@ use quickcheck::{Arbitrary, Gen}; use quickcheck_macros::quickcheck; +use crate::bn254::traits::*; use crate::bn254::bigint::*; use crate::bn254::test::properties::*; @@ -14,11 +15,21 @@ type Big7 = BigInt<7>; type Big9 = BigInt<9>; //------------------------------------------------------------------------------ +// some trivialities to get it started #[test] -fn zero_is_zero() { - assert!( Big::is_zero( Big::zero() ) ) -} +fn zero_is_zero() { assert!( Big::is_zero( Big::zero() ) ) } + +#[test] +fn zero_is_not_one() { assert!( !Big::is_one ( Big::zero() ) ) } + +#[test] +fn one_is_not_zero() { assert!( !Big::is_zero( Big::one () ) ) } + +#[test] +fn one_is_one() { assert!( Big::is_one ( Big::one () ) ) } + +//------------------------------------------------------------------------------ #[test] fn unit_to_decimal() { diff --git a/src/bn254/traits.rs b/src/bn254/traits.rs new file mode 100644 index 0000000..c969e96 --- /dev/null +++ b/src/bn254/traits.rs @@ -0,0 +1,13 @@ + +// rust have things like independent Neg, Add, Sub, Mul, all going to +// arbritrary whatever third types (...), but they missed this one, hah! + +pub trait Zero { + fn zero() -> Self; + fn is_zero(x: Self) -> bool; +} + +pub trait One { + fn one() -> Self; + fn is_one(x: Self) -> bool; +} \ No newline at end of file