Skip to content

Commit e848427

Browse files
committed
docs: add comments
--- type: pre_commit_static_analysis_report description: Results of running static analysis checks when committing changes. report: - task: lint_filenames status: passed - task: lint_editorconfig status: passed - task: lint_markdown status: na - task: lint_package_json status: na - task: lint_repl_help status: na - task: lint_javascript_src status: passed - task: lint_javascript_cli status: na - task: lint_javascript_examples status: na - task: lint_javascript_tests status: na - task: lint_javascript_benchmarks status: na - task: lint_python status: na - task: lint_r status: na - task: lint_c_src status: na - task: lint_c_examples status: na - task: lint_c_benchmarks status: na - task: lint_c_tests_fixtures status: na - task: lint_shell status: na - task: lint_typescript_declarations status: na - task: lint_typescript_tests status: na - task: lint_license_headers status: passed ---
1 parent 6aedb56 commit e848427

File tree

1 file changed

+57
-41
lines changed
  • lib/node_modules/@stdlib/fft/base/fftpack/lib

1 file changed

+57
-41
lines changed

lib/node_modules/@stdlib/fft/base/fftpack/lib/radf2.js

Lines changed: 57 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -250,27 +250,20 @@ function radf2( M, L, cc, sc, oc, out, so, oo, twiddles, st, ot ) { // eslint-di
250250
var i;
251251
var k;
252252

253-
/*
253+
/**
254254
* First, perform the core butterfly for each sub-sequence being transformed.
255255
*
256-
* In the following loop, we FIXME: ????
257-
258-
* Input rows (length-M complex vectors, Re/Im interleaved):
259-
*
260-
* row0 = even + odd = [a0, b0, a1, b1, …]
261-
* row1 = even − odd = [c0, d0, c1, d1, …]
262-
*
263-
* For n = 0 (elements i = 0,1) the twiddle factor is +1, so
256+
* In the following loop, we handle harmonic `n = 0` for every transform. As described for `iptr`, the input array is interpreted as a three-dimensional array, containing two "rows" per sub-sequence.
264257
*
265-
* E₀ = ½(row0 + row1) and O₀ = ½(row0 − row1)
258+
* row0 = even + odd (j = 0)
259+
* row1 = even - odd (j = 1)
266260
*
267-
* The forward radix-2 butterfly stores two **columns**:
261+
* For a radix-2 forward FFT of a real-valued signal `x` and `n = 0`,
268262
*
269-
* CH(1,1,K) ← row0 + row1 ⟶ optr( 0 , 0, k, … )
270-
* CH(IDO,2,K) ← row0 − row1 ⟶ optr( M-1 , 1, k, … )
263+
* x[0] = row0 + row1 = 2⋅even
264+
* x[M] = row0 - row1 = 2⋅odd
271265
*
272-
* i.e. column j = 0 holds “even + odd” starting at i = 0,
273-
* column j = 1 holds “even − odd” starting at i = M-1.
266+
* Because `W_N^0 = 1`, no twiddle multiplication is necessary.
274267
*/
275268
for ( k = 0; k < L; k++ ) {
276269
ip1 = iptr( 0, k, 0, L, M, sc, oc ); // real part row 0
@@ -286,10 +279,19 @@ function radf2( M, L, cc, sc, oc, out, so, oo, twiddles, st, ot ) { // eslint-di
286279
if ( M < 2 ) {
287280
return;
288281
}
289-
/*
290-
* Next, apply the general case where we need to loop through the non-trivial harmonics of each complex sub-vector.
282+
/**
283+
* Next, apply the general case where we need to loop through the non-trivial harmonics.
284+
*
285+
* For each harmonic `n = 1, ..., M/2-1`, we need to
286+
*
287+
* - recover even/odd spectra from the two input rows.
288+
* - multiply the odd part by the twiddle factor `W_n = cos(θ) - j sin(θ)`.
289+
* - form the following
290+
*
291+
* x[2n] = E_n + W_n⋅O_n => column 0
292+
* x[2n+1] = E_n - W_n⋅O_n => column 1
291293
*
292-
* // FIXME: complete extended description
294+
* The mirror index `im = M + 1 - i` selects the conjugate-symmetric partner, thus allowing the routine to read each symmetry pair only once.
293295
*/
294296
if ( M >= 3 ) {
295297
MP1 = M + 1;
@@ -298,49 +300,63 @@ function radf2( M, L, cc, sc, oc, out, so, oo, twiddles, st, ot ) { // eslint-di
298300
for ( k = 0; k < L; k++ ) {
299301
// Loop over the elements in each sub-sequence...
300302
for ( i = 2; i < M; i += 2 ) {
301-
im = MP1 - i; // "mirror" index => ????
303+
im = MP1 - i; // "mirror" index
302304

303-
it1 = ( (i-1)*st ) + ot; // ????
304-
it2 = ( i*st ) + ot; // ????
305+
// Resolve twiddle factor indices:
306+
it1 = ( (i-1)*st ) + ot; // cos(θ)
307+
it2 = ( i*st ) + ot; // sin(θ)
305308

306-
ip1 = iptr( i, k, 1, L, M, sc, oc ); // ????
307-
ip2 = iptr( i+1, k, 1, L, M, sc, oc ); // ????
308-
tr2 = ( twiddles[ it1 ] * cc[ ip1 ] ) + ( twiddles[ it2 ] * cc[ ip2 ] ); // ????
309-
ti2 = ( twiddles[ it1 ] * cc[ ip2 ] ) - ( twiddles[ it2 ] * cc[ ip1 ] ); // ????
309+
// Load the `even-odd` row...
310+
ip1 = iptr( i, k, 1, L, M, sc, oc ); // c = Re(row1)
311+
ip2 = iptr( i+1, k, 1, L, M, sc, oc ); // d = Im(row1)
310312

311-
ip1 = iptr( i+1, k, 0, L, M, sc, oc ); // ????
312-
io = optr( i+1, 0, k, M, so, oo ); // ????
313-
out[ io ] = cc[ ip1 ] + ti2; // ????
313+
// tmp = W_n ⋅ (c + j⋅d)
314+
tr2 = ( twiddles[ it1 ] * cc[ ip1 ] ) + ( twiddles[ it2 ] * cc[ ip2 ] ); // Re(tmp)
315+
ti2 = ( twiddles[ it1 ] * cc[ ip2 ] ) - ( twiddles[ it2 ] * cc[ ip1 ] ); // Im(tmp)
314316

315-
io = optr( im, 1, k, M, so, oo ); // ????
316-
out[ io ] = ti2 - cc[ ip1 ]; // ????
317+
// Load the `even+odd` row...
318+
ip1 = iptr( i+1, k, 0, L, M, sc, oc ); // b = Im(row0)
319+
io = optr( i+1, 0, k, M, so, oo ); // Im(x[2n])
320+
out[ io ] = cc[ ip1 ] + ti2;
317321

318-
ip1 = iptr( i, k, 0, L, M, sc, oc ); // ????
319-
io = optr( i, 0, k, M, so, oo ); // ????
320-
out[ io ] = cc[ ip1 ] + tr2; // ????
322+
io = optr( im, 1, k, M, so, oo ); // Im(x[2n+1])
323+
out[ io ] = ti2 - cc[ ip1 ];
321324

322-
io = optr( im-1, 1, k, M, so, oo ); // ????
323-
out[ io ] = cc[ ip1 ] - tr2; // ????
325+
ip1 = iptr( i, k, 0, L, M, sc, oc ); // a = Re(row0)
326+
io = optr( i, 0, k, M, so, oo ); // Re(x[2n])
327+
out[ io ] = cc[ ip1 ] + tr2;
328+
329+
io = optr( im-1, 1, k, M, so, oo ); // Re(x[2n+1])
330+
out[ io ] = cc[ ip1 ] - tr2;
324331
}
325332
}
326-
// When `M` is odd, there is no Nyquist pair to process, and, thus, the central element is purely real and was handled in the very first butterfly, so we do not need to perform any further transformations...
333+
// When `M` is odd, there is no Nyquist pair to process, so we do not need to perform any further transformations...
327334
if ( M%2 === 1 ) {
328335
return;
329336
}
330337
}
331-
/*
338+
/**
332339
* Lastly, handle the Nyquist frequency where `i = M-1` (i.e., the last element of each sub-sequence).
333340
*
334341
* When `M` is even, the Nyquist index is `i = M/2`. In this stage, we've stored that element at the end of each sub-sequence (i.e., `i = M-1` in the packed layout).
335342
*
336-
* At this point, FIXME: ????
343+
* At this point, the cosine term is -1 and the sine term is 0, so the twiddle multiplication collapses to simple addition/subtraction.
344+
*
345+
* In this case,
346+
*
347+
* W_n⋅O_n = ±Re(O_n)
348+
*
349+
* where
350+
*
351+
* row0 = Re(E_n)
352+
* row1 = -Re(O_n)
337353
*/
338354
for ( k = 0; k < L; k++ ) {
339-
ip1 = iptr( M-1, k, 1, L, M, sc, oc );
355+
ip1 = iptr( M-1, k, 1, L, M, sc, oc ); // -Re(O_n)
340356
io = optr( 0, 1, k, M, so, oo );
341-
out[ io ] = -cc[ ip1 ];
357+
out[ io ] = -cc[ ip1 ]; // -(-Re(O_n)) = Re(O_n)
342358

343-
ip1 = iptr( M-1, k, 0, L, M, sc, oc );
359+
ip1 = iptr( M-1, k, 0, L, M, sc, oc ); // Re(E_n)
344360
io = optr( M-1, 0, k, M, so, oo );
345361
out[ io ] = cc[ ip1 ];
346362
}

0 commit comments

Comments
 (0)