Repository: opencv/opencv
File: modules/dnn/src/layers/dft_layer.cpp (C++)

Code before:
#include "../precomp.hpp"
#include <opencv2/dnn/shape_utils.hpp>
#include <opencv2/core.hpp>
#include <numeric>

// ONNX DFT operator
// Spec: https://onnx.ai/onnx/operators/onnx__DFT.html
// Supported opset: 17-22

namespace cv {
namespace dnn {

template<typename Scalar, typename ComplexVec, typename FillFn>
static void dftAlongAxisWorker(const Mat& src,
                               Mat& dst,
                               const std::vector<int>& dimSizesSrc,
                               const std::vector<size_t>& stridesSrc,
                               const std::vector<size_t>& stridesDst,
                               const std::vector<int>& iterDims,
                               const std::vector<int>& outerSizes,
                               const std::vector<size_t>& outerStep,
                               const size_t totalOuter,
                               const int axis,
                               const int N,
                               const size_t strideAxisSrc,
                               const size_t strideAxisDst,
                               const int inMatType,
                               const int flagsBase,
                               const bool inverse,
                               FillFn&& fill)
{
    const Scalar* sp = src.ptr<Scalar>();
    Scalar* dp = dst.ptr<Scalar>();
    cv::parallel_for_(Range(0, (int)totalOuter), [&](const Range& r){
        Mat inRow(1, N, inMatType);
        for (int pos = r.start; pos < r.end; ++pos)
        {
            size_t baseSrc = 0;
            size_t baseDst = 0;
            for (size_t t = 0; t < iterDims.size(); ++t)
            {
                int idxVal = outerStep.empty() ? 0 : (int)((pos / outerStep[t]) % (size_t)outerSizes[t]);
                int d = iterDims[t];
                baseSrc += (size_t)idxVal * stridesSrc[d];
                baseDst += (size_t)idxVal * stridesDst[d];
            }
            const Scalar* in = sp + baseSrc;
            Scalar* out = dp + baseDst;
            fill(inRow, in, dimSizesSrc[axis], N, strideAxisSrc);
            Mat outRow;
            int flags = flagsBase | (inverse ? (DFT_INVERSE | DFT_SCALE) : 0);

Review comment (performance):
just add `bool onesided` parameter here and inside function compute `int Nout = onesided ? (N+1)/2 : N;`

Code after:
#include "../precomp.hpp"
#include <opencv2/dnn/shape_utils.hpp>
#include <opencv2/core.hpp>
#include "../net_impl.hpp"
#include "layers_common.hpp"
#include <numeric>

// ONNX DFT operator
// Spec: https://onnx.ai/onnx/operators/onnx__DFT.html
// Supported opset: 17-22

namespace cv {
namespace dnn {

template<typename T, typename ComplexVec, typename FillFn>
static void dftAlongAxisWorker(const Mat& src,
                               Mat& dst,
                               const std::vector<int>& dimSizesSrc,
                               const std::vector<size_t>& stridesSrc,
                               const std::vector<size_t>& stridesDst,
                               const std::vector<int>& iterDims,
                               const std::vector<int>& outerSizes,
                               const std::vector<size_t>& outerStep,
                               const size_t totalOuter,
                               const int axis,
                               const int N,
                               const int outN,
                               const size_t strideAxisSrc,
                               const size_t strideAxisDst,
                               const int inMatType,
                               const int flagsBase,
                               const bool inverse,
                               FillFn&& fill)
{
    const T* sp = src.ptr<T>();
    T* dp = dst.ptr<T>();
    cv::parallel_for_(Range(0, (int)totalOuter), [&](const Range& r){
        Mat inRow(1, N, inMatType);
        Mat outRow;
        for (int pos = r.start; pos < r.end; ++pos)
        {
            size_t baseSrc = 0;
            size_t baseDst = 0;
            for (size_t t = 0; t < iterDims.size(); ++t)
            {
                int idxVal = outerStep.empty() ? 0 : (int)((pos / outerStep[t]) % (size_t)outerSizes[t]);
                int d = iterDims[t];
                baseSrc += (size_t)idxVal * stridesSrc[d];
                baseDst += (size_t)idxVal * stridesDst[d];
            }
            const T* in = sp + baseSrc;