Skip to content

Commit

Permalink
feat: add limbs conversion from ark_ff bigint to arbitrary limbs in V…
Browse files Browse the repository at this point in the history
…ec<u32>
  • Loading branch information
moven0831 committed Nov 7, 2024
1 parent 3c83886 commit 6f7884c
Showing 1 changed file with 71 additions and 0 deletions.
71 changes: 71 additions & 0 deletions mopro-msm/src/msm/metal_msm/utils/limbs_conversion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ 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>;
fn to_limbs(&self, num_limbs: usize, log_limb_size: u32) -> Vec<u32>;
}

pub trait FromLimbs {
fn from_u32_limbs(limbs: &[u32]) -> Self;
fn from_limbs(limbs: &[u32], log_limb_size: u32) -> Self;
fn from_u128(num: u128) -> Self;
fn from_u32(num: u32) -> Self;
}
Expand All @@ -26,6 +28,37 @@ impl ToLimbs for BigInteger256 {
});
limbs
}

fn to_limbs(&self, num_limbs: usize, log_limb_size: u32) -> Vec<u32> {
let mut result = vec![0u32; num_limbs];
let limb_size = 1u32 << log_limb_size;
let mask = limb_size - 1;

// Convert to little-endian representation
let bytes = self.to_bytes_le();
let mut val = 0u32;
let mut bits = 0u32;
let mut limb_idx = 0;

for &byte in bytes.iter() {
val |= (byte as u32) << bits;
bits += 8;

while bits >= log_limb_size && limb_idx < num_limbs {
result[limb_idx] = val & mask;
val >>= log_limb_size;
bits -= log_limb_size;
limb_idx += 1;
}
}

// Handle any remaining bits
if bits > 0 && limb_idx < num_limbs {
result[limb_idx] = val;
}

result
}
}

// convert from little endian to big endian
Expand All @@ -40,6 +73,10 @@ impl ToLimbs for Fq {
});
limbs
}

fn to_limbs(&self, num_limbs: usize, log_limb_size: u32) -> Vec<u32> {
self.0.to_limbs(num_limbs, log_limb_size)
}
}

impl FromLimbs for BigInteger256 {
Expand All @@ -63,6 +100,35 @@ impl FromLimbs for BigInteger256 {
fn from_u32(num: u32) -> Self {
BigInteger256::new([num as u64, 0, 0, 0])
}

fn from_limbs(limbs: &[u32], log_limb_size: u32) -> Self {
let mut result = [0u64; 4];
let limb_size = log_limb_size as usize;
let mut accumulated_bits = 0;
let mut current_u64 = 0u64;
let mut result_idx = 0;

for &limb in limbs {
// Add the current limb at the appropriate position
current_u64 |= (limb as u64) << accumulated_bits;
accumulated_bits += limb_size;

// If we've accumulated 64 bits or more, store the result
while accumulated_bits >= 64 && result_idx < 4 {
result[result_idx] = current_u64;
current_u64 = limb as u64 >> (limb_size - (accumulated_bits - 64));
accumulated_bits -= 64;
result_idx += 1;
}
}

// Handle any remaining bits
if accumulated_bits > 0 && result_idx < 4 {
result[result_idx] = current_u64;
}

BigInteger256::new(result)
}
}

impl FromLimbs for Fq {
Expand All @@ -88,4 +154,9 @@ impl FromLimbs for Fq {
num as u64, 0, 0, 0,
])))
}

fn from_limbs(limbs: &[u32], log_limb_size: u32) -> Self {
let bigint = BigInteger256::from_limbs(limbs, log_limb_size);
Fq::new(mont_reduction::raw_reduction(bigint))
}
}

0 comments on commit 6f7884c

Please sign in to comment.