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

Code before:
{
    output.create(input.dims, input.size.p, input.type());
    const size_t numElements = input.total();

    const T* inputPtr = input.ptr<T>();
    T* outputPtr = output.ptr<T>();

    if (shift.total() == 1)
    {
        T shiftScalar = 0;
        tensorToScalar(shift, CvTypeConst, &shiftScalar);
        parallel_for_(Range(0, (int)numElements), [&](const Range& r){
            for (int i = r.start; i < r.end; ++i)
                outputPtr[i] = doShift<T,T>(inputPtr[i], shiftScalar, direction, BitWidth);
        });
    }
    else
    {
        CV_Assert(shift.size == input.size);
        const T* shiftPtr = nullptr;
        Mat shiftTmp;
        if (shift.type() == CvTypeConst)
            shiftPtr = shift.ptr<T>();
        else
        {
            shift.convertTo(shiftTmp, CvTypeConst);
            shiftPtr = shiftTmp.ptr<T>();
        }
        parallel_for_(Range(0, (int)numElements), [&](const Range& r){
            for (int i = r.start; i < r.end; ++i)
                outputPtr[i] = doShift<T,T>(inputPtr[i], shiftPtr[i], direction, BitWidth);
        });
    }
}

class BitShiftLayerImpl CV_FINAL : public BitShiftLayer
{
    int direction_; // 0=LEFT, 1=RIGHT

public:
    BitShiftLayerImpl(const LayerParams& params)
    {
        setParamsFrom(params);
        direction_ = params.get<int>("direction", 0);
    }

    bool supportBackend(int backendId) CV_OVERRIDE
    {
        return backendId == DNN_BACKEND_OPENCV;
    }


Review comment (suggestion):
extra conversion into a temporary array is too big overhead for such a simple operation. Please, rewrite it to avoid the use of temporary array.

Code after:

template<typename T, int CvTypeConst, int BitWidth>
void runBitShift(const Mat& input, const Mat& shift, Mat& output, int direction)
{
    output.create(input.dims, input.size.p, input.type());
    const size_t numElements = input.total();

    const T* inputPtr = input.ptr<T>();
    T* outputPtr = output.ptr<T>();

    if (shift.total() == 1)
    {
        T shiftScalar = 0;
        tensorToScalar(shift, CvTypeConst, &shiftScalar);
        parallel_for_(Range(0, (int)numElements), [&](const Range& r){
            for (int i = r.start; i < r.end; ++i)
                outputPtr[i] = doShift<T,T>(inputPtr[i], shiftScalar, direction, BitWidth);
        });
    }
    else
    {
        CV_Assert(shift.size == input.size);
        CV_Assert(shift.type() == CvTypeConst);
        const T* shiftPtr = shift.ptr<T>();
        parallel_for_(Range(0, (int)numElements), [&](const Range& r){
            for (int i = r.start; i < r.end; ++i)
                outputPtr[i] = doShift<T,T>(inputPtr[i], shiftPtr[i], direction, BitWidth);
        });
    }
}

class BitShiftLayerImpl CV_FINAL : public BitShiftLayer
{
    int direction_; // 0=LEFT, 1=RIGHT

public:
    BitShiftLayerImpl(const LayerParams& params)
    {
        setParamsFrom(params);
        direction_ = params.get<int>("direction", 0);
    }

    bool supportBackend(int backendId) CV_OVERRIDE
    {
        return backendId == DNN_BACKEND_OPENCV;
    }

    bool getMemoryShapes(const std::vector<MatShape>& inputs, const int requiredOutputs,
                         std::vector<MatShape>& outputs, std::vector<MatShape>& internals) const CV_OVERRIDE
    {
        CV_Assert(inputs.size() >= 2);