Skip to content

Commit

Permalink
Work
Browse files Browse the repository at this point in the history
  • Loading branch information
Pratyush committed Aug 3, 2023
1 parent 47cd419 commit 04b4106
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 20 deletions.
5 changes: 3 additions & 2 deletions algebra-core/src/group/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,10 @@ pub trait MultiplicativeGroup:
invert_and_mul_batch(v, &Self::one());
}

fn invert_batch(v: &[Self]) {
fn invert_batch(v: &[Self]) -> Vec<Self> {
let mut v = v.to_vec();
Self::invert_batch(&mut v);
Self::invert_batch_in_place(&mut v);
v
}
}

Expand Down
2 changes: 1 addition & 1 deletion algebra-core/src/module/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ pub trait ScalarExp<Exponent: Sc>:
fn pow_exp_base(base: &Self::ExpBase, exp: Exponent) -> Self {
let mut res = Self::one();
let (sign, exp) = exp.as_u64s();
for (i, bit) in crate::bits::BitIteratorBE::without_leading_zeros(exp).enumerate() {
for bit in crate::bits::BitIteratorBE::without_leading_zeros(exp) {
res.square_in_place();
if bit {
res *= base;
Expand Down
64 changes: 64 additions & 0 deletions algebra-core/src/module/scalar.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use ark_std::fmt::Debug;

use crate::biginteger::{signed_mod_reduction, arithmetic::{sbb_for_sub_with_borrow, adc_for_add_with_carry}};

#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
pub enum Sign {
Negative = -1,
Expand All @@ -25,6 +27,68 @@ pub trait Scalar: Send + Sync + Copy + Debug {
fn as_bytes(&self) -> (Sign, Self::U8Ref);

fn as_u64s(&self) -> (Sign, Self::U64Ref);

/// Returns the windowed non-adjacent form of `self`, for a window of size `w`.
fn find_wnaf(&self, w: usize) -> Option<Vec<i64>> {
// w > 2 due to definition of wNAF, and w < 64 to make sure that `i64`
// can fit each signed digit
if (2..64).contains(&w) {
let mut res = vec![];
let mut e = self.as_u64s().1.as_ref().to_vec();

while !is_zero(&e) {
let z: i64;
if is_odd(&e) {
z = signed_mod_reduction(e[0], 1 << w);
if z >= 0 {
sub_with_borrow(&mut e, z as u64);
} else {
add_with_carry(&mut e, (-z) as u64);
}
} else {
z = 0;
}
res.push(z);
div2(&mut e);
}

Some(res)
} else {
None
}
}
}

fn is_zero(a: &[u64]) -> bool {
a.iter().all(|x| *x == 0)
}

fn is_odd(a: &[u64]) -> bool {
a[0] % 2 == 1
}

fn sub_with_borrow(a: &mut [u64], b: u64) {
let mut borrow = sbb_for_sub_with_borrow(&mut a[0], b, 0);
for a in &mut a[1..] {
borrow = sbb_for_sub_with_borrow(a, 0, borrow);
}
}

fn add_with_carry(a: &mut [u64], b: u64) {
let mut carry = adc_for_add_with_carry(&mut a[0], b, 0);
for a in &mut a[1..] {
carry = adc_for_add_with_carry(a, 0, carry);
}
}

fn div2(a: &mut [u64]) {
let mut t = 0;
for a in a.iter_mut().rev() {
let t2 = *a << 63;
*a >>= 1;
*a |= t;
t = t2;
}
}

macro_rules! impl_scalar_unsigned {
Expand Down
75 changes: 72 additions & 3 deletions algebra-core/src/scalar_mul/wnaf.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
module::{Scalar, ScalarMul},
AdditiveGroup,
module::{Scalar, ScalarMul, ScalarExp},
AdditiveGroup, MultiplicativeGroup,
};
use ark_std::vec::Vec;

Expand Down Expand Up @@ -60,7 +60,7 @@ impl WnafContext {
if 1 << (self.window_size - 1) > base_table.len() {
return None;
}
let scalar_wnaf = scalar.into_bigint().find_wnaf(self.window_size).unwrap();
let scalar_wnaf = scalar.find_wnaf(self.window_size).unwrap();

let mut result = G::zero();

Expand All @@ -85,3 +85,72 @@ impl WnafContext {
Some(result)
}
}


impl WnafContext {
pub fn multiplicative_table<G: MultiplicativeGroup>(&self, mut base: G) -> Vec<G> {
let mut table = Vec::with_capacity(1 << (self.window_size - 1));
let sqr = base.square();

for _ in 0..(1 << (self.window_size - 1)) {
table.push(base);
base *= &sqr;
}
table
}

/// Computes scalar multiplication of a group element `g` by `scalar`.
///
/// This method uses the wNAF algorithm to perform the scalar
/// multiplication; first, it uses `Self::table` to calculate an
/// appropriate table of multiples of `g`, and then uses the wNAF
/// algorithm to compute the scalar multiple.
pub fn exp<G: ScalarExp<S>, S: Scalar>(&self, g: G, scalar: &S) -> G {
let table = self.multiplicative_table(g);
self.exp_with_table(&table, scalar).unwrap()
}

/// Computes scalar multiplication of a group element by `scalar`.
/// `base_table` holds precomputed multiples of the group element; it can be
/// generated using `Self::table`. `scalar` is an element of
/// `G::ScalarField`.
///
/// Returns `None` if the table is too small.
pub fn exp_with_table<G: ScalarExp<S>, S: Scalar>(
&self,
base_table: &[G],
scalar: &S,
) -> Option<G> {
if 1 << (self.window_size - 1) > base_table.len() {
return None;
}
let scalar_wnaf = scalar.find_wnaf(self.window_size).unwrap();
let inv_table = if G::INVERSION_IS_FAST {
vec![]
} else {
G::invert_batch(base_table)
};

let mut result = G::one();

let mut found_non_zero = false;

for n in scalar_wnaf.iter().rev() {
if found_non_zero {
result.square_in_place();
}

if *n != 0 {
found_non_zero = true;

if *n > 0 {
result *= &base_table[(n / 2) as usize];
} else {
result *= &inv_table[(n / 2) as usize];
}
}
}

Some(result)
}
}
14 changes: 0 additions & 14 deletions ff/src/fields/utils.rs
Original file line number Diff line number Diff line change
@@ -1,14 +0,0 @@
/// Calculates the k-adicity of n, i.e., the number of trailing 0s in a base-k
/// representation.
pub fn k_adicity(k: u64, mut n: u64) -> u32 {
let mut r = 0;
while n > 1 {
if n % k == 0 {
r += 1;
n /= k;
} else {
return r;
}
}
r
}

0 comments on commit 04b4106

Please sign in to comment.