@@ -2530,16 +2530,16 @@ class RFFT {
25302530 output[N / 2 ].im = 0.0 ;
25312531 }
25322532
2533- const int * RESTRICT kin = KINV .data ();
2534- for (int k = 1 ; k < N / 2 ; ++k) {
2535- const int m = kin[k];
2533+ // Walk Bruun residues in their native linear order. This keeps the hot
2534+ // work-buffer reads streaming and mirrors inverse_mag_phase's read
2535+ // order through the standard mag-phase buffer during round trips.
2536+ const int * RESTRICT standard_bin = IDX .data ();
2537+ for (int m = 1 ; m < N / 2 ; ++m) {
2538+ const int k = standard_bin[m];
25362539 const double re = work[2 *m];
25372540 const double im = -work[2 *m + 1 ];
25382541 const double mag = std::sqrt (re * re + im * im);
2539- double phase = bruun_phase_atan2_mag (im, re, mag);
2540- if (phase < 0.0 ) {
2541- phase += 2.0 * M_PI ;
2542- }
2542+ const double phase = bruun_phase_atan2_mag (im, re, mag);
25432543 output[k].re = mag;
25442544 output[k].im = phase;
25452545 }
@@ -2586,16 +2586,14 @@ class RFFT {
25862586 output[N / 2 ].im = 0 .0f ;
25872587 }
25882588
2589- const int * RESTRICT kin = KINV .data ();
2590- for (int k = 1 ; k < N / 2 ; ++k) {
2591- const int m = kin[k];
2589+ // Match the double path's residue-linear traversal for cache locality.
2590+ const int * RESTRICT standard_bin = IDX .data ();
2591+ for (int m = 1 ; m < N / 2 ; ++m) {
2592+ const int k = standard_bin[m];
25922593 const float re = work[2 *m];
25932594 const float im = -work[2 *m + 1 ];
25942595 const float mag = std::sqrt (re * re + im * im);
2595- float phase = bruun_phase_atan2_mag_f32 (im, re, mag);
2596- if (phase < 0 .0f ) {
2597- phase += 2 .0f * static_cast <float >(M_PI );
2598- }
2596+ const float phase = bruun_phase_atan2_mag_f32 (im, re, mag);
25992597 output[k].re = mag;
26002598 output[k].im = phase;
26012599 }
0 commit comments