Skip to content

Commit

Permalink
Refactor some internals of ff (#492)
Browse files Browse the repository at this point in the history
Co-authored-by: Weikeng Chen <w.k@berkeley.edu>
  • Loading branch information
Pratyush and weikengchen authored Oct 26, 2022
1 parent 19b6010 commit 3835af5
Show file tree
Hide file tree
Showing 15 changed files with 750 additions and 550 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,10 @@
- Remove method `generator_inv`.
- Remove method `divide_by_vanishing_poly_on_coset_in_place`.
- Remove coset fft methods: `coset_fft`, `coset_fft_in_place`, `coset_ifft`, `coset_ifft_in_place`.
- [\#492](https://github.com/arkworks-rs/algebra/pull/492) (`ark-ff`) Refactor `ark-ff` APIs:
- Splits the contents of `ff/src/fields/mod.rs` into smaller files for easier management.
- Moves `BitIterator` out of `ark_ff::fields` and into `ark_ff` directly.
- Adds `impl<'a, 'b> Add/Sub/Mul/Div<&'a F> for &'b F`

### Features

Expand Down
2 changes: 1 addition & 1 deletion ec/src/models/bls12/g2.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use ark_ff::fields::{BitIteratorBE, Field, Fp2};
use ark_ff::{BitIteratorBE, Field, Fp2};
use ark_serialize::*;
use ark_std::{vec::Vec, One};

Expand Down
4 changes: 2 additions & 2 deletions ec/src/models/bls12/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ use ark_ff::{
fp12_2over3over2::{Fp12, Fp12Config},
fp2::Fp2Config,
fp6_3over2::Fp6Config,
BitIteratorBE, Field, Fp2, PrimeField,
Fp2,
},
CyclotomicMultSubgroup,
BitIteratorBE, CyclotomicMultSubgroup, Field, PrimeField,
};
use ark_std::{marker::PhantomData, vec::Vec};
use num_traits::{One, Zero};
Expand Down
2 changes: 1 addition & 1 deletion ec/src/models/bw6/g2.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use ark_ff::fields::{BitIteratorBE, Field};
use ark_ff::{BitIteratorBE, Field};
use ark_serialize::*;
use ark_std::vec::Vec;
use num_traits::One;
Expand Down
4 changes: 2 additions & 2 deletions ec/src/models/bw6/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ use ark_ff::{
fields::{
fp3::Fp3Config,
fp6_2over3::{Fp6, Fp6Config},
BitIteratorBE, Field, PrimeField,
Field, PrimeField,
},
CyclotomicMultSubgroup,
BitIteratorBE, CyclotomicMultSubgroup,
};
use itertools::Itertools;
use num_traits::One;
Expand Down
5 changes: 2 additions & 3 deletions ff/src/biginteger/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use crate::{
const_for,
fields::{BitIteratorBE, BitIteratorLE},
UniformRand,
bits::{BitIteratorBE, BitIteratorLE},
const_for, UniformRand,
};
#[allow(unused)]
use ark_ff_macros::unroll_for_loops;
Expand Down
82 changes: 82 additions & 0 deletions ff/src/bits.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/// Iterates over a slice of `u64` in *big-endian* order.
#[derive(Debug)]
pub struct BitIteratorBE<Slice: AsRef<[u64]>> {
s: Slice,
n: usize,
}

impl<Slice: AsRef<[u64]>> BitIteratorBE<Slice> {
pub fn new(s: Slice) -> Self {
let n = s.as_ref().len() * 64;
BitIteratorBE { s, n }
}

/// Construct an iterator that automatically skips any leading zeros.
/// That is, it skips all zeros before the most-significant one.
pub fn without_leading_zeros(s: Slice) -> impl Iterator<Item = bool> {
Self::new(s).skip_while(|b| !b)
}
}

impl<Slice: AsRef<[u64]>> Iterator for BitIteratorBE<Slice> {
type Item = bool;

fn next(&mut self) -> Option<bool> {
if self.n == 0 {
None
} else {
self.n -= 1;
let part = self.n / 64;
let bit = self.n - (64 * part);

Some(self.s.as_ref()[part] & (1 << bit) > 0)
}
}
}

/// Iterates over a slice of `u64` in *little-endian* order.
#[derive(Debug)]
pub struct BitIteratorLE<Slice: AsRef<[u64]>> {
s: Slice,
n: usize,
max_len: usize,
}

impl<Slice: AsRef<[u64]>> BitIteratorLE<Slice> {
pub fn new(s: Slice) -> Self {
let n = 0;
let max_len = s.as_ref().len() * 64;
BitIteratorLE { s, n, max_len }
}

/// Construct an iterator that automatically skips any trailing zeros.
/// That is, it skips all zeros after the most-significant one.
pub fn without_trailing_zeros(s: Slice) -> impl Iterator<Item = bool> {
let mut first_trailing_zero = 0;
for (i, limb) in s.as_ref().iter().enumerate().rev() {
first_trailing_zero = i * 64 + (64 - limb.leading_zeros()) as usize;
if *limb != 0 {
break;
}
}
let mut iter = Self::new(s);
iter.max_len = first_trailing_zero;
iter
}
}

impl<Slice: AsRef<[u64]>> Iterator for BitIteratorLE<Slice> {
type Item = bool;

fn next(&mut self) -> Option<bool> {
if self.n == self.max_len {
None
} else {
let part = self.n / 64;
let bit = self.n - (64 * part);
self.n += 1;

Some(self.s.as_ref()[part] & (1 << bit) > 0)
}
}
}
140 changes: 139 additions & 1 deletion ff/src/fields/arithmetic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,75 @@ macro_rules! impl_additive_ops_from_ref {
}
}

