-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: migrate prev utils mod to refactored metal msm
- Loading branch information
Showing
3 changed files
with
133 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
use ark_bn254::Fq; | ||
use ark_ff::biginteger::{BigInteger, BigInteger256}; | ||
|
||
use crate::msm::metal::abstraction::mont_reduction; | ||
|
||
// implement to_u32_limbs and from_u32_limbs for BigInt<4> | ||
pub trait ToLimbs { | ||
fn to_u32_limbs(&self) -> Vec<u32>; | ||
} | ||
|
||
pub trait FromLimbs { | ||
fn from_u32_limbs(limbs: &[u32]) -> Self; | ||
fn from_u128(num: u128) -> Self; | ||
fn from_u32(num: u32) -> Self; | ||
} | ||
|
||
// convert from little endian to big endian | ||
impl ToLimbs for BigInteger256 { | ||
fn to_u32_limbs(&self) -> Vec<u32> { | ||
let mut limbs = Vec::new(); | ||
self.to_bytes_be().chunks(8).for_each(|chunk| { | ||
let high = u32::from_be_bytes(chunk[0..4].try_into().unwrap()); | ||
let low = u32::from_be_bytes(chunk[4..8].try_into().unwrap()); | ||
limbs.push(high); | ||
limbs.push(low); | ||
}); | ||
limbs | ||
} | ||
} | ||
|
||
// convert from little endian to big endian | ||
impl ToLimbs for Fq { | ||
fn to_u32_limbs(&self) -> Vec<u32> { | ||
let mut limbs = Vec::new(); | ||
self.0.to_bytes_be().chunks(8).for_each(|chunk| { | ||
let high = u32::from_be_bytes(chunk[0..4].try_into().unwrap()); | ||
let low = u32::from_be_bytes(chunk[4..8].try_into().unwrap()); | ||
limbs.push(high); | ||
limbs.push(low); | ||
}); | ||
limbs | ||
} | ||
} | ||
|
||
impl FromLimbs for BigInteger256 { | ||
// convert from big endian to little endian for metal | ||
fn from_u32_limbs(limbs: &[u32]) -> Self { | ||
let mut big_int = [0u64; 4]; | ||
for (i, limb) in limbs.chunks(2).rev().enumerate() { | ||
let high = u64::from(limb[0]); | ||
let low = u64::from(limb[1]); | ||
big_int[i] = (high << 32) | low; | ||
} | ||
BigInteger256::new(big_int) | ||
} | ||
// provide little endian u128 since arkworks use this value as well | ||
fn from_u128(num: u128) -> Self { | ||
let high = (num >> 64) as u64; | ||
let low = num as u64; | ||
BigInteger256::new([low, high, 0, 0]) | ||
} | ||
// provide little endian u32 since arkworks use this value as well | ||
fn from_u32(num: u32) -> Self { | ||
BigInteger256::new([num as u64, 0, 0, 0]) | ||
} | ||
} | ||
|
||
impl FromLimbs for Fq { | ||
// convert from big endian to little endian for metal | ||
fn from_u32_limbs(limbs: &[u32]) -> Self { | ||
let mut big_int = [0u64; 4]; | ||
for (i, limb) in limbs.chunks(2).rev().enumerate() { | ||
let high = u64::from(limb[0]); | ||
let low = u64::from(limb[1]); | ||
big_int[i] = (high << 32) | low; | ||
} | ||
Fq::new(mont_reduction::raw_reduction(BigInteger256::new(big_int))) | ||
} | ||
fn from_u128(num: u128) -> Self { | ||
let high = (num >> 64) as u64; | ||
let low = num as u64; | ||
Fq::new(mont_reduction::raw_reduction(BigInteger256::new([ | ||
low, high, 0, 0, | ||
]))) | ||
} | ||
fn from_u32(num: u32) -> Self { | ||
Fq::new(mont_reduction::raw_reduction(BigInteger256::new([ | ||
num as u64, 0, 0, 0, | ||
]))) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
pub mod limbs_conversion; | ||
pub mod mont_reduction; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
use ark_bn254::FqConfig; | ||
use ark_ff::{ | ||
biginteger::{arithmetic as fa, BigInt}, | ||
fields::models::{MontBackend, MontConfig}, | ||
Fp, | ||
}; | ||
|
||
// Reference: https://github.com/arkworks-rs/algebra/blob/master/ff/src/fields/models/fp/montgomery_backend.rs#L373-L389 | ||
const N: usize = 4; | ||
pub fn into_bigint(a: Fp<MontBackend<FqConfig, N>, N>) -> BigInt<N> { | ||
let a = a.0; | ||
raw_reduction(a) | ||
} | ||
|
||
pub fn raw_reduction(a: BigInt<N>) -> BigInt<N> { | ||
let mut r = a.0; // parse into [u64; N] | ||
|
||
// Montgomery Reduction | ||
for i in 0..N { | ||
let k = r[i].wrapping_mul(<FqConfig as MontConfig<N>>::INV); | ||
let mut carry = 0; | ||
|
||
fa::mac_with_carry( | ||
r[i], | ||
k, | ||
<FqConfig as MontConfig<N>>::MODULUS.0[0], | ||
&mut carry, | ||
); | ||
for j in 1..N { | ||
r[(j + i) % N] = fa::mac_with_carry( | ||
r[(j + i) % N], | ||
k, | ||
<FqConfig as MontConfig<N>>::MODULUS.0[j], | ||
&mut carry, | ||
); | ||
} | ||
r[i % N] = carry; | ||
} | ||
BigInt::new(r) | ||
} |