Task 6 of 6
The inverse transform differs from the forward one in two small ways: the exponent
is +2πi·kt/n instead of -, and the result is divided by n. You
could write a second set of kernels. You do not have to — there is an identity that gets the
inverse out of the forward transform you already have:
ifft(X) = conj( fft( conj(X) ) ) / n
Conjugating flips the sign of every imaginary part, which is exactly the sign flip the exponent needs; doing it on the way in and again on the way out leaves everything else where it was. Nine lines of kernel and a division, and the transform runs both ways.
And then the warning, which is the real content of this task. A round trip is a consistency check, not a correctness check — it proves your inverse undoes your forward transform, and nothing else. Flip the twiddle sign in the butterfly and the forward transform computes the conjugate of the right spectrum; run it through this same inverse and the signal comes back perfectly, to the last bit. The magnitudes were already identical, the round trip is clean, and every plot looks right. The only thing that catches it is the comparison you did in the last task: against the definition.
conjugate(spectrum, scale), used at both ends — it negates the imaginary plane and multiplies both planes by scale1; coming out it is 1 / nconsole.log the largest round-trip error and the verdictThe kernel owns one output cell, and which plane it is decides the sign:
if (this.thread.y === 0) return spectrum[0][this.thread.x] * scale;
return -spectrum[1][this.thread.x] * scale;
The real part keeps its sign. Only the imaginary part turns over.
const recovered = conjugate(fft(conjugate(spectrum, 1)), 1 / n);
Inside out: conjugate, transform, conjugate again and scale. The
1 on the way in is not decoration — the same kernel has to take a scale
both times or gpu.js sees two different call shapes.
All of it, on the inverse. A forward transform followed by an unscaled inverse gives you the signal multiplied by n — so if every recovered sample is 256 times too big, the division is missing rather than misplaced.
This page is an interactive exercise — the editor, the GPU runner and your saved progress need JavaScript. The text above is the full brief.