Skip to content

Commit

Permalink
Implement Fourier transform.
Browse files Browse the repository at this point in the history
  • Loading branch information
afck committed Sep 3, 2018
1 parent 76ac2a5 commit 8820c11
Show file tree
Hide file tree
Showing 4 changed files with 462 additions and 3 deletions.
30 changes: 29 additions & 1 deletion benches/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,34 @@ mod poly_benches {
);
}

// Benchmarks multiplication of two polynomials using their Fourier transform.
fn multiplication_fft(c: &mut Criterion) {
let mut rng = rand::thread_rng();
c.bench_function_over_inputs(
"Polynomial multiplication using FFT",
move |b, &&deg: &&usize| {
let log_n = deg.next_power_of_two().trailing_zeros() as usize + 1;
let rand_factors = || {
let lhs = Poly::random(deg, &mut rng).unwrap();
let rhs = Poly::random(deg, &mut rng).unwrap();
(lhs, rhs)
};
b.iter_with_setup(rand_factors, |(lhs, rhs)| {
let lhs_fft = lhs
.fourier_transform(log_n)
.expect("failed to apply Fourier transform");
let rhs_fft = rhs
.fourier_transform(log_n)
.expect("failed to apply Fourier transform");
(lhs_fft * rhs_fft)
.inverse_fourier_transform()
.expect("failed to apply inverse Fourier transform");
})
},
&[5, 10, 20, 40],
);
}

// Benchmarks Lagrange interpolation for a polynomial.
fn interpolate(c: &mut Criterion) {
let mut rng = rand::thread_rng();
Expand All @@ -45,7 +73,7 @@ mod poly_benches {
criterion_group!{
name = poly_benches;
config = Criterion::default();
targets = multiplication, interpolate,
targets = multiplication, multiplication_fft, interpolate,
}
}

Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ extern crate tiny_keccak;
pub mod error;
mod into_fr;
pub mod poly;
pub mod poly_vals;
pub mod serde_impl;

use std::env;
Expand Down
17 changes: 15 additions & 2 deletions src/poly.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,11 @@ use std::{cmp, iter, ops};
use errno::errno;
use memsec::{memzero, mlock, munlock};
use pairing::bls12_381::{Fr, G1Affine, G1};
use pairing::{CurveAffine, CurveProjective, Field};
use pairing::{CurveAffine, CurveProjective, Field, PrimeField};
use rand::Rng;

use super::{ContainsSecret, Error, IntoFr, Result, SHOULD_MLOCK_SECRETS};
use poly_vals::{fourier_transform, PolyVals};

/// A univariate polynomial in the prime field.
#[derive(Serialize, Deserialize, PartialEq, Eq)]
Expand Down Expand Up @@ -348,8 +349,9 @@ impl Poly {
///
/// Returns an `Error::MlockFailed` if we have reached the systems's locked memory limit.
pub fn new(coeff: Vec<Fr>) -> Result<Self> {
let poly = Poly { coeff };
let mut poly = Poly { coeff };
poly.mlock_secret_memory()?;
poly.remove_zeros()?;
Ok(poly)
}

Expand All @@ -363,6 +365,17 @@ impl Poly {
Poly::new(coeff)
}

/// Returns the Fourier transform of this polynomial.
pub fn fourier_transform(&self, log_n: usize) -> Result<PolyVals> {
// The canonical primitive `n`-th root of unity.
let mut root = Fr::root_of_unity();
for _ in log_n..(Fr::S as usize) {
root.square();
}
let vals = fourier_transform(log_n, &self.coeff, &root);
PolyVals::new(log_n, vals)
}

/// Returns the polynomial with constant value `0`.
///
/// # Errors
Expand Down
Loading

0 comments on commit 8820c11

Please sign in to comment.