|
1 | 1 | import { test } from 'node:test' |
2 | 2 | import assert from 'node:assert/strict' |
3 | | -import rfft, { fft, irfft, cfft, cifft } from './index.js' |
| 3 | +import rfft, { fft, ifft, cfft, cifft } from './index.js' |
4 | 4 |
|
5 | 5 | const EPSILON = 1e-6 |
6 | 6 |
|
@@ -262,85 +262,85 @@ test('fft: view overwritten on repeated calls', () => { |
262 | 262 | assert(Math.abs(ra[1][10] - (-N / 2)) < EPSILON, 'ra now reflects b') |
263 | 263 | }) |
264 | 264 |
|
265 | | -// --- Inverse real FFT (irfft) --- |
| 265 | +// --- Inverse real FFT (ifft) --- |
266 | 266 |
|
267 | | -test('irfft: rejects invalid input', () => { |
| 267 | +test('ifft: rejects invalid input', () => { |
268 | 268 | // bins=1 → N=0 (invalid) |
269 | | - assert.throws(() => irfft(new Float64Array(1), new Float64Array(1))) |
| 269 | + assert.throws(() => ifft(new Float64Array(1), new Float64Array(1))) |
270 | 270 | // bins=4 → N=6 (not power of 2) |
271 | | - assert.throws(() => irfft(new Float64Array(4), new Float64Array(4))) |
| 271 | + assert.throws(() => ifft(new Float64Array(4), new Float64Array(4))) |
272 | 272 | }) |
273 | 273 |
|
274 | | -test('irfft(fft(x)) round-trip recovers signal', () => { |
| 274 | +test('ifft(fft(x)) round-trip recovers signal', () => { |
275 | 275 | for (const N of [4, 64, 256, 1024]) { |
276 | 276 | const input = new Float32Array(N) |
277 | 277 | for (let i = 0; i < N; i++) input[i] = Math.sin(i * 0.7) + Math.cos(i * 1.3) |
278 | 278 |
|
279 | 279 | const [re, im] = fft(input) |
280 | | - const recovered = irfft(re, im) |
| 280 | + const recovered = ifft(re, im) |
281 | 281 |
|
282 | 282 | assert.equal(recovered.length, N) |
283 | 283 | for (let i = 0; i < N; i++) |
284 | 284 | assert(Math.abs(recovered[i] - input[i]) < EPSILON, `N=${N}, i=${i}: ${recovered[i]} vs ${input[i]}`) |
285 | 285 | } |
286 | 286 | }) |
287 | 287 |
|
288 | | -test('irfft: DC spectrum → constant signal', () => { |
| 288 | +test('ifft: DC spectrum → constant signal', () => { |
289 | 289 | const N = 64, half = N / 2 |
290 | 290 | const re = new Float64Array(half + 1) |
291 | 291 | const im = new Float64Array(half + 1) |
292 | 292 | re[0] = N // X[0] = N for DC=1 |
293 | | - const out = irfft(re, im) |
| 293 | + const out = ifft(re, im) |
294 | 294 | for (let i = 0; i < N; i++) |
295 | 295 | assert(Math.abs(out[i] - 1) < EPSILON, `i=${i}: ${out[i]}`) |
296 | 296 | }) |
297 | 297 |
|
298 | | -test('irfft: cosine spectrum → cosine signal', () => { |
| 298 | +test('ifft: cosine spectrum → cosine signal', () => { |
299 | 299 | const N = 128, k0 = 5, half = N / 2 |
300 | 300 | const re = new Float64Array(half + 1) |
301 | 301 | const im = new Float64Array(half + 1) |
302 | 302 | re[k0] = N / 2 // cos at bin k0 |
303 | | - const out = irfft(re, im) |
| 303 | + const out = ifft(re, im) |
304 | 304 | for (let i = 0; i < N; i++) { |
305 | 305 | const expected = Math.cos(2 * Math.PI * k0 * i / N) |
306 | 306 | assert(Math.abs(out[i] - expected) < EPSILON, `i=${i}: ${out[i]} vs ${expected}`) |
307 | 307 | } |
308 | 308 | }) |
309 | 309 |
|
310 | | -test('irfft: sine spectrum → sine signal', () => { |
| 310 | +test('ifft: sine spectrum → sine signal', () => { |
311 | 311 | const N = 128, k0 = 5, half = N / 2 |
312 | 312 | const re = new Float64Array(half + 1) |
313 | 313 | const im = new Float64Array(half + 1) |
314 | 314 | im[k0] = -N / 2 // sin at bin k0: X[k0] = -jN/2 |
315 | | - const out = irfft(re, im) |
| 315 | + const out = ifft(re, im) |
316 | 316 | for (let i = 0; i < N; i++) { |
317 | 317 | const expected = Math.sin(2 * Math.PI * k0 * i / N) |
318 | 318 | assert(Math.abs(out[i] - expected) < EPSILON, `i=${i}: ${out[i]} vs ${expected}`) |
319 | 319 | } |
320 | 320 | }) |
321 | 321 |
|
322 | | -test('irfft: output buffer parameter', () => { |
| 322 | +test('ifft: output buffer parameter', () => { |
323 | 323 | const N = 64, half = N / 2 |
324 | 324 | const re = new Float64Array(half + 1) |
325 | 325 | const im = new Float64Array(half + 1) |
326 | 326 | re[0] = N |
327 | 327 | const buf = new Float64Array(N) |
328 | | - const ret = irfft(re, im, buf) |
| 328 | + const ret = ifft(re, im, buf) |
329 | 329 | assert.equal(ret, buf) |
330 | 330 | assert(Math.abs(buf[0] - 1) < EPSILON) |
331 | 331 | }) |
332 | 332 |
|
333 | | -test('irfft: view overwritten on repeated calls', () => { |
| 333 | +test('ifft: view overwritten on repeated calls', () => { |
334 | 334 | const N = 64, half = N / 2 |
335 | 335 |
|
336 | 336 | const re1 = new Float64Array(half + 1), im1 = new Float64Array(half + 1) |
337 | 337 | re1[0] = N // DC → all ones |
338 | | - const a = irfft(re1, im1) |
| 338 | + const a = ifft(re1, im1) |
339 | 339 | assert(Math.abs(a[half] - 1) < EPSILON, 'DC: a[32] should be 1') |
340 | 340 |
|
341 | 341 | const re2 = new Float64Array(half + 1), im2 = new Float64Array(half + 1) |
342 | 342 | re2[3] = N / 2 // cosine at bin 3 → cos(2π·3·32/64) = cos(3π) = -1 |
343 | | - irfft(re2, im2) // overwrites a |
| 343 | + ifft(re2, im2) // overwrites a |
344 | 344 |
|
345 | 345 | assert(Math.abs(a[half] - (-1)) < EPSILON, 'a[32] should now be -1 (cosine at bin 3)') |
346 | 346 | }) |
|
0 commit comments