impl<'b, P: $params> core::ops::Add<$type<P>> for &'b $type<P> {
type Output = $type<P>;

#[inline]
fn add(self, mut other: $type<P>) -> $type<P> {
other.add_assign(self);
other
}
}

#[allow(unused_qualifications)]
impl<'a, 'b, P: $params> core::ops::Add<&'a $type<P>> for &'b $type<P> {
type Output = $type<P>;

#[inline]
fn add(self, other: &'a $type<P>) -> $type<P> {
let mut result = *self;
result.add_assign(&*other);
result
}
}

#[allow(unused_qualifications)]
impl<'a, 'b, P: $params> core::ops::Add<&'a mut $type<P>> for &'b $type<P> {
type Output = $type<P>;

#[inline]
fn add(self, other: &'a mut $type<P>) -> $type<P> {
let mut result = *self;
result.add_assign(&*other);
result
}
}

impl<'b, P: $params> core::ops::Sub<$type<P>> for &'b $type<P> {
type Output = $type<P>;

#[inline]
fn sub(self, other: $type<P>) -> $type<P> {
let mut result = *self;
result.sub_assign(&other);
result
}
}

#[allow(unused_qualifications)]
impl<'a, 'b, P: $params> core::ops::Sub<&'a $type<P>> for &'b $type<P> {
type Output = $type<P>;

#[inline]
fn sub(self, other: &'a $type<P>) -> $type<P> {
let mut result = *self;
result.sub_assign(&*other);
result
}
}

#[allow(unused_qualifications)]
impl<'a, 'b, P: $params> core::ops::Sub<&'a mut $type<P>> for &'b $type<P> {
type Output = $type<P>;

#[inline]
fn sub(self, other: &'a mut $type<P>) -> $type<P> {
let mut result = *self;
result.sub_assign(&*other);
result
}
}

#[allow(unused_qualifications)]
impl<P: $params> core::ops::Sub<Self> for $type<P> {
type Output = Self;
Expand Down Expand Up @@ -94,7 +163,7 @@ macro_rules! impl_additive_ops_from_ref {
};
}

// Implements AddAssign on Self by deferring to an implementation on &Self
// Implements `MulAssign` and `DivAssign` by deferring to an implementation on &Self
#[macro_export]
macro_rules! impl_multiplicative_ops_from_ref {
($type: ident, $params: ident) => {
Expand Down Expand Up @@ -146,6 +215,75 @@ macro_rules! impl_multiplicative_ops_from_ref {
}
}

impl<'b, P: $params> core::ops::Mul<$type<P>> for &'b $type<P> {
type Output = $type<P>;

#[inline]
fn mul(self, mut other: $type<P>) -> $type<P> {
other.mul_assign(self);
other
}
}

#[allow(unused_qualifications)]
impl<'a, 'b, P: $params> core::ops::Mul<&'a $type<P>> for &'b $type<P> {
type Output = $type<P>;

#[inline]
fn mul(self, other: &'a $type<P>) -> $type<P> {
let mut result = *self;
result.mul_assign(&*other);
result
}
}

#[allow(unused_qualifications)]
impl<'a, 'b, P: $params> core::ops::Mul<&'a mut $type<P>> for &'b $type<P> {
type Output = $type<P>;

#[inline]
fn mul(self, other: &'a mut $type<P>) -> $type<P> {
let mut result = *self;
result.mul_assign(&*other);
result
}
}

impl<'b, P: $params> core::ops::Div<$type<P>> for &'b $type<P> {
type Output = $type<P>;

#[inline]
fn div(self, other: $type<P>) -> $type<P> {
let mut result = *self;
result.div_assign(&other);
result
}
}

#[allow(unused_qualifications)]
impl<'a, 'b, P: $params> core::ops::Div<&'a $type<P>> for &'b $type<P> {
type Output = $type<P>;

#[inline]
fn div(self, other: &'a $type<P>) -> $type<P> {
let mut result = *self;
result.div_assign(&*other);
result
}
}

#[allow(unused_qualifications)]
impl<'a, 'b, P: $params> core::ops::Div<&'a mut $type<P>> for &'b $type<P> {
type Output = $type<P>;

#[inline]
fn div(self, other: &'a mut $type<P>) -> $type<P> {
let mut result = *self;
result.div_assign(&*other);
result
}
}

#[allow(unused_qualifications)]
impl<P: $params> core::iter::Product<Self> for $type<P> {
fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
Expand Down
Loading

0 comments on commit 3835af5

Please sign in to comment.