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

Add support for System.Numerics.Complex[] #61

Closed
AlexandrSpirin opened this issue May 7, 2023 · 2 comments · Fixed by #66
Closed

Add support for System.Numerics.Complex[] #61

AlexandrSpirin opened this issue May 7, 2023 · 2 comments · Fixed by #66

Comments

@AlexandrSpirin
Copy link

Why do you use your own Complex class for complex numbers, now C# has a built-in class and it looks like it can do the same thing as yours?

@swharden
Copy link
Owner

Hi @AlexandrSpirin, this is a good question! I think the reason I implemented my own complex number class is so it could be minimal and simple, and easily ported to other languages. Compare the complexity of these two classes:

I recognize that people who already have data in System.Numerics.Complex[] would expect a FFT library to be able to work with that standard data type. We could add support for this in a non-breaking way by overloading these two functions with essentially identical code:

/// <summary>
/// Compute the discrete Fourier Transform (in-place) using the FFT algorithm.
/// </summary>
/// <param name="buffer">Data to transform in-place. Length must be a power of 2.</param>
public static void FFT(Span<Complex> buffer)
{
if (buffer.Length == 0)
throw new ArgumentException("Buffer must not be empty");
if (!IsPowerOfTwo(buffer.Length))
throw new ArgumentException("Buffer length must be a power of 2");
FFT_WithoutChecks(buffer);
}
/// <summary>
/// High performance FFT function.
/// Complex input will be transformed in place.
/// Input array length must be a power of two. This length is NOT validated.
/// Running on an array with an invalid length may throw an invalid index exception.
/// </summary>
private static void FFT_WithoutChecks(Span<Complex> buffer)
{
for (int i = 1; i < buffer.Length; i++)
{
int j = BitReverse(i, buffer.Length);
if (j > i)
(buffer[j], buffer[i]) = (buffer[i], buffer[j]);
}
for (int i = 1; i <= buffer.Length / 2; i *= 2)
{
double mult1 = -Math.PI / i;
for (int j = 0; j < buffer.Length; j += (i * 2))
{
for (int k = 0; k < i; k++)
{
int evenI = j + k;
int oddI = j + k + i;
Complex temp = new Complex(Math.Cos(mult1 * k), Math.Sin(mult1 * k));
temp *= buffer[oddI];
buffer[oddI] = buffer[evenI] - temp;
buffer[evenI] += temp;
}
}
}
}

If you want to create a PR I would be happy to review it! Bonus points for demonstrating the new usage in the readme and in a new test. If you decide not to that's okay, I'll leave this issue open and implement this next time I work in this code base.

Thanks again for pointing this out!
Scott

@swharden swharden changed the title Complex Add support for System.Numerics.Complex[] May 12, 2023
@swharden
Copy link
Owner

swharden commented May 17, 2023

Following-up, I'm moving these methods into their own static class with a simpler API that resembles Math.NET

// Apply FFT in place
System.Numerics.Complex[] samples = { /* */ };
FftSharp.FFT.Forward(samples);
// Get FFT from real data array
double[] samples = { /* */ };
System.Numerics.Complex[] fft = FftSharp.FFT.Forward(samples);

The Transform class will eventually be deprecated

swharden added a commit that referenced this issue May 17, 2023
Simple methods which act on System.Numeric.Complex data types #61
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 a pull request may close this issue.

2 participants