Skip to content

Commit 832cc46

Browse files
authored
Fix Issue 10796 - FFT doesn’t work with user-defined complex types (dlang#10797)
1 parent 6f571c5 commit 832cc46

File tree

1 file changed

+47
-5
lines changed

1 file changed

+47
-5
lines changed

std/numeric.d

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3733,7 +3733,16 @@ public:
37333733
}
37343734
else if (range.length == 1)
37353735
{
3736-
buf[0] = range[0];
3736+
static if (isNumeric!(ElementType!R))
3737+
{
3738+
buf[0].re = range[0];
3739+
buf[0].im = 0;
3740+
}
3741+
else
3742+
{
3743+
buf[0].re = range[0].re;
3744+
buf[0].im = range[0].im;
3745+
}
37373746
return;
37383747
}
37393748
else if (range.length == 2)
@@ -3931,6 +3940,26 @@ void inverseFft(Ret, R)(R range, Ret buf)
39313940
assert(isClose(twoInv[1].im, 0, 0.0, 1e-10));
39323941
}
39333942

3943+
// https://github.com/dlang/phobos/issues/10796
3944+
@system unittest
3945+
{
3946+
import std.algorithm;
3947+
import std.range;
3948+
static struct C { float re, im; } // User-defined complex
3949+
3950+
float[8] arr = [1,2,3,4,5,6,7,8];
3951+
C[8] fft1;
3952+
fft(arr[], fft1[]);
3953+
assert(isClose(fft1[].map!"a.re",
3954+
[36.0, -4, -4, -4, -4, -4, -4, -4], 1e-4));
3955+
assert(isClose(fft1[].map!"a.im",
3956+
[0, 9.6568, 4, 1.6568, 0, -1.6568, -4, -9.6568], 1e-4));
3957+
3958+
auto inv = inverseFft(fft1[]);
3959+
assert(isClose(inv[].map!"a.re", arr[], 1e-6));
3960+
assert(inv[].map!"a.im".maxElement < 1e-10);
3961+
}
3962+
39343963
// Swaps the real and imaginary parts of a complex number. This is useful
39353964
// for inverse FFTs.
39363965
C swapRealImag(C)(C input)
@@ -4112,11 +4141,24 @@ struct Stride(R)
41124141
// using a generic slow DFT. This seems to be the best base case. (Size 1
41134142
// can be coded inline as buf[0] = range[0]).
41144143
void slowFourier2(Ret, R)(R range, Ret buf)
4144+
if (isComplexLike!(ElementType!Ret))
4145+
in (range.length == 2)
4146+
in (buf.length == 2)
41154147
{
4116-
assert(range.length == 2);
4117-
assert(buf.length == 2);
4118-
buf[0] = range[0] + range[1];
4119-
buf[1] = range[0] - range[1];
4148+
static if (isNumeric!(ElementType!R))
4149+
{
4150+
buf[0].re = range[0] + range[1];
4151+
buf[0].im = 0;
4152+
buf[1].re = range[0] - range[1];
4153+
buf[1].im = 0;
4154+
}
4155+
else
4156+
{
4157+
buf[0].re = range[0].re + range[1].re;
4158+
buf[0].im = range[0].im + range[1].im;
4159+
buf[1].re = range[0].re - range[1].re;
4160+
buf[1].im = range[0].im - range[1].im;
4161+
}
41204162
}
41214163

41224164
// Hard-coded base case for FFT of size 4. Doesn't work as well as the size

0 commit comments

Comments
 (0)