Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement an iterative FFT algorithm #21

Merged
merged 1 commit into from
Apr 5, 2021
Merged

Conversation

cjpatton
Copy link
Collaborator

This adds an alternative FFT algorithm for doing the discrete Fourier transform. The main advantage is that you don't have to set up auxiliary state (PolyAuxMemory and PolyFFTTempMemory) that gets carried around through the code. It's also quite a bit faster, even compared to amortizing the cost of setting up the auxiliary state across FFT operations. This is demonstrated by the benchmarks in the last commit. The commit is marked "WIP" because I'm not sure we actually want to merge it, since it requires making the the polynomial module pubic.

@cjpatton
Copy link
Collaborator Author

Currently the new code isn't integrated into proof generation/verification. There is a unit test that confirms that the algorithms output the same thing, and I've tested that the rest of the tests pass with the new algorithm. If you'd like, we can integrate the new algorithm as part of this PR.

@cjpatton cjpatton force-pushed the iter-fft branch 3 times, most recently from a9fb223 to a415368 Compare April 1, 2021 04:17
src/finite_field.rs Outdated Show resolved Hide resolved
src/finite_field.rs Outdated Show resolved Hide resolved
src/finite_field.rs Outdated Show resolved Hide resolved
src/finite_field.rs Outdated Show resolved Hide resolved
src/finite_field.rs Outdated Show resolved Hide resolved
src/fft.rs Outdated Show resolved Hide resolved
src/fft.rs Outdated
}

/// Sets `outp` to the inverse of the DFT of `inp`.
pub fn dft_inv<F: FieldElement>(outp: &mut [F], inp: &[F]) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar comments to the dft function:

  1. I'd prefer a longer, more explicit function name like inverse_discrete_fourier_transform
  2. Would prefer that this return the output as [F] instead of taking a mutable slice, unless there's a specific reason to do it this way.

Copy link
Collaborator Author

@cjpatton cjpatton Apr 3, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1. I'd prefer a longer, more explicit function name like `inverse_discrete_fourier_transform`

Changed to discrete_fourier_transform_inv, in order to align with FieldElement::inv.

2. Would prefer that this return the output as `[F]` instead of taking a mutable slice, unless there's a specific reason to do it this way.

See above comment (I'm trying to avoid nedless malloc).

src/fft.rs Outdated
/// Sets `outp` to the inverse of the DFT of `inp`.
pub fn dft_inv<F: FieldElement>(outp: &mut [F], inp: &[F]) {
let n = inp.len();
let m: F = F::from_usize(n).unwrap().inv();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly to dft, dft_inv should return an error and avoid unwrap().

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here again, I think panicking is more appropriate. The function will only panic if discrete_fourier_transform() isn't implemented properly. (See the new input length checks in that function.)

src/fft.rs Outdated Show resolved Hide resolved
+ Display
{
/// The integer representation of the field element.
type Integer;

/// Modular exponentation, i.e., `self^exp (mod p)`.
fn pow(&self, exp: Self) -> Self;
fn pow(&self, exp: Self) -> Self; // TODO(cjpatton) exp should have type Self::Integer
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why? Because I might want to raise self to some exponent that's greater than the field prime?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if one would ever want to do that. The reason is more mathematically pedantic: Raising an element of a group (or field) to the power of an element of that group (or field) is not always well-defined. In general, a^x only makes sense if x is an integer.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that I plan to solve this TODO in the next PR.

Copy link
Contributor

@tgeoghegan tgeoghegan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a couple typos in a comment, but LGTM otherwise!

src/benchmarked.rs Outdated Show resolved Hide resolved
This change adds an alternative algorithm for computing the discrete
Fourier transform. It also adds a new module, benchmarked, for
components of the crate that we want to benchmark, but don't want to
expose in the public API. Finally, it adds a benchmark for comparing the
speed of iterative FFT and recursive FFT on various input lengths.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants