implement Zero and One trait abstractions

This commit is contained in:
Balazs Komuves 2026-01-30 03:04:16 +01:00
parent 0628b17ca1
commit b01b63bdab
No known key found for this signature in database
GPG Key ID: F63B7AEF18435562
7 changed files with 127 additions and 6 deletions

View File

@ -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) );
}

View File

@ -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<const N: usize> Ord for BigInt<N> {
fn cmp(&self, other: &Self) -> Ordering { BigInt::cmp(*self, *other) }
}
//--------------------------------------
// (non-standard ones, too...)
impl<const N: usize> Zero for BigInt<N> {
fn zero() -> Self { BigInt::zero() }
fn is_zero(x: Self) -> bool { BigInt::is_zero(x) }
}
impl<const N: usize> One for BigInt<N> {
fn one() -> Self { BigInt::one() }
fn is_one(x: Self) -> bool { BigInt::is_one(x) }
}
//------------------------------------------------------------------------------
// conversion traits
@ -210,6 +224,10 @@ impl<const N: usize> BigInt<N> {
BigInt([0; N])
}
pub fn one() -> BigInt<N> {
BigInt::from_u32(1)
}
pub fn from_u32(x: u32) -> BigInt<N> {
let mut xs = [0; N];
xs[0] = x;
@ -223,6 +241,20 @@ impl<const N: usize> BigInt<N> {
big.0.iter().all(|&x| x == 0)
}
pub fn is_one(big: BigInt<N>) -> 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<N>, big2: BigInt<N>) -> Ordering {
let mut res : Ordering = Ordering::Equal;
for i in (0..N).rev() {

View File

@ -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()

View File

@ -1,6 +1,7 @@
mod platform;
pub mod traits;
pub mod bigint;
pub mod constant;
pub mod montgomery;

View File

@ -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()

View File

@ -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() {

13
src/bn254/traits.rs Normal file
View File

@ -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;
}