@@ -92,6 +92,13 @@ struct dft_stage
92
92
{
93
93
do_execute (cinvert_t (), out, in, temp);
94
94
}
95
+ KFR_MEM_INTRINSIC void execute (bool inverse, complex<T>* out, const complex<T>* in, u8 * temp)
96
+ {
97
+ if (inverse)
98
+ do_execute (cinvert_t (), out, in, temp);
99
+ else
100
+ do_execute (cdirect_t (), out, in, temp);
101
+ }
95
102
virtual ~dft_stage () {}
96
103
97
104
protected:
@@ -155,6 +162,12 @@ using fn_transpose = void (*)(complex<T>*, const complex<T>*, shape<2>);
155
162
template <typename T>
156
163
void dft_initialize_transpose (fn_transpose<T>& transpose);
157
164
165
+ template <typename T>
166
+ void dft_progressive_start (const dft_plan<T>& plan, typename dft_plan<T>::progressive& progressive,
167
+ bool inverse, complex<T>* out, const complex<T>* in, u8 * temp);
168
+ template <typename T>
169
+ void dft_progressive_step (const dft_plan<T>& plan, typename dft_plan<T>::progressive& progressive);
170
+
158
171
} // namespace internal_generic
159
172
160
173
/* *
@@ -232,9 +245,10 @@ struct dft_plan
232
245
*
233
246
* @param size The size of the DFT.
234
247
* @param order The order of the DFT samples. See `dft_order`.
248
+ * @param progressive_optimized If true, the plan will be optimized for progressive execution.
235
249
*/
236
- explicit dft_plan (size_t size, dft_order order = dft_order::normal)
237
- : size(size), temp_size(0 ), data_size(0 ), arblen(false )
250
+ explicit dft_plan (size_t size, dft_order order = dft_order::normal, bool progressive_optimized = false )
251
+ : size(size), temp_size(0 ), data_size(0 ), arblen(false ), progressive_optimized(progressive_optimized)
238
252
{
239
253
internal_generic::dft_initialize (*this );
240
254
}
@@ -369,6 +383,7 @@ struct dft_plan
369
383
std::vector<dft_stage_ptr<T>> all_stages; /* *< Internal data. */
370
384
std::array<std::vector<dft_stage<T>*>, 2 > stages; /* *< Internal data. */
371
385
bool arblen; /* *< True if Bluestein's FFT algorithm is selected. */
386
+ bool progressive_optimized; /* *< True if the plan is for progressive execution of the DFT. */
372
387
using bitset = std::bitset<DFT_MAX_STAGES>; /* *< Internal typedef. */
373
388
std::array<bitset, 2 > disposition_inplace; /* *< Internal data. */
374
389
std::array<bitset, 2 > disposition_outofplace; /* *< Internal data. */
@@ -380,12 +395,64 @@ struct dft_plan
380
395
static bitset precompute_disposition (int num_stages, bitset can_inplace_per_stage,
381
396
bool inplace_requested);
382
397
398
+ /* * Internal data structure for progressive execution of the DFT.
399
+ Do not access the members directly as they may change in future versions.
400
+ */
401
+ struct progressive
402
+ {
403
+ bool inverse;
404
+ complex<T>* out;
405
+ const complex<T>* in;
406
+ u8 * temp;
407
+ bitset disposition;
408
+ complex<T>* scratch;
409
+ size_t step = 0 ;
410
+ };
411
+
412
+ // / @brief Returns the number of steps for progressive execution of the DFT.
413
+ // / @return The number of steps for progressive execution.
414
+ size_t progressive_total_steps () const ;
415
+
416
+ /* *
417
+ * @brief Initiates the progressive execution of the DFT.
418
+ * @param inverse If true, applies the inverse DFT.
419
+ * @param out Pointer to the output data.
420
+ * @param in Pointer to the input data.
421
+ * @param temp Temporary (scratch) buffer. A scratch buffer of size
422
+ * `plan->temp_size` must be provided.
423
+ * @return A `progressive` structure that can be used with `progressive_step`.
424
+ * @note Ensure that the entire input data is available in the `in` buffer before calling this function.
425
+ * The `out` buffer will contain the result data after the final step of the progressive execution.
426
+ */
427
+ KFR_MEM_INTRINSIC progressive progressive_start (bool inverse, complex<T>* out, const complex<T>* in,
428
+ u8 * temp) const
429
+ {
430
+ KFR_LOGIC_CHECK (is_initialized (), " dft_plan is not initialized" );
431
+ KFR_LOGIC_CHECK (temp_size == 0 || temp != nullptr ,
432
+ " Temporary buffer must be provided for progressive execution" );
433
+ progressive result{};
434
+ internal_generic::dft_progressive_start (*this , result, inverse, out, in, temp);
435
+ return result;
436
+ }
437
+
438
+ /* *
439
+ * @brief Steps the progressive execution of the DFT.
440
+ * @param progressive A `progressive` structure returned by `progressive_start`.
441
+ * @return `true` if there are more steps to execute, `false` if the DFT is complete.
442
+ */
443
+ KFR_MEM_INTRINSIC bool progressive_step (progressive& progressive) const
444
+ {
445
+ internal_generic::dft_progressive_step (*this , progressive);
446
+ return ++progressive.step < stages[progressive.inverse ].size ();
447
+ }
448
+
383
449
protected:
384
450
struct noinit
385
451
{
386
452
};
387
- explicit dft_plan (noinit, size_t size, dft_order order = dft_order::normal)
388
- : size(size), temp_size(0 ), data_size(0 ), arblen(false )
453
+ explicit dft_plan (noinit, size_t size, dft_order order = dft_order::normal,
454
+ bool progressive_optimized = false )
455
+ : size(size), temp_size(0 ), data_size(0 ), arblen(false ), progressive_optimized(progressive_optimized)
389
456
{
390
457
}
391
458
@@ -426,8 +493,10 @@ struct dft_plan_real : dft_plan<T>
426
493
(void )cpu;
427
494
}
428
495
429
- explicit dft_plan_real (size_t size, dft_pack_format fmt = dft_pack_format::CCs)
430
- : dft_plan<T>(typename dft_plan<T>::noinit{}, size / 2 ), size(size), fmt(fmt)
496
+ explicit dft_plan_real (size_t size, dft_pack_format fmt = dft_pack_format::CCs,
497
+ bool progressive_optimized = false )
498
+ : dft_plan<T>(typename dft_plan<T>::noinit{}, size / 2 , dft_order::normal, progressive_optimized),
499
+ size(size), fmt(fmt)
431
500
{
432
501
KFR_LOGIC_CHECK (is_even (size), " dft_plan_real requires size to be even" );
433
502
internal_generic::dft_real_initialize (*this );
@@ -488,6 +557,28 @@ struct dft_plan_real : dft_plan<T>
488
557
{
489
558
this ->execute_dft (ctrue, ptr_cast<complex<T>>(out.data ()), in.data (), temp);
490
559
}
560
+
561
+ using progressive = typename dft_plan<T>::progressive;
562
+
563
+ KFR_MEM_INTRINSIC progressive progressive_start (T* out, const complex<T>* in, u8 * temp) const
564
+ {
565
+ KFR_LOGIC_CHECK (is_initialized (), " dft_plan_real is not initialized" );
566
+ KFR_LOGIC_CHECK (this ->temp_size == 0 || temp != nullptr ,
567
+ " Temporary buffer must be provided for progressive execution" );
568
+ progressive result{};
569
+ internal_generic::dft_progressive_start (*this , result, true , ptr_cast<complex<T>>(out), in, temp);
570
+ return result;
571
+ }
572
+ KFR_MEM_INTRINSIC progressive progressive_start (complex<T>* out, const T* in, u8 * temp) const
573
+ {
574
+ KFR_LOGIC_CHECK (is_initialized (), " dft_plan_real is not initialized" );
575
+ KFR_LOGIC_CHECK (this ->temp_size == 0 || temp != nullptr ,
576
+ " Temporary buffer must be provided for progressive execution" );
577
+ progressive result{};
578
+ internal_generic::dft_progressive_start (*this , result, false , out, ptr_cast<const complex<T>>(in),
579
+ temp);
580
+ return result;
581
+ }
491
582
};
492
583
493
584
// / @brief Multidimensional DFT
0 commit comments