1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-21 19:33:03 +04:00

Merge branch 4.x

This commit is contained in:
Alexander Smorkalov
2025-03-11 16:38:05 +03:00
306 changed files with 9362 additions and 19775 deletions
+3 -3
View File
@@ -247,15 +247,15 @@ int fastcv_hal_cvtBGRtoYUVApprox(
/// @param width Source image width
/// @param height Source image height
/// @param cn Number of channels
/// @param lowThreshold low hresholds value
/// @param lowThreshold low thresholds value
/// @param highThreshold high thresholds value
/// @param ksize Kernel size for Sobel operator.
/// @param L2gradient Flag, indicating use of L2 or L1 norma.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int fastcv_hal_canny(
const uchar* src_data,
const uchar* src_data,
size_t src_step,
uchar* dst_data,
uchar* dst_data,
size_t dst_step,
int width,
int height,
+35 -75
View File
@@ -75,13 +75,13 @@ class FcvSobelLoop_Invoker : public cv::ParallelLoopBody
// Need additional lines to be border.
if(range.start > 0)
{
topLines += halfKernelSize;
paddedHeight += halfKernelSize;
topLines += MIN(range.start, halfKernelSize);
paddedHeight += MIN(range.start, halfKernelSize);
}
if(range.end < height)
{
paddedHeight += halfKernelSize;
paddedHeight += MIN(height-range.end, halfKernelSize);
}
cv::Mat srcPadded = src(cv::Rect(0, range.start-topLines, width, paddedHeight));
@@ -305,8 +305,9 @@ int fastcv_hal_sobel(
else
{
int nThreads = cv::getNumThreads();
int nStripes = nThreads > 1 ? 3*nThreads : 1;
// In each stripe, the height should be equal or larger than ksize.
// Use 3*nThreads stripes to avoid too many threads.
int nStripes = nThreads > 1 ? MIN(height / (int)ksize, 3 * nThreads) : 1;
cv::parallel_for_(cv::Range(0, height), FcvSobelLoop_Invoker(src, dst, dx, dy, ksize, fcvBorder, 0), nStripes);
}
@@ -466,47 +467,30 @@ class FcvGaussianBlurLoop_Invoker : public cv::ParallelLoopBody
{
public:
FcvGaussianBlurLoop_Invoker(const cv::Mat& _src, cv::Mat& _dst, int _ksize, fcvBorderType _fcvBorder, int _fcvBorderValue) :
cv::ParallelLoopBody(), src(_src),dst(_dst), ksize(_ksize), fcvBorder(_fcvBorder), fcvBorderValue(_fcvBorderValue)
FcvGaussianBlurLoop_Invoker(const cv::Mat& _src, cv::Mat& _dst, int _ksize, int _borderType, int _fcvBorderValue) :
cv::ParallelLoopBody(), src(_src),dst(_dst), ksize(_ksize), borderType(_borderType), fcvBorderValue(_fcvBorderValue)
{
width = src.cols;
height = src.rows;
halfKernelSize = ksize / 2;
halfKSize = ksize / 2;
fcvFuncType = FCV_MAKETYPE(ksize, src.depth());
}
virtual void operator()(const cv::Range& range) const CV_OVERRIDE
{
int topLines = 0;
int rangeHeight = range.end-range.start;
int paddedHeight = rangeHeight;
int rangeHeight = range.end - range.start;
int paddedHeight = rangeHeight + halfKSize * 2;
int paddedWidth = width;
// Need additional lines to be border.
if(range.start != 0)
{
topLines += halfKernelSize;
paddedHeight += halfKernelSize;
}
if(range.end != height)
{
paddedHeight += halfKernelSize;
}
const cv::Mat srcPadded = src(cv::Rect(0, range.start - topLines, width, paddedHeight));
cv::Mat dstPadded = cv::Mat(paddedHeight, width, CV_8U);
cv::Mat srcPadded = src(cv::Rect(0, range.start, paddedWidth, paddedHeight));
cv::Mat dstPadded = dst(cv::Rect(0, range.start, paddedWidth, paddedHeight));
if (fcvFuncType == FCV_MAKETYPE(3,CV_8U))
fcvFilterGaussian3x3u8_v4(srcPadded.data, width, paddedHeight, srcPadded.step, dstPadded.data, dstPadded.step,
fcvBorder, 0);
fcvFilterGaussian3x3u8_v4(srcPadded.data, paddedWidth, paddedHeight, srcPadded.step, dstPadded.data, dstPadded.step,
fcvBorderType::FASTCV_BORDER_UNDEFINED, fcvBorderValue);
else if (fcvFuncType == FCV_MAKETYPE(5,CV_8U))
fcvFilterGaussian5x5u8_v3(srcPadded.data, width, paddedHeight, srcPadded.step, dstPadded.data, dstPadded.step,
fcvBorder, 0);
// Only copy center part back to output image and ignore the padded lines
cv::Mat temp1 = dstPadded(cv::Rect(0, topLines, width, rangeHeight));
cv::Mat temp2 = dst(cv::Rect(0, range.start, width, rangeHeight));
temp1.copyTo(temp2);
fcvFilterGaussian5x5u8_v3(srcPadded.data, paddedWidth, paddedHeight, srcPadded.step, dstPadded.data, dstPadded.step,
fcvBorderType::FASTCV_BORDER_UNDEFINED, fcvBorderValue);
}
private:
@@ -515,9 +499,9 @@ class FcvGaussianBlurLoop_Invoker : public cv::ParallelLoopBody
int width;
int height;
const int ksize;
int halfKernelSize;
int halfKSize;
int fcvFuncType;
fcvBorderType fcvBorder;
int borderType;
int fcvBorderValue;
FcvGaussianBlurLoop_Invoker(const FcvGaussianBlurLoop_Invoker &); // = delete;
@@ -544,9 +528,9 @@ int fastcv_hal_gaussianBlurBinomial(
if (src_data == dst_data)
CV_HAL_RETURN_NOT_IMPLEMENTED("Inplace is not supported");
// The input image width and height should greater than kernel size
if (((size_t)height <= ksize) || ((size_t)width <= ksize))
CV_HAL_RETURN_NOT_IMPLEMENTED("Input image size should be larger than kernel size");
// The pixels of input image should larger than 320*240
if((width*height) < (320*240))
CV_HAL_RETURN_NOT_IMPLEMENTED("Input image size should be larger than 320*240");
// The input channel should be 1
if (cn != 1)
@@ -559,35 +543,7 @@ int fastcv_hal_gaussianBlurBinomial(
INITIALIZATION_CHECK;
fcvStatus status = FASTCV_SUCCESS;
fcvBorderType fcvBorder = fcvBorderType::FASTCV_BORDER_UNDEFINED;
int fcvFuncType = FCV_MAKETYPE(ksize,depth);
switch (border_type)
{
case cv::BorderTypes::BORDER_REPLICATE:
{
fcvBorder = fcvBorderType::FASTCV_BORDER_REPLICATE;
break;
}
// For constant border, there are no border value, OpenCV default value is 0
case cv::BorderTypes::BORDER_CONSTANT:
{
fcvBorder = fcvBorderType::FASTCV_BORDER_CONSTANT;
break;
}
case cv::BorderTypes::BORDER_REFLECT:
{
fcvBorder = fcvBorderType::FASTCV_BORDER_REFLECT;
break;
}
case cv::BorderTypes::BORDER_REFLECT_101:
{
fcvBorder = fcvBorderType::FASTCV_BORDER_REFLECT_V2;
break;
}
default:
CV_HAL_RETURN_NOT_IMPLEMENTED(cv::format("Border type:%s is not supported", borderToString(border_type)));
}
int fcvFuncType = FCV_MAKETYPE(ksize, depth);
int nThreads = cv::getNumThreads();
int nStripes = (nThreads > 1) ? ((height > 60) ? 3 * nThreads : 1) : 1;
@@ -597,9 +553,13 @@ int fastcv_hal_gaussianBlurBinomial(
case FCV_MAKETYPE(3,CV_8U):
case FCV_MAKETYPE(5,CV_8U):
{
cv::Mat src = cv::Mat(height, width, CV_8UC1, (void*)src_data, src_step);
cv::Mat dst = cv::Mat(height, width, CV_8UC1, (void*)dst_data, dst_step);
cv::parallel_for_(cv::Range(0, height), FcvGaussianBlurLoop_Invoker(src, dst, ksize, fcvBorder, 0), nStripes);
cv::Mat src = cv::Mat(height, width, CV_8UC1, (void *)src_data, src_step);
cv::Mat dst = cv::Mat(height, width, CV_8UC1, (void *)dst_data, dst_step);
cv::Mat src_tmp = cv::Mat(height + ksize - 1, width + ksize - 1, CV_8UC1);
cv::Mat dst_tmp = cv::Mat(height + ksize - 1, width + ksize - 1, CV_8UC1);
cv::copyMakeBorder(src, src_tmp, ksize / 2, ksize / 2, ksize / 2, ksize / 2, border_type);
cv::parallel_for_(cv::Range(0, height), FcvGaussianBlurLoop_Invoker(src_tmp, dst_tmp, ksize, border_type, 0), nStripes);
dst_tmp(cv::Rect(ksize / 2, ksize / 2, width, height)).copyTo(dst);
break;
}
default:
@@ -1017,10 +977,10 @@ int fastcv_hal_canny(
if (lowThreshold > highThreshold)
CV_HAL_RETURN_NOT_IMPLEMENTED("lowThreshold is greater then highThreshold");
const double epsilon = 1e-9;
if (std::abs(lowThreshold - std::round(lowThreshold)) > epsilon || std::abs(highThreshold - std::round(highThreshold)) > epsilon)
const double epsilon = 1e-9;
if (std::abs(lowThreshold - std::round(lowThreshold)) > epsilon || std::abs(highThreshold - std::round(highThreshold)) > epsilon)
CV_HAL_RETURN_NOT_IMPLEMENTED("threshold with decimal values not supported");
INITIALIZATION_CHECK;
+12
View File
@@ -22,6 +22,7 @@
#if defined(__riscv_v) && __riscv_v == 1000000
#include "hal_rvv_1p0/merge.hpp" // core
#include "hal_rvv_1p0/mean.hpp" // core
#include "hal_rvv_1p0/dxt.hpp" // core
#include "hal_rvv_1p0/norm.hpp" // core
#include "hal_rvv_1p0/norm_diff.hpp" // core
#include "hal_rvv_1p0/norm_hamming.hpp" // core
@@ -30,6 +31,17 @@
#include "hal_rvv_1p0/atan.hpp" // core
#include "hal_rvv_1p0/split.hpp" // core
#include "hal_rvv_1p0/flip.hpp" // core
#include "hal_rvv_1p0/lut.hpp" // core
#include "hal_rvv_1p0/exp.hpp" // core
#include "hal_rvv_1p0/log.hpp" // core
#include "hal_rvv_1p0/lu.hpp" // core
#include "hal_rvv_1p0/cholesky.hpp" // core
#include "hal_rvv_1p0/qr.hpp" // core
#include "hal_rvv_1p0/svd.hpp" // core
#include "hal_rvv_1p0/filter.hpp" // imgproc
#include "hal_rvv_1p0/pyramids.hpp" // imgproc
#include "hal_rvv_1p0/color.hpp" // imgproc
#endif
#endif
+121
View File
@@ -0,0 +1,121 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#ifndef OPENCV_HAL_RVV_CHOLESKY_HPP_INCLUDED
#define OPENCV_HAL_RVV_CHOLESKY_HPP_INCLUDED
#include <cmath>
#include <limits>
#include <riscv_vector.h>
#include "hal_rvv_1p0/types.hpp"
namespace cv { namespace cv_hal_rvv { namespace cholesky {
#undef cv_hal_Cholesky32f
#define cv_hal_Cholesky32f cv::cv_hal_rvv::cholesky::Cholesky<cv::cv_hal_rvv::RVV_F32M4>
#undef cv_hal_Cholesky64f
#define cv_hal_Cholesky64f cv::cv_hal_rvv::cholesky::Cholesky<cv::cv_hal_rvv::RVV_F64M4>
// the algorithm is copied from core/src/matrix_decomp.cpp,
// in the function template static int cv::CholImpl
template <typename RVV_T, typename T = typename RVV_T::ElemType>
inline int Cholesky(T* src1, size_t src1_step, int m, T* src2, size_t src2_step, int n, bool* info)
{
int i, j, k;
double s;
src1_step /= sizeof(src1[0]);
src2_step /= sizeof(src2[0]);
int vlmax = RVV_T::setvlmax(), vl;
for( i = 0; i < m; i++ )
{
for( j = 0; j < i; j++ )
{
auto vec_sum = RVV_T::vmv(0, vlmax);
for( k = 0; k < j; k += vl )
{
vl = RVV_T::setvl(j - k);
auto vec_src1 = RVV_T::vload(src1 + i * src1_step + k, vl);
auto vec_src2 = RVV_T::vload(src1 + j * src1_step + k, vl);
vec_sum = __riscv_vfmacc_tu(vec_sum, vec_src1, vec_src2, vl);
}
s = src1[i*src1_step + j] - __riscv_vfmv_f(__riscv_vfredosum(vec_sum, RVV<T, LMUL_1>::vmv_s(0, vlmax), vlmax));
src1[i*src1_step + j] = (T)(s*src1[j*src1_step + j]);
}
auto vec_sum = RVV_T::vmv(0, vlmax);
for( k = 0; k < j; k += vl )
{
vl = RVV_T::setvl(j - k);
auto vec_src = RVV_T::vload(src1 + i * src1_step + k, vl);
vec_sum = __riscv_vfmacc_tu(vec_sum, vec_src, vec_src, vl);
}
s = src1[i*src1_step + i] - __riscv_vfmv_f(__riscv_vfredosum(vec_sum, RVV<T, LMUL_1>::vmv_s(0, vlmax), vlmax));
if( s < std::numeric_limits<T>::epsilon() )
{
*info = false;
return CV_HAL_ERROR_OK;
}
src1[i*src1_step + i] = (T)(1./std::sqrt(s));
}
if (!src2)
{
for( i = 0; i < m; i += vl )
{
vl = RVV_T::setvl(m - i);
auto vec_src = RVV_T::vload_stride(src1 + i * src1_step + i, sizeof(T) * (src1_step + 1), vl);
vec_src = __riscv_vfrdiv(vec_src, 1, vl);
RVV_T::vstore_stride(src1 + i * src1_step + i, sizeof(T) * (src1_step + 1), vec_src, vl);
}
*info = true;
return CV_HAL_ERROR_OK;
}
for( i = 0; i < m; i++ )
{
for( j = 0; j < n; j++ )
{
auto vec_sum = RVV_T::vmv(0, vlmax);
for( k = 0; k < i; k += vl )
{
vl = RVV_T::setvl(i - k);
auto vec_src1 = RVV_T::vload(src1 + i * src1_step + k, vl);
auto vec_src2 = RVV_T::vload_stride(src2 + k * src2_step + j, sizeof(T) * src2_step, vl);
vec_sum = __riscv_vfmacc_tu(vec_sum, vec_src1, vec_src2, vl);
}
s = src2[i*src2_step + j] - __riscv_vfmv_f(__riscv_vfredosum(vec_sum, RVV<T, LMUL_1>::vmv_s(0, vlmax), vlmax));
src2[i*src2_step + j] = (T)(s*src1[i*src1_step + i]);
}
}
for( i = m-1; i >= 0; i-- )
{
for( j = 0; j < n; j++ )
{
auto vec_sum = RVV_T::vmv(0, vlmax);
for( k = i + 1; k < m; k += vl )
{
vl = RVV_T::setvl(m - k);
auto vec_src1 = RVV_T::vload_stride(src1 + k * src1_step + i, sizeof(T) * src1_step, vl);
auto vec_src2 = RVV_T::vload_stride(src2 + k * src2_step + j, sizeof(T) * src2_step, vl);
vec_sum = __riscv_vfmacc_tu(vec_sum, vec_src1, vec_src2, vl);
}
s = src2[i*src2_step + j] - __riscv_vfmv_f(__riscv_vfredosum(vec_sum, RVV<T, LMUL_1>::vmv_s(0, vlmax), vlmax));
src2[i*src2_step + j] = (T)(s*src1[i*src1_step + i]);
}
}
for( i = 0; i < m; i += vl )
{
vl = RVV_T::setvl(m - i);
auto vec_src = RVV_T::vload_stride(src1 + i * src1_step + i, sizeof(T) * (src1_step + 1), vl);
vec_src = __riscv_vfrdiv(vec_src, 1, vl);
RVV_T::vstore_stride(src1 + i * src1_step + i, sizeof(T) * (src1_step + 1), vec_src, vl);
}
*info = true;
return CV_HAL_ERROR_OK;
}
}}}
#endif
File diff suppressed because it is too large Load Diff
+565
View File
@@ -0,0 +1,565 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#ifndef OPENCV_HAL_RVV_DXT_HPP_INCLUDED
#define OPENCV_HAL_RVV_DXT_HPP_INCLUDED
#include <riscv_vector.h>
#include "hal_rvv_1p0/types.hpp"
#include "opencv2/core/types.hpp"
namespace cv { namespace cv_hal_rvv { namespace dxt {
#undef cv_hal_dft
#define cv_hal_dft cv::cv_hal_rvv::dxt::dft
template<typename T> struct rvv;
template<> struct rvv<float> : RVV_F32MF2
{
using T = RVV_F32MF2::VecType;
using TabType = RVV_U32M8;
using TabTypeF = RVV_SameLen<float, TabType>;
static inline void vlseg(const float* a, T& b, T& c, size_t d) { auto x = __riscv_vlseg2e32_v_f32mf2x2(a, d); b = __riscv_vget_v_f32mf2x2_f32mf2(x, 0), c = __riscv_vget_v_f32mf2x2_f32mf2(x, 1); }
static inline void vlsseg(const float* a, ptrdiff_t b, T& c, T& d, size_t e) { auto x = __riscv_vlsseg2e32_v_f32mf2x2(a, b, e); c = __riscv_vget_v_f32mf2x2_f32mf2(x, 0), d = __riscv_vget_v_f32mf2x2_f32mf2(x, 1); }
static inline void vsseg(float* a, T b, T c, size_t d) { __riscv_vsseg2e32(a, __riscv_vset_v_f32mf2_f32mf2x2(__riscv_vset_v_f32mf2_f32mf2x2(vfloat32mf2x2_t(), 0, b), 1, c), d); }
};
template<> struct rvv<double> : RVV_F64M1
{
using T = RVV_F64M1::VecType;
using TabType = RVV_U32M4;
using TabTypeF = RVV_SameLen<double, TabType>;
static inline void vlseg(const double* a, T& b, T& c, size_t d) { auto x = __riscv_vlseg2e64_v_f64m1x2(a, d); b = __riscv_vget_v_f64m1x2_f64m1(x, 0), c = __riscv_vget_v_f64m1x2_f64m1(x, 1); }
static inline void vlsseg(const double* a, ptrdiff_t b, T& c, T& d, size_t e) { auto x = __riscv_vlsseg2e64_v_f64m1x2(a, b, e); c = __riscv_vget_v_f64m1x2_f64m1(x, 0), d = __riscv_vget_v_f64m1x2_f64m1(x, 1); }
static inline void vsseg(double* a, T b, T c, size_t d) { __riscv_vsseg2e64(a, __riscv_vset_v_f64m1_f64m1x2(__riscv_vset_v_f64m1_f64m1x2(vfloat64m1x2_t(), 0, b), 1, c), d); }
};
// the algorithm is copied from core/src/dxt.cpp,
// in the function template static void cv::DFT and cv::DFT_R2, cv::DFT_R3, cv::DFT_R5
template <typename T>
inline int dft(const Complex<T>* src, Complex<T>* dst, int nf, int *factors, T scale, int* itab,
const Complex<T>* wave, int tab_size, int len, bool isInverse, bool noPermute)
{
int n = len;
int f_idx, nx;
int dw0 = tab_size, dw;
int i, j, k;
Complex<T> t;
using VT = typename rvv<T>::VecType;
using TabType = typename rvv<T>::TabType;
using TabTypeF = typename rvv<T>::TabTypeF;
int tab_step = tab_size == n ? 1 : tab_size == n*2 ? 2 : tab_size/n;
int vl;
// 0. shuffle data
if( dst != src )
{
if( !isInverse )
{
for( i = 0; i < n; i += vl )
{
vl = TabType::setvl(n - i);
auto vec_itab = TabType::vload_stride(reinterpret_cast<const uint*>(itab + i * tab_step), sizeof(int) * tab_step, vl);
vec_itab = __riscv_vmul(vec_itab, sizeof(T) * 2, vl);
auto vec_src_re = __riscv_vloxei32(reinterpret_cast<const T*>(src), vec_itab, vl);
vec_itab = __riscv_vadd(vec_itab, sizeof(T), vl);
auto vec_src_im = __riscv_vloxei32(reinterpret_cast<const T*>(src), vec_itab, vl);
TabTypeF::vstore_stride(reinterpret_cast<T*>(dst + i), sizeof(T) * 2, vec_src_re, vl);
TabTypeF::vstore_stride(reinterpret_cast<T*>(dst + i) + 1, sizeof(T) * 2, vec_src_im, vl);
}
}
else
{
for( i = 0; i < n; i += vl )
{
vl = TabType::setvl(n - i);
auto vec_itab = TabType::vload_stride(reinterpret_cast<const uint*>(itab + i * tab_step), sizeof(int) * tab_step, vl);
vec_itab = __riscv_vmul(vec_itab, sizeof(T) * 2, vl);
auto vec_src_re = __riscv_vloxei32(reinterpret_cast<const T*>(src), vec_itab, vl);
vec_itab = __riscv_vadd(vec_itab, sizeof(T), vl);
auto vec_src_im = __riscv_vloxei32(reinterpret_cast<const T*>(src), vec_itab, vl);
vec_src_im = __riscv_vfneg(vec_src_im, vl);
TabTypeF::vstore_stride(reinterpret_cast<T*>(dst + i), sizeof(T) * 2, vec_src_re, vl);
TabTypeF::vstore_stride(reinterpret_cast<T*>(dst + i) + 1, sizeof(T) * 2, vec_src_im, vl);
}
}
}
else
{
// copied from core/src/dxt.cpp, it is slow to swap elements by intrinsics
if( !noPermute )
{
if( nf == 1 )
{
if( (n & 3) == 0 )
{
int n2 = n/2;
Complex<T>* dsth = dst + n2;
for( i = 0; i < n2; i += 2, itab += tab_step*2 )
{
j = itab[0];
t = dst[i+1], dst[i+1] = dsth[j], dsth[j] = t;
if( j > i )
{
t = dst[i], dst[i] = dst[j], dst[j] = t;
t = dsth[i+1], dsth[i+1] = dsth[j+1], dsth[j+1] = t;
}
}
}
// else do nothing
}
else
{
for( i = 0; i < n; i++, itab += tab_step )
{
j = itab[0];
if( j > i )
t = dst[i], dst[i] = dst[j], dst[j] = t;
}
}
}
if( isInverse )
{
for( i = 0; i < n; i += vl )
{
vl = TabType::setvl(n - i);
auto vec_src_im = TabTypeF::vload_stride(reinterpret_cast<const T*>(dst + i) + 1, sizeof(T) * 2, vl);
vec_src_im = __riscv_vfneg(vec_src_im, vl);
TabTypeF::vstore_stride(reinterpret_cast<T*>(dst + i) + 1, sizeof(T) * 2, vec_src_im, vl);
}
}
}
n = 1;
// 1. power-2 transforms
if( (factors[0] & 1) == 0 )
{
// radix-4 transform
for( ; n*4 <= factors[0]; )
{
nx = n;
n *= 4;
dw0 /= 4;
for( i = 0; i < len; i += n )
{
Complex<T> *v0, *v1;
T r0, i0, r1, i1, r2, i2, r3, i3, r4, i4;
v0 = dst + i;
v1 = v0 + nx*2;
r0 = v1[0].re; i0 = v1[0].im;
r4 = v1[nx].re; i4 = v1[nx].im;
r1 = r0 + r4; i1 = i0 + i4;
r3 = i0 - i4; i3 = r4 - r0;
r2 = v0[0].re; i2 = v0[0].im;
r4 = v0[nx].re; i4 = v0[nx].im;
r0 = r2 + r4; i0 = i2 + i4;
r2 -= r4; i2 -= i4;
v0[0].re = r0 + r1; v0[0].im = i0 + i1;
v1[0].re = r0 - r1; v1[0].im = i0 - i1;
v0[nx].re = r2 + r3; v0[nx].im = i2 + i3;
v1[nx].re = r2 - r3; v1[nx].im = i2 - i3;
for( j = 1; j < nx; j += vl )
{
vl = rvv<T>::setvl(nx - j);
v0 = dst + i + j;
v1 = v0 + nx*2;
VT vec_re, vec_im, vec_w_re, vec_w_im;
rvv<T>::vlseg(reinterpret_cast<const T*>(v1), vec_re, vec_im, vl);
rvv<T>::vlsseg(reinterpret_cast<const T*>(wave + j * dw0), sizeof(T) * dw0 * 2, vec_w_re, vec_w_im, vl);
auto vec_r0 = __riscv_vfadd(__riscv_vfmul(vec_re, vec_w_im, vl), __riscv_vfmul(vec_im, vec_w_re, vl), vl);
auto vec_i0 = __riscv_vfsub(__riscv_vfmul(vec_re, vec_w_re, vl), __riscv_vfmul(vec_im, vec_w_im, vl), vl);
rvv<T>::vlseg(reinterpret_cast<const T*>(v1 + nx), vec_re, vec_im, vl);
rvv<T>::vlsseg(reinterpret_cast<const T*>(wave + j * dw0 * 3), sizeof(T) * dw0 * 6, vec_w_re, vec_w_im, vl);
auto vec_r3 = __riscv_vfadd(__riscv_vfmul(vec_re, vec_w_im, vl), __riscv_vfmul(vec_im, vec_w_re, vl), vl);
auto vec_i3 = __riscv_vfsub(__riscv_vfmul(vec_re, vec_w_re, vl), __riscv_vfmul(vec_im, vec_w_im, vl), vl);
auto vec_r1 = __riscv_vfadd(vec_i0, vec_i3, vl);
auto vec_i1 = __riscv_vfadd(vec_r0, vec_r3, vl);
vec_r3 = __riscv_vfsub(vec_r0, vec_r3, vl);
vec_i3 = __riscv_vfsub(vec_i3, vec_i0, vl);
VT vec_r4, vec_i4;
rvv<T>::vlseg(reinterpret_cast<const T*>(v0), vec_r4, vec_i4, vl);
rvv<T>::vlseg(reinterpret_cast<const T*>(v0 + nx), vec_re, vec_im, vl);
rvv<T>::vlsseg(reinterpret_cast<const T*>(wave + j * dw0 * 2), sizeof(T) * dw0 * 4, vec_w_re, vec_w_im, vl);
auto vec_r2 = __riscv_vfsub(__riscv_vfmul(vec_re, vec_w_re, vl), __riscv_vfmul(vec_im, vec_w_im, vl), vl);
auto vec_i2 = __riscv_vfadd(__riscv_vfmul(vec_re, vec_w_im, vl), __riscv_vfmul(vec_im, vec_w_re, vl), vl);
vec_r0 = __riscv_vfadd(vec_r4, vec_r2, vl);
vec_i0 = __riscv_vfadd(vec_i4, vec_i2, vl);
rvv<T>::vsseg(reinterpret_cast<T*>(v0), __riscv_vfadd(vec_r0, vec_r1, vl), __riscv_vfadd(vec_i0, vec_i1, vl), vl);
rvv<T>::vsseg(reinterpret_cast<T*>(v1), __riscv_vfsub(vec_r0, vec_r1, vl), __riscv_vfsub(vec_i0, vec_i1, vl), vl);
vec_r2 = __riscv_vfsub(vec_r4, vec_r2, vl);
vec_i2 = __riscv_vfsub(vec_i4, vec_i2, vl);
rvv<T>::vsseg(reinterpret_cast<T*>(v0 + nx), __riscv_vfadd(vec_r2, vec_r3, vl), __riscv_vfadd(vec_i2, vec_i3, vl), vl);
rvv<T>::vsseg(reinterpret_cast<T*>(v1 + nx), __riscv_vfsub(vec_r2, vec_r3, vl), __riscv_vfsub(vec_i2, vec_i3, vl), vl);
}
}
}
for( ; n < factors[0]; )
{
// do the remaining radix-2 transform
nx = n;
n *= 2;
dw0 /= 2;
for( i = 0; i < len; i += n )
{
Complex<T>* v = dst + i;
T r0 = v[0].re + v[nx].re;
T i0 = v[0].im + v[nx].im;
T r1 = v[0].re - v[nx].re;
T i1 = v[0].im - v[nx].im;
v[0].re = r0; v[0].im = i0;
v[nx].re = r1; v[nx].im = i1;
for( j = 1; j < nx; j += vl )
{
vl = rvv<T>::setvl(nx - j);
v = dst + i + j;
VT vec_re, vec_im, vec_w_re, vec_w_im;
rvv<T>::vlseg(reinterpret_cast<const T*>(v + nx), vec_re, vec_im, vl);
rvv<T>::vlsseg(reinterpret_cast<const T*>(wave + j * dw0), sizeof(T) * dw0 * 2, vec_w_re, vec_w_im, vl);
auto vec_r1 = __riscv_vfsub(__riscv_vfmul(vec_re, vec_w_re, vl), __riscv_vfmul(vec_im, vec_w_im, vl), vl);
auto vec_i1 = __riscv_vfadd(__riscv_vfmul(vec_re, vec_w_im, vl), __riscv_vfmul(vec_im, vec_w_re, vl), vl);
VT vec_r0, vec_i0;
rvv<T>::vlseg(reinterpret_cast<const T*>(v), vec_r0, vec_i0, vl);
rvv<T>::vsseg(reinterpret_cast<T*>(v), __riscv_vfadd(vec_r0, vec_r1, vl), __riscv_vfadd(vec_i0, vec_i1, vl), vl);
rvv<T>::vsseg(reinterpret_cast<T*>(v + nx), __riscv_vfsub(vec_r0, vec_r1, vl), __riscv_vfsub(vec_i0, vec_i1, vl), vl);
}
}
}
}
// 2. all the other transforms
for( f_idx = (factors[0]&1) ? 0 : 1; f_idx < nf; f_idx++ )
{
int factor = factors[f_idx];
nx = n;
n *= factor;
dw0 /= factor;
if( factor == 3 )
{
const T sin_120 = 0.86602540378443864676372317075294;
for( i = 0; i < len; i += n )
{
Complex<T>* v = dst + i;
T r1 = v[nx].re + v[nx*2].re;
T i1 = v[nx].im + v[nx*2].im;
T r0 = v[0].re;
T i0 = v[0].im;
T r2 = sin_120*(v[nx].im - v[nx*2].im);
T i2 = sin_120*(v[nx*2].re - v[nx].re);
v[0].re = r0 + r1; v[0].im = i0 + i1;
r0 -= (T)0.5*r1; i0 -= (T)0.5*i1;
v[nx].re = r0 + r2; v[nx].im = i0 + i2;
v[nx*2].re = r0 - r2; v[nx*2].im = i0 - i2;
for( j = 1; j < nx; j += vl )
{
vl = rvv<T>::setvl(nx - j);
v = dst + i + j;
VT vec_re, vec_im, vec_w_re, vec_w_im;
rvv<T>::vlseg(reinterpret_cast<const T*>(v + nx), vec_re, vec_im, vl);
rvv<T>::vlsseg(reinterpret_cast<const T*>(wave + j * dw0), sizeof(T) * dw0 * 2, vec_w_re, vec_w_im, vl);
auto vec_r0 = __riscv_vfsub(__riscv_vfmul(vec_re, vec_w_re, vl), __riscv_vfmul(vec_im, vec_w_im, vl), vl);
auto vec_i0 = __riscv_vfadd(__riscv_vfmul(vec_re, vec_w_im, vl), __riscv_vfmul(vec_im, vec_w_re, vl), vl);
rvv<T>::vlseg(reinterpret_cast<const T*>(v + nx * 2), vec_re, vec_im, vl);
rvv<T>::vlsseg(reinterpret_cast<const T*>(wave + j * dw0 * 2), sizeof(T) * dw0 * 4, vec_w_re, vec_w_im, vl);
auto vec_r2 = __riscv_vfadd(__riscv_vfmul(vec_re, vec_w_im, vl), __riscv_vfmul(vec_im, vec_w_re, vl), vl);
auto vec_i2 = __riscv_vfsub(__riscv_vfmul(vec_re, vec_w_re, vl), __riscv_vfmul(vec_im, vec_w_im, vl), vl);
auto vec_r1 = __riscv_vfadd(vec_r0, vec_i2, vl);
auto vec_i1 = __riscv_vfadd(vec_i0, vec_r2, vl);
vec_r2 = __riscv_vfmul(__riscv_vfsub(vec_i0, vec_r2, vl), sin_120, vl);
vec_i2 = __riscv_vfmul(__riscv_vfsub(vec_i2, vec_r0, vl), sin_120, vl);
rvv<T>::vlseg(reinterpret_cast<const T*>(v), vec_r0, vec_i0, vl);
rvv<T>::vsseg(reinterpret_cast<T*>(v), __riscv_vfadd(vec_r0, vec_r1, vl), __riscv_vfadd(vec_i0, vec_i1, vl), vl);
vec_r0 = __riscv_vfsub(vec_r0, __riscv_vfmul(vec_r1, 0.5, vl), vl);
vec_i0 = __riscv_vfsub(vec_i0, __riscv_vfmul(vec_i1, 0.5, vl), vl);
rvv<T>::vsseg(reinterpret_cast<T*>(v + nx), __riscv_vfadd(vec_r0, vec_r2, vl), __riscv_vfadd(vec_i0, vec_i2, vl), vl);
rvv<T>::vsseg(reinterpret_cast<T*>(v + nx * 2), __riscv_vfsub(vec_r0, vec_r2, vl), __riscv_vfsub(vec_i0, vec_i2, vl), vl);
}
}
}
else if( factor == 5 )
{
const T fft5_2 = 0.559016994374947424102293417182819;
const T fft5_3 = -0.951056516295153572116439333379382;
const T fft5_4 = -1.538841768587626701285145288018455;
const T fft5_5 = 0.363271264002680442947733378740309;
for( i = 0; i < len; i += n )
{
for( j = 0; j < nx; j += vl )
{
vl = rvv<T>::setvl(nx - j);
Complex<T>* v0 = dst + i + j;
Complex<T>* v1 = v0 + nx*2;
Complex<T>* v2 = v1 + nx*2;
VT vec_re, vec_im, vec_w_re, vec_w_im;
rvv<T>::vlseg(reinterpret_cast<const T*>(v0 + nx), vec_re, vec_im, vl);
rvv<T>::vlsseg(reinterpret_cast<const T*>(wave + j * dw0), sizeof(T) * dw0 * 2, vec_w_re, vec_w_im, vl);
auto vec_r3 = __riscv_vfsub(__riscv_vfmul(vec_re, vec_w_re, vl), __riscv_vfmul(vec_im, vec_w_im, vl), vl);
auto vec_i3 = __riscv_vfadd(__riscv_vfmul(vec_re, vec_w_im, vl), __riscv_vfmul(vec_im, vec_w_re, vl), vl);
rvv<T>::vlseg(reinterpret_cast<const T*>(v2), vec_re, vec_im, vl);
rvv<T>::vlsseg(reinterpret_cast<const T*>(wave + j * dw0 * 4), sizeof(T) * dw0 * 8, vec_w_re, vec_w_im, vl);
auto vec_r2 = __riscv_vfsub(__riscv_vfmul(vec_re, vec_w_re, vl), __riscv_vfmul(vec_im, vec_w_im, vl), vl);
auto vec_i2 = __riscv_vfadd(__riscv_vfmul(vec_re, vec_w_im, vl), __riscv_vfmul(vec_im, vec_w_re, vl), vl);
auto vec_r1 = __riscv_vfadd(vec_r3, vec_r2, vl);
auto vec_i1 = __riscv_vfadd(vec_i3, vec_i2, vl);
vec_r3 = __riscv_vfsub(vec_r3, vec_r2, vl);
vec_i3 = __riscv_vfsub(vec_i3, vec_i2, vl);
rvv<T>::vlseg(reinterpret_cast<const T*>(v1 + nx), vec_re, vec_im, vl);
rvv<T>::vlsseg(reinterpret_cast<const T*>(wave + j * dw0 * 3), sizeof(T) * dw0 * 6, vec_w_re, vec_w_im, vl);
auto vec_r4 = __riscv_vfsub(__riscv_vfmul(vec_re, vec_w_re, vl), __riscv_vfmul(vec_im, vec_w_im, vl), vl);
auto vec_i4 = __riscv_vfadd(__riscv_vfmul(vec_re, vec_w_im, vl), __riscv_vfmul(vec_im, vec_w_re, vl), vl);
rvv<T>::vlseg(reinterpret_cast<const T*>(v1), vec_re, vec_im, vl);
rvv<T>::vlsseg(reinterpret_cast<const T*>(wave + j * dw0 * 2), sizeof(T) * dw0 * 4, vec_w_re, vec_w_im, vl);
auto vec_r0 = __riscv_vfsub(__riscv_vfmul(vec_re, vec_w_re, vl), __riscv_vfmul(vec_im, vec_w_im, vl), vl);
auto vec_i0 = __riscv_vfadd(__riscv_vfmul(vec_re, vec_w_im, vl), __riscv_vfmul(vec_im, vec_w_re, vl), vl);
vec_r2 = __riscv_vfadd(vec_r4, vec_r0, vl);
vec_i2 = __riscv_vfadd(vec_i4, vec_i0, vl);
vec_r4 = __riscv_vfsub(vec_r4, vec_r0, vl);
vec_i4 = __riscv_vfsub(vec_i4, vec_i0, vl);
rvv<T>::vlseg(reinterpret_cast<const T*>(v0), vec_r0, vec_i0, vl);
auto vec_r5 = __riscv_vfadd(vec_r1, vec_r2, vl);
auto vec_i5 = __riscv_vfadd(vec_i1, vec_i2, vl);
rvv<T>::vsseg(reinterpret_cast<T*>(v0), __riscv_vfadd(vec_r0, vec_r5, vl), __riscv_vfadd(vec_i0, vec_i5, vl), vl);
vec_r0 = __riscv_vfsub(vec_r0, __riscv_vfmul(vec_r5, 0.25, vl), vl);
vec_i0 = __riscv_vfsub(vec_i0, __riscv_vfmul(vec_i5, 0.25, vl), vl);
vec_r1 = __riscv_vfmul(__riscv_vfsub(vec_r1, vec_r2, vl), fft5_2, vl);
vec_i1 = __riscv_vfmul(__riscv_vfsub(vec_i1, vec_i2, vl), fft5_2, vl);
vec_r2 = __riscv_vfmul(__riscv_vfadd(vec_i3, vec_i4, vl), -fft5_3, vl);
vec_i2 = __riscv_vfmul(__riscv_vfadd(vec_r3, vec_r4, vl), fft5_3, vl);
vec_i3 = __riscv_vfmul(vec_i3, -fft5_5, vl);
vec_r3 = __riscv_vfmul(vec_r3, fft5_5, vl);
vec_i4 = __riscv_vfmul(vec_i4, -fft5_4, vl);
vec_r4 = __riscv_vfmul(vec_r4, fft5_4, vl);
vec_r5 = __riscv_vfadd(vec_r2, vec_i3, vl);
vec_i5 = __riscv_vfadd(vec_i2, vec_r3, vl);
vec_r2 = __riscv_vfsub(vec_r2, vec_i4, vl);
vec_i2 = __riscv_vfsub(vec_i2, vec_r4, vl);
vec_r3 = __riscv_vfadd(vec_r0, vec_r1, vl);
vec_i3 = __riscv_vfadd(vec_i0, vec_i1, vl);
rvv<T>::vsseg(reinterpret_cast<T*>(v0 + nx), __riscv_vfadd(vec_r3, vec_r2, vl), __riscv_vfadd(vec_i3, vec_i2, vl), vl);
rvv<T>::vsseg(reinterpret_cast<T*>(v2), __riscv_vfsub(vec_r3, vec_r2, vl), __riscv_vfsub(vec_i3, vec_i2, vl), vl);
vec_r0 = __riscv_vfsub(vec_r0, vec_r1, vl);
vec_i0 = __riscv_vfsub(vec_i0, vec_i1, vl);
rvv<T>::vsseg(reinterpret_cast<T*>(v1), __riscv_vfadd(vec_r0, vec_r5, vl), __riscv_vfadd(vec_i0, vec_i5, vl), vl);
rvv<T>::vsseg(reinterpret_cast<T*>(v1 + nx), __riscv_vfsub(vec_r0, vec_r5, vl), __riscv_vfsub(vec_i0, vec_i5, vl), vl);
}
}
}
else
{
// radix-"factor" - an odd number
int p, q, factor2 = (factor - 1)/2;
int dd, dw_f = tab_size/factor;
std::vector<Complex<T> > buf(factor2 * 2);
Complex<T>* a = buf.data();
Complex<T>* b = a + factor2;
for( i = 0; i < len; i += n )
{
for( j = 0, dw = 0; j < nx; j++, dw += dw0 )
{
Complex<T>* v = dst + i + j;
Complex<T> v_0 = v[0];
Complex<T> vn_0 = v_0;
if( j == 0 )
{
for( p = 1; p <= factor2; p += vl )
{
vl = rvv<T>::setvl(factor2 + 1 - p);
VT vec_a_re, vec_a_im, vec_b_re, vec_b_im;
rvv<T>::vlsseg(reinterpret_cast<const T*>(v + nx * p), sizeof(T) * nx * 2, vec_a_re, vec_a_im, vl);
rvv<T>::vlsseg(reinterpret_cast<const T*>(v + n - nx * p), (ptrdiff_t)sizeof(T) * nx * -2, vec_b_re, vec_b_im, vl);
auto vec_r0 = __riscv_vfadd(vec_a_re, vec_b_re, vl);
auto vec_r1 = __riscv_vfsub(vec_a_re, vec_b_re, vl);
auto vec_i0 = __riscv_vfsub(vec_a_im, vec_b_im, vl);
auto vec_i1 = __riscv_vfadd(vec_a_im, vec_b_im, vl);
vn_0.re += __riscv_vfmv_f(__riscv_vfredosum(vec_r0, RVV<T, LMUL_1>::vmv_s(0, vl), vl));
vn_0.im += __riscv_vfmv_f(__riscv_vfredosum(vec_i1, RVV<T, LMUL_1>::vmv_s(0, vl), vl));
rvv<T>::vsseg(reinterpret_cast<T*>(a + p - 1), vec_r0, vec_i0, vl);
rvv<T>::vsseg(reinterpret_cast<T*>(b + p - 1), vec_r1, vec_i1, vl);
}
}
else
{
const Complex<T>* wave_ = wave + dw*factor;
for( p = 1; p <= factor2; p += vl )
{
vl = rvv<T>::setvl(factor2 + 1 - p);
VT vec_re, vec_im, vec_w_re, vec_w_im;
rvv<T>::vlsseg(reinterpret_cast<const T*>(v + nx * p), sizeof(T) * nx * 2, vec_re, vec_im, vl);
rvv<T>::vlsseg(reinterpret_cast<const T*>(wave + p * dw), sizeof(T) * dw * 2, vec_w_re, vec_w_im, vl);
auto vec_r2 = __riscv_vfsub(__riscv_vfmul(vec_re, vec_w_re, vl), __riscv_vfmul(vec_im, vec_w_im, vl), vl);
auto vec_i2 = __riscv_vfadd(__riscv_vfmul(vec_re, vec_w_im, vl), __riscv_vfmul(vec_im, vec_w_re, vl), vl);
rvv<T>::vlsseg(reinterpret_cast<const T*>(v + n - nx * p), (ptrdiff_t)sizeof(T) * nx * -2, vec_re, vec_im, vl);
rvv<T>::vlsseg(reinterpret_cast<const T*>(wave_ - p * dw), (ptrdiff_t)sizeof(T) * dw * -2, vec_w_re, vec_w_im, vl);
auto vec_r1 = __riscv_vfsub(__riscv_vfmul(vec_re, vec_w_re, vl), __riscv_vfmul(vec_im, vec_w_im, vl), vl);
auto vec_i1 = __riscv_vfadd(__riscv_vfmul(vec_re, vec_w_im, vl), __riscv_vfmul(vec_im, vec_w_re, vl), vl);
auto vec_r0 = __riscv_vfadd(vec_r2, vec_r1, vl);
auto vec_i0 = __riscv_vfsub(vec_i2, vec_i1, vl);
vec_r1 = __riscv_vfsub(vec_r2, vec_r1, vl);
vec_i1 = __riscv_vfadd(vec_i2, vec_i1, vl);
vn_0.re += __riscv_vfmv_f(__riscv_vfredosum(vec_r0, RVV<T, LMUL_1>::vmv_s(0, vl), vl));
vn_0.im += __riscv_vfmv_f(__riscv_vfredosum(vec_i1, RVV<T, LMUL_1>::vmv_s(0, vl), vl));
rvv<T>::vsseg(reinterpret_cast<T*>(a + p - 1), vec_r0, vec_i0, vl);
rvv<T>::vsseg(reinterpret_cast<T*>(b + p - 1), vec_r1, vec_i1, vl);
}
}
v[0] = vn_0;
for( p = 1, k = nx; p <= factor2; p++, k += nx )
{
Complex<T> s0 = v_0, s1 = v_0;
dd = dw_f*p;
vl = __riscv_vsetvlmax_e32mf2();
auto vec_dd = __riscv_vid_v_u32mf2(vl);
vec_dd = __riscv_vmul(vec_dd, dd, vl);
vec_dd = __riscv_vremu(vec_dd, tab_size, vl);
for( q = 0; q < factor2; q += vl )
{
vl = rvv<T>::setvl(factor2 - q);
auto vec_d = __riscv_vadd(vec_dd, (q + 1) * dd % tab_size, vl);
auto vmask = __riscv_vmsgeu(vec_d, tab_size, vl);
vec_d = __riscv_vsub_mu(vmask, vec_d, vec_d, tab_size, vl);
vec_d = __riscv_vmul(vec_d, sizeof(T) * 2, vl);
auto vec_w = __riscv_vloxei32(reinterpret_cast<const T*>(wave), vec_d, vl);
VT vec_a_re, vec_a_im, vec_b_re, vec_b_im;
rvv<T>::vlsseg(reinterpret_cast<const T*>(a + q), sizeof(T) * 2, vec_a_re, vec_a_im, vl);
rvv<T>::vlsseg(reinterpret_cast<const T*>(b + q), sizeof(T) * 2, vec_b_re, vec_b_im, vl);
auto vec_r0 = __riscv_vfmul(vec_w, vec_a_re, vl);
auto vec_r1 = __riscv_vfmul(vec_w, vec_b_im, vl);
vec_w = __riscv_vloxei32(reinterpret_cast<const T*>(wave) + 1, vec_d, vl);
auto vec_i0 = __riscv_vfmul(vec_w, vec_a_im, vl);
auto vec_i1 = __riscv_vfmul(vec_w, vec_b_re, vl);
T r0 = __riscv_vfmv_f(__riscv_vfredosum(vec_r0, RVV<T, LMUL_1>::vmv_s(0, vl), vl));
T i0 = __riscv_vfmv_f(__riscv_vfredosum(vec_i0, RVV<T, LMUL_1>::vmv_s(0, vl), vl));
T r1 = __riscv_vfmv_f(__riscv_vfredosum(vec_r1, RVV<T, LMUL_1>::vmv_s(0, vl), vl));
T i1 = __riscv_vfmv_f(__riscv_vfredosum(vec_i1, RVV<T, LMUL_1>::vmv_s(0, vl), vl));
s1.re += r0 + i0; s0.re += r0 - i0;
s1.im += r1 - i1; s0.im += r1 + i1;
}
v[k] = s0;
v[n-k] = s1;
}
}
}
}
}
if( scale != 1 )
{
T re_scale = scale, im_scale = scale;
if( isInverse )
im_scale = -im_scale;
for( i = 0; i < len; i += vl )
{
vl = TabType::setvl(len - i);
auto vec_src_re = TabTypeF::vload_stride(reinterpret_cast<const T*>(dst + i), sizeof(T) * 2, vl);
auto vec_src_im = TabTypeF::vload_stride(reinterpret_cast<const T*>(dst + i) + 1, sizeof(T) * 2, vl);
vec_src_re = __riscv_vfmul(vec_src_re, re_scale, vl);
vec_src_im = __riscv_vfmul(vec_src_im, im_scale, vl);
TabTypeF::vstore_stride(reinterpret_cast<T*>(dst + i), sizeof(T) * 2, vec_src_re, vl);
TabTypeF::vstore_stride(reinterpret_cast<T*>(dst + i) + 1, sizeof(T) * 2, vec_src_im, vl);
}
}
else if( isInverse )
{
for( i = 0; i < len; i += vl )
{
vl = TabType::setvl(len - i);
auto vec_src_im = TabTypeF::vload_stride(reinterpret_cast<const T*>(dst + i) + 1, sizeof(T) * 2, vl);
vec_src_im = __riscv_vfneg(vec_src_im, vl);
TabTypeF::vstore_stride(reinterpret_cast<T*>(dst + i) + 1, sizeof(T) * 2, vec_src_im, vl);
}
}
return CV_HAL_ERROR_OK;
}
inline int dft(const uchar* src, uchar* dst, int depth, int nf, int *factors, double scale, int* itab, void* wave,
int tab_size, int n, bool isInverse, bool noPermute)
{
if( n == 0 )
return CV_HAL_ERROR_OK;
switch( depth )
{
case CV_32F:
return dft(reinterpret_cast<const Complex<float>*>(src), reinterpret_cast<Complex<float>*>(dst), nf, factors, (float)scale,
itab, reinterpret_cast<const Complex<float>*>(wave), tab_size, n, isInverse, noPermute);
case CV_64F:
return dft(reinterpret_cast<const Complex<double>*>(src), reinterpret_cast<Complex<double>*>(dst), nf, factors, (double)scale,
itab, reinterpret_cast<const Complex<double>*>(wave), tab_size, n, isInverse, noPermute);
}
return CV_HAL_ERROR_NOT_IMPLEMENTED;
}
}}}
#endif
+202
View File
@@ -0,0 +1,202 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level
// directory of this distribution and at http://opencv.org/license.html.
#pragma once
#include <riscv_vector.h>
namespace cv { namespace cv_hal_rvv {
#undef cv_hal_exp32f
#define cv_hal_exp32f cv::cv_hal_rvv::exp32f
#undef cv_hal_exp64f
#define cv_hal_exp64f cv::cv_hal_rvv::exp64f
namespace detail {
static constexpr size_t exp_scale = 6;
static constexpr size_t exp_tab_size = 1 << exp_scale;
static constexpr size_t exp_mask = exp_tab_size - 1;
static constexpr double exp_prescale = 1.4426950408889634073599246810019 * (1 << exp_scale);
static constexpr double exp_postscale = 1. / (1 << exp_scale);
// log10(DBL_MAX) < 3000
static constexpr double exp_max_val = (3000. * (1 << exp_scale)) / exp_prescale;
static constexpr double exp_min_val = -exp_max_val;
static constexpr double exp32f_a0 = .9670371139572337719125840413672004409288e-2;
static constexpr double exp32f_a1 = .5550339366753125211915322047004666939128e-1 / exp32f_a0;
static constexpr double exp32f_a2 = .2402265109513301490103372422686535526573 / exp32f_a0;
static constexpr double exp32f_a3 = .6931471805521448196800669615864773144641 / exp32f_a0;
static constexpr double exp32f_a4 = 1.000000000000002438532970795181890933776 / exp32f_a0;
static constexpr double exp64f_a0 = .13369713757180123244806654839424e-2 / exp32f_a0;
static constexpr double exp64f_a1 = .96180973140732918010002372686186e-2 / exp32f_a0;
static constexpr double exp64f_a2 = .55504108793649567998466049042729e-1 / exp32f_a0;
static constexpr double exp64f_a3 = .24022650695886477918181338054308 / exp32f_a0;
static constexpr double exp64f_a4 = .69314718055994546743029643825322 / exp32f_a0;
static constexpr double exp64f_a5 = .99999999999999999998285227504999 / exp32f_a0;
#define EXP_TAB_VALUE \
{ \
1.0 * exp32f_a0, \
1.0108892860517004600204097905619 * exp32f_a0, \
1.0218971486541166782344801347833 * exp32f_a0, \
1.0330248790212284225001082839705 * exp32f_a0, \
1.0442737824274138403219664787399 * exp32f_a0, \
1.0556451783605571588083413251529 * exp32f_a0, \
1.0671404006768236181695211209928 * exp32f_a0, \
1.0787607977571197937406800374385 * exp32f_a0, \
1.0905077326652576592070106557607 * exp32f_a0, \
1.1023825833078409435564142094256 * exp32f_a0, \
1.1143867425958925363088129569196 * exp32f_a0, \
1.126521618608241899794798643787 * exp32f_a0, \
1.1387886347566916537038302838415 * exp32f_a0, \
1.151189229952982705817759635202 * exp32f_a0, \
1.1637248587775775138135735990922 * exp32f_a0, \
1.1763969916502812762846457284838 * exp32f_a0, \
1.1892071150027210667174999705605 * exp32f_a0, \
1.2021567314527031420963969574978 * exp32f_a0, \
1.2152473599804688781165202513388 * exp32f_a0, \
1.2284805361068700056940089577928 * exp32f_a0, \
1.2418578120734840485936774687266 * exp32f_a0, \
1.2553807570246910895793906574423 * exp32f_a0, \
1.2690509571917332225544190810323 * exp32f_a0, \
1.2828700160787782807266697810215 * exp32f_a0, \
1.2968395546510096659337541177925 * exp32f_a0, \
1.3109612115247643419229917863308 * exp32f_a0, \
1.3252366431597412946295370954987 * exp32f_a0, \
1.3396675240533030053600306697244 * exp32f_a0, \
1.3542555469368927282980147401407 * exp32f_a0, \
1.3690024229745906119296011329822 * exp32f_a0, \
1.3839098819638319548726595272652 * exp32f_a0, \
1.3989796725383111402095281367152 * exp32f_a0, \
1.4142135623730950488016887242097 * exp32f_a0, \
1.4296133383919700112350657782751 * exp32f_a0, \
1.4451808069770466200370062414717 * exp32f_a0, \
1.4609177941806469886513028903106 * exp32f_a0, \
1.476826145939499311386907480374 * exp32f_a0, \
1.4929077282912648492006435314867 * exp32f_a0, \
1.5091644275934227397660195510332 * exp32f_a0, \
1.5255981507445383068512536895169 * exp32f_a0, \
1.5422108254079408236122918620907 * exp32f_a0, \
1.5590044002378369670337280894749 * exp32f_a0, \
1.5759808451078864864552701601819 * exp32f_a0, \
1.5931421513422668979372486431191 * exp32f_a0, \
1.6104903319492543081795206673574 * exp32f_a0, \
1.628027421857347766848218522014 * exp32f_a0, \
1.6457554781539648445187567247258 * exp32f_a0, \
1.6636765803267364350463364569764 * exp32f_a0, \
1.6817928305074290860622509524664 * exp32f_a0, \
1.7001063537185234695013625734975 * exp32f_a0, \
1.7186192981224779156293443764563 * exp32f_a0, \
1.7373338352737062489942020818722 * exp32f_a0, \
1.7562521603732994831121606193753 * exp32f_a0, \
1.7753764925265212525505592001993 * exp32f_a0, \
1.7947090750031071864277032421278 * exp32f_a0, \
1.8142521755003987562498346003623 * exp32f_a0, \
1.8340080864093424634870831895883 * exp32f_a0, \
1.8539791250833855683924530703377 * exp32f_a0, \
1.8741676341102999013299989499544 * exp32f_a0, \
1.8945759815869656413402186534269 * exp32f_a0, \
1.9152065613971472938726112702958 * exp32f_a0, \
1.9360617934922944505980559045667 * exp32f_a0, \
1.9571441241754002690183222516269 * exp32f_a0, \
1.9784560263879509682582499181312 * exp32f_a0, \
}
static constexpr float exp_tab_32f[exp_tab_size] = EXP_TAB_VALUE;
static constexpr double exp_tab_64f[exp_tab_size] = EXP_TAB_VALUE;
#undef EXP_TAB_VALUE
} // namespace detail
inline int exp32f(const float* src, float* dst, int _len)
{
size_t vl = __riscv_vsetvlmax_e32m4();
auto exp_a2 = __riscv_vfmv_v_f_f32m4(detail::exp32f_a2, vl);
auto exp_a3 = __riscv_vfmv_v_f_f32m4(detail::exp32f_a3, vl);
auto exp_a4 = __riscv_vfmv_v_f_f32m4(detail::exp32f_a4, vl);
for (size_t len = _len; len > 0; len -= vl, src += vl, dst += vl)
{
vl = __riscv_vsetvl_e32m4(len);
auto x0 = __riscv_vle32_v_f32m4(src, vl);
x0 = __riscv_vfmax(x0, detail::exp_min_val, vl);
x0 = __riscv_vfmin(x0, detail::exp_max_val, vl);
x0 = __riscv_vfmul(x0, detail::exp_prescale, vl);
auto xi = __riscv_vfcvt_rtz_x_f_v_i32m4(x0, vl);
x0 = __riscv_vfsub(x0, __riscv_vfcvt_f_x_v_f32m4(xi, vl), vl);
x0 = __riscv_vfmul(x0, detail::exp_postscale, vl);
auto t = __riscv_vsra(xi, detail::exp_scale, vl);
t = __riscv_vadd(t, 127, vl);
t = __riscv_vmax(t, 0, vl);
t = __riscv_vmin(t, 255, vl);
auto buf = __riscv_vreinterpret_f32m4(__riscv_vsll(t, 23, vl));
auto _xi = __riscv_vreinterpret_u32m4(xi);
_xi = __riscv_vsll(__riscv_vand(_xi, detail::exp_mask, vl), 2, vl);
auto tab_v = __riscv_vluxei32(detail::exp_tab_32f, _xi, vl);
auto res = __riscv_vfmul(buf, tab_v, vl);
auto xn = __riscv_vfadd(x0, detail::exp32f_a1, vl);
xn = __riscv_vfmadd(xn, x0, exp_a2, vl);
xn = __riscv_vfmadd(xn, x0, exp_a3, vl);
xn = __riscv_vfmadd(xn, x0, exp_a4, vl);
res = __riscv_vfmul(res, xn, vl);
__riscv_vse32(dst, res, vl);
}
return CV_HAL_ERROR_OK;
}
inline int exp64f(const double* src, double* dst, int _len)
{
size_t vl = __riscv_vsetvlmax_e64m4();
// all vector registers are used up, so not load more constants
auto exp_a2 = __riscv_vfmv_v_f_f64m4(detail::exp64f_a2, vl);
auto exp_a3 = __riscv_vfmv_v_f_f64m4(detail::exp64f_a3, vl);
auto exp_a4 = __riscv_vfmv_v_f_f64m4(detail::exp64f_a4, vl);
auto exp_a5 = __riscv_vfmv_v_f_f64m4(detail::exp64f_a5, vl);
for (size_t len = _len; len > 0; len -= vl, src += vl, dst += vl)
{
vl = __riscv_vsetvl_e64m4(len);
auto x0 = __riscv_vle64_v_f64m4(src, vl);
x0 = __riscv_vfmax(x0, detail::exp_min_val, vl);
x0 = __riscv_vfmin(x0, detail::exp_max_val, vl);
x0 = __riscv_vfmul(x0, detail::exp_prescale, vl);
auto xi = __riscv_vfcvt_rtz_x_f_v_i64m4(x0, vl);
x0 = __riscv_vfsub(x0, __riscv_vfcvt_f_x_v_f64m4(xi, vl), vl);
x0 = __riscv_vfmul(x0, detail::exp_postscale, vl);
auto t = __riscv_vsra(xi, detail::exp_scale, vl);
t = __riscv_vadd(t, 1023, vl);
t = __riscv_vmax(t, 0, vl);
t = __riscv_vmin(t, 2047, vl);
auto buf = __riscv_vreinterpret_f64m4(__riscv_vsll(t, 52, vl));
auto _xi = __riscv_vreinterpret_u64m4(xi);
_xi = __riscv_vsll(__riscv_vand(_xi, detail::exp_mask, vl), 3, vl);
auto tab_v = __riscv_vluxei64(detail::exp_tab_64f, _xi, vl);
auto res = __riscv_vfmul(buf, tab_v, vl);
auto xn = __riscv_vfadd(__riscv_vfmul(x0, detail::exp64f_a0, vl), detail::exp64f_a1, vl);
xn = __riscv_vfmadd(xn, x0, exp_a2, vl);
xn = __riscv_vfmadd(xn, x0, exp_a3, vl);
xn = __riscv_vfmadd(xn, x0, exp_a4, vl);
xn = __riscv_vfmadd(xn, x0, exp_a5, vl);
res = __riscv_vfmul(res, xn, vl);
__riscv_vse64(dst, res, vl);
}
return CV_HAL_ERROR_OK;
}
}} // namespace cv::cv_hal_rvv
+852
View File
@@ -0,0 +1,852 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#ifndef OPENCV_HAL_RVV_FILTER_HPP_INCLUDED
#define OPENCV_HAL_RVV_FILTER_HPP_INCLUDED
#include "../../imgproc/include/opencv2/imgproc/hal/interface.h"
#include <riscv_vector.h>
struct cvhalFilter2D;
namespace cv { namespace cv_hal_rvv {
namespace filter {
#undef cv_hal_filterInit
#undef cv_hal_filter
#undef cv_hal_filterFree
#define cv_hal_filterInit cv::cv_hal_rvv::filter::filterInit
#define cv_hal_filter cv::cv_hal_rvv::filter::filter
#define cv_hal_filterFree cv::cv_hal_rvv::filter::filterFree
class FilterInvoker : public ParallelLoopBody
{
public:
template<typename... Args>
FilterInvoker(std::function<int(int, int, Args...)> _func, Args&&... args)
{
func = std::bind(_func, std::placeholders::_1, std::placeholders::_2, std::forward<Args>(args)...);
}
virtual void operator()(const Range& range) const override
{
func(range.start, range.end);
}
private:
std::function<int(int, int)> func;
};
template<typename... Args>
static inline int invoke(int start, int end, std::function<int(int, int, Args...)> func, Args&&... args)
{
cv::parallel_for_(Range(start + 1, end), FilterInvoker(func, std::forward<Args>(args)...), cv::getNumThreads());
return func(start, start + 1, std::forward<Args>(args)...);
}
static inline int borderInterpolate( int p, int len, int borderType )
{
if( (unsigned)p < (unsigned)len )
;
else if( borderType == BORDER_REPLICATE )
p = p < 0 ? 0 : len - 1;
else if( borderType == BORDER_REFLECT || borderType == BORDER_REFLECT_101 )
{
int delta = borderType == BORDER_REFLECT_101;
if( len == 1 )
return 0;
do
{
if( p < 0 )
p = -p - 1 + delta;
else
p = len - 1 - (p - len) - delta;
}
while( (unsigned)p >= (unsigned)len );
}
else if( borderType == BORDER_CONSTANT )
p = -1;
return p;
}
struct Filter2D
{
const uchar* kernel_data;
size_t kernel_step;
int kernel_type;
int kernel_width;
int kernel_height;
int src_type;
int dst_type;
int borderType;
double delta;
int anchor_x;
int anchor_y;
};
inline int filterInit(cvhalFilter2D** context, uchar* kernel_data, size_t kernel_step, int kernel_type, int kernel_width, int kernel_height, int /*max_width*/, int /*max_height*/, int src_type, int dst_type, int borderType, double delta, int anchor_x, int anchor_y, bool /*allowSubmatrix*/, bool /*allowInplace*/)
{
if (kernel_type != CV_32FC1 || src_type != CV_8UC4 || dst_type != CV_8UC4)
return CV_HAL_ERROR_NOT_IMPLEMENTED;
if (kernel_width != kernel_height)
return CV_HAL_ERROR_NOT_IMPLEMENTED;
if (kernel_width != 3 && kernel_width != 5)
return CV_HAL_ERROR_NOT_IMPLEMENTED;
if ((borderType & ~BORDER_ISOLATED) == BORDER_WRAP)
return CV_HAL_ERROR_NOT_IMPLEMENTED;
anchor_x = anchor_x < 0 ? kernel_width / 2 : anchor_x;
anchor_y = anchor_y < 0 ? kernel_height / 2 : anchor_y;
*context = reinterpret_cast<cvhalFilter2D*>(new Filter2D{kernel_data, kernel_step, kernel_type, kernel_width, kernel_height, src_type, dst_type, borderType, delta, anchor_x, anchor_y});
return CV_HAL_ERROR_OK;
}
static void process3(int anchor, int left, int right, float delta, const float* kernel, const uchar* row0, const uchar* row1, const uchar* row2, uchar* dst)
{
int vl;
for (int i = left; i < right; i += vl)
{
vl = __riscv_vsetvl_e8m1(right - i);
auto s0 = __riscv_vfmv_v_f_f32m4(delta, vl);
auto s1 = __riscv_vfmv_v_f_f32m4(delta, vl);
auto s2 = __riscv_vfmv_v_f_f32m4(delta, vl);
auto s3 = __riscv_vfmv_v_f_f32m4(delta, vl);
auto addshift = [&](vfloat32m4_t a, vfloat32m4_t b, float k0, float k1, float k2, float r1, float r2) {
a = __riscv_vfmacc(a, k0, b, vl);
b = __riscv_vfslide1down(b, r1, vl);
a = __riscv_vfmacc(a, k1, b, vl);
b = __riscv_vfslide1down(b, r2, vl);
return __riscv_vfmacc(a, k2, b, vl);
};
auto loadsrc = [&](const uchar* row, float k0, float k1, float k2) {
if (!row) return;
const uchar* extra = row + (i - anchor) * 4;
auto src = __riscv_vlseg4e8_v_u8m1x4(extra, vl);
auto v0 = __riscv_vfwcvt_f(__riscv_vwcvtu_x(__riscv_vget_v_u8m1x4_u8m1(src, 0), vl), vl);
auto v1 = __riscv_vfwcvt_f(__riscv_vwcvtu_x(__riscv_vget_v_u8m1x4_u8m1(src, 1), vl), vl);
auto v2 = __riscv_vfwcvt_f(__riscv_vwcvtu_x(__riscv_vget_v_u8m1x4_u8m1(src, 2), vl), vl);
auto v3 = __riscv_vfwcvt_f(__riscv_vwcvtu_x(__riscv_vget_v_u8m1x4_u8m1(src, 3), vl), vl);
s0 = addshift(s0, v0, k0, k1, k2, extra[vl * 4 ], extra[vl * 4 + 4]);
s1 = addshift(s1, v1, k0, k1, k2, extra[vl * 4 + 1], extra[vl * 4 + 5]);
s2 = addshift(s2, v2, k0, k1, k2, extra[vl * 4 + 2], extra[vl * 4 + 6]);
s3 = addshift(s3, v3, k0, k1, k2, extra[vl * 4 + 3], extra[vl * 4 + 7]);
};
loadsrc(row0, kernel[0], kernel[1], kernel[2]);
loadsrc(row1, kernel[3], kernel[4], kernel[5]);
loadsrc(row2, kernel[6], kernel[7], kernel[8]);
vuint8m1x4_t val{};
val = __riscv_vset_v_u8m1_u8m1x4(val, 0, __riscv_vnclipu(__riscv_vfncvt_xu(s0, vl), 0, __RISCV_VXRM_RNU, vl));
val = __riscv_vset_v_u8m1_u8m1x4(val, 1, __riscv_vnclipu(__riscv_vfncvt_xu(s1, vl), 0, __RISCV_VXRM_RNU, vl));
val = __riscv_vset_v_u8m1_u8m1x4(val, 2, __riscv_vnclipu(__riscv_vfncvt_xu(s2, vl), 0, __RISCV_VXRM_RNU, vl));
val = __riscv_vset_v_u8m1_u8m1x4(val, 3, __riscv_vnclipu(__riscv_vfncvt_xu(s3, vl), 0, __RISCV_VXRM_RNU, vl));
__riscv_vsseg4e8(dst + i * 4, val, vl);
}
}
static void process5(int anchor, int left, int right, float delta, const float* kernel, const uchar* row0, const uchar* row1, const uchar* row2, const uchar* row3, const uchar* row4, uchar* dst)
{
int vl;
for (int i = left; i < right; i += vl)
{
vl = __riscv_vsetvl_e8m1(right - i);
auto s0 = __riscv_vfmv_v_f_f32m4(delta, vl);
auto s1 = __riscv_vfmv_v_f_f32m4(delta, vl);
auto s2 = __riscv_vfmv_v_f_f32m4(delta, vl);
auto s3 = __riscv_vfmv_v_f_f32m4(delta, vl);
auto addshift = [&](vfloat32m4_t a, vfloat32m4_t b, float k0, float k1, float k2, float k3, float k4, float r1, float r2, float r3, float r4) {
a = __riscv_vfmacc(a, k0, b, vl);
b = __riscv_vfslide1down(b, r1, vl);
a = __riscv_vfmacc(a, k1, b, vl);
b = __riscv_vfslide1down(b, r2, vl);
a = __riscv_vfmacc(a, k2, b, vl);
b = __riscv_vfslide1down(b, r3, vl);
a = __riscv_vfmacc(a, k3, b, vl);
b = __riscv_vfslide1down(b, r4, vl);
return __riscv_vfmacc(a, k4, b, vl);
};
auto loadsrc = [&](const uchar* row, float k0, float k1, float k2, float k3, float k4) {
if (!row) return;
auto src = __riscv_vlseg4e8_v_u8m1x4(row + (i - anchor) * 4, vl);
auto v0 = __riscv_vfwcvt_f(__riscv_vwcvtu_x(__riscv_vget_v_u8m1x4_u8m1(src, 0), vl), vl);
auto v1 = __riscv_vfwcvt_f(__riscv_vwcvtu_x(__riscv_vget_v_u8m1x4_u8m1(src, 1), vl), vl);
auto v2 = __riscv_vfwcvt_f(__riscv_vwcvtu_x(__riscv_vget_v_u8m1x4_u8m1(src, 2), vl), vl);
auto v3 = __riscv_vfwcvt_f(__riscv_vwcvtu_x(__riscv_vget_v_u8m1x4_u8m1(src, 3), vl), vl);
const uchar* extra = row + (i + vl - anchor) * 4;
s0 = addshift(s0, v0, k0, k1, k2, k3, k4, *(extra ), *(extra + 4), *(extra + 8), *(extra + 12));
s1 = addshift(s1, v1, k0, k1, k2, k3, k4, *(extra + 1), *(extra + 5), *(extra + 9), *(extra + 13));
s2 = addshift(s2, v2, k0, k1, k2, k3, k4, *(extra + 2), *(extra + 6), *(extra + 10), *(extra + 14));
s3 = addshift(s3, v3, k0, k1, k2, k3, k4, *(extra + 3), *(extra + 7), *(extra + 11), *(extra + 15));
};
loadsrc(row0, kernel[ 0], kernel[ 1], kernel[ 2], kernel[ 3], kernel[ 4]);
loadsrc(row1, kernel[ 5], kernel[ 6], kernel[ 7], kernel[ 8], kernel[ 9]);
loadsrc(row2, kernel[10], kernel[11], kernel[12], kernel[13], kernel[14]);
loadsrc(row3, kernel[15], kernel[16], kernel[17], kernel[18], kernel[19]);
loadsrc(row4, kernel[20], kernel[21], kernel[22], kernel[23], kernel[24]);
vuint8m1x4_t val{};
val = __riscv_vset_v_u8m1_u8m1x4(val, 0, __riscv_vnclipu(__riscv_vfncvt_xu(s0, vl), 0, __RISCV_VXRM_RNU, vl));
val = __riscv_vset_v_u8m1_u8m1x4(val, 1, __riscv_vnclipu(__riscv_vfncvt_xu(s1, vl), 0, __RISCV_VXRM_RNU, vl));
val = __riscv_vset_v_u8m1_u8m1x4(val, 2, __riscv_vnclipu(__riscv_vfncvt_xu(s2, vl), 0, __RISCV_VXRM_RNU, vl));
val = __riscv_vset_v_u8m1_u8m1x4(val, 3, __riscv_vnclipu(__riscv_vfncvt_xu(s3, vl), 0, __RISCV_VXRM_RNU, vl));
__riscv_vsseg4e8(dst + i * 4, val, vl);
}
}
// the algorithm is copied from 3rdparty/carotene/src/convolution.cpp,
// in the function void CAROTENE_NS::convolution
template<int ksize>
static inline int filter(int start, int end, Filter2D* data, const uchar* src_data, size_t src_step, uchar* dst_data, int width, int height, int full_width, int full_height, int offset_x, int offset_y)
{
float kernel[ksize * ksize];
for (int i = 0; i < ksize * ksize; i++)
{
kernel[i] = reinterpret_cast<const float*>(data->kernel_data + (i / ksize) * data->kernel_step)[i % ksize];
}
constexpr int noval = std::numeric_limits<int>::max();
auto access = [&](int x, int y) {
int pi, pj;
if (data->borderType & BORDER_ISOLATED)
{
pi = borderInterpolate(x - data->anchor_y, height, data->borderType & ~BORDER_ISOLATED);
pj = borderInterpolate(y - data->anchor_x, width , data->borderType & ~BORDER_ISOLATED);
pi = pi < 0 ? noval : pi;
pj = pj < 0 ? noval : pj;
}
else
{
pi = borderInterpolate(offset_y + x - data->anchor_y, full_height, data->borderType);
pj = borderInterpolate(offset_x + y - data->anchor_x, full_width , data->borderType);
pi = pi < 0 ? noval : pi - offset_y;
pj = pj < 0 ? noval : pj - offset_x;
}
return std::make_pair(pi, pj);
};
auto process = [&](int x, int y) {
float sum0, sum1, sum2, sum3;
sum0 = sum1 = sum2 = sum3 = data->delta;
for (int i = 0; i < ksize * ksize; i++)
{
auto p = access(x + i / ksize, y + i % ksize);
if (p.first != noval && p.second != noval)
{
sum0 += kernel[i] * src_data[p.first * src_step + p.second * 4 ];
sum1 += kernel[i] * src_data[p.first * src_step + p.second * 4 + 1];
sum2 += kernel[i] * src_data[p.first * src_step + p.second * 4 + 2];
sum3 += kernel[i] * src_data[p.first * src_step + p.second * 4 + 3];
}
}
dst_data[(x * width + y) * 4 ] = std::max(0, std::min((int)std::round(sum0), (int)std::numeric_limits<uchar>::max()));
dst_data[(x * width + y) * 4 + 1] = std::max(0, std::min((int)std::round(sum1), (int)std::numeric_limits<uchar>::max()));
dst_data[(x * width + y) * 4 + 2] = std::max(0, std::min((int)std::round(sum2), (int)std::numeric_limits<uchar>::max()));
dst_data[(x * width + y) * 4 + 3] = std::max(0, std::min((int)std::round(sum3), (int)std::numeric_limits<uchar>::max()));
};
for (int i = start; i < end; i++)
{
const int left = ksize - 1, right = width - (ksize - 1);
if (left >= right)
{
for (int j = 0; j < width; j++)
process(i, j);
}
else
{
for (int j = 0; j < left; j++)
process(i, j);
for (int j = right; j < width; j++)
process(i, j);
const uchar* row0 = access(i , 0).first == noval ? nullptr : src_data + access(i , 0).first * src_step;
const uchar* row1 = access(i + 1, 0).first == noval ? nullptr : src_data + access(i + 1, 0).first * src_step;
const uchar* row2 = access(i + 2, 0).first == noval ? nullptr : src_data + access(i + 2, 0).first * src_step;
if (ksize == 3)
{
process3(data->anchor_x, left, right, data->delta, kernel, row0, row1, row2, dst_data + i * width * 4);
}
else
{
const uchar* row3 = access(i + 3, 0).first == noval ? nullptr : src_data + access(i + 3, 0).first * src_step;
const uchar* row4 = access(i + 4, 0).first == noval ? nullptr : src_data + access(i + 4, 0).first * src_step;
process5(data->anchor_x, left, right, data->delta, kernel, row0, row1, row2, row3, row4, dst_data + i * width * 4);
}
}
}
return CV_HAL_ERROR_OK;
}
inline int filter(cvhalFilter2D* context, uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, int width, int height, int full_width, int full_height, int offset_x, int offset_y)
{
Filter2D* data = reinterpret_cast<Filter2D*>(context);
std::vector<uchar> dst(width * height * 4);
int res = CV_HAL_ERROR_NOT_IMPLEMENTED;
switch (data->kernel_width)
{
case 3:
res = invoke(0, height, {filter<3>}, data, src_data, src_step, dst.data(), width, height, full_width, full_height, offset_x, offset_y);
break;
case 5:
res = invoke(0, height, {filter<5>}, data, src_data, src_step, dst.data(), width, height, full_width, full_height, offset_x, offset_y);
break;
}
for (int i = 0; i < height; i++)
std::copy(dst.data() + i * width * 4, dst.data() + (i + 1) * width * 4, dst_data + i * dst_step);
return res;
}
inline int filterFree(cvhalFilter2D* context)
{
delete reinterpret_cast<Filter2D*>(context);
return CV_HAL_ERROR_OK;
}
} // cv::cv_hal_rvv::filter
namespace sepFilter {
#undef cv_hal_sepFilterInit
#undef cv_hal_sepFilter
#undef cv_hal_sepFilterFree
#define cv_hal_sepFilterInit cv::cv_hal_rvv::sepFilter::sepFilterInit
#define cv_hal_sepFilter cv::cv_hal_rvv::sepFilter::sepFilter
#define cv_hal_sepFilterFree cv::cv_hal_rvv::sepFilter::sepFilterFree
struct sepFilter2D
{
int src_type;
int dst_type;
int kernel_type;
const uchar* kernelx_data;
int kernelx_length;
const uchar* kernely_data;
int kernely_length;
int anchor_x;
int anchor_y;
double delta;
int borderType;
};
inline int sepFilterInit(cvhalFilter2D **context, int src_type, int dst_type, int kernel_type, uchar *kernelx_data, int kernelx_length, uchar *kernely_data, int kernely_length, int anchor_x, int anchor_y, double delta, int borderType)
{
if (kernel_type != CV_32FC1 || src_type != CV_8UC1 || (dst_type != CV_16SC1 && dst_type != CV_32FC1))
return CV_HAL_ERROR_NOT_IMPLEMENTED;
if (kernelx_length != kernely_length)
return CV_HAL_ERROR_NOT_IMPLEMENTED;
if (kernelx_length != 3 && kernelx_length != 5)
return CV_HAL_ERROR_NOT_IMPLEMENTED;
if ((borderType & ~BORDER_ISOLATED) == BORDER_WRAP)
return CV_HAL_ERROR_NOT_IMPLEMENTED;
anchor_x = anchor_x < 0 ? kernelx_length / 2 : anchor_x;
anchor_y = anchor_y < 0 ? kernely_length / 2 : anchor_y;
*context = reinterpret_cast<cvhalFilter2D*>(new sepFilter2D{src_type, dst_type, kernel_type, kernelx_data, kernelx_length, kernely_data, kernely_length, anchor_x, anchor_y, delta, borderType & ~BORDER_ISOLATED});
return CV_HAL_ERROR_OK;
}
// the algorithm is copied from 3rdparty/carotene/src/separable_filter.hpp,
// in the functor RowFilter3x3S16Generic and ColFilter3x3S16Generic
template<int ksize>
static inline int sepFilterRow(int start, int end, sepFilter2D* data, const uchar* src_data, size_t src_step, float* dst_data, int width, int full_width, int offset_x)
{
constexpr int noval = std::numeric_limits<int>::max();
auto access = [&](int y) {
int pj;
if (data->borderType & BORDER_ISOLATED)
{
pj = filter::borderInterpolate(y - data->anchor_x, width, data->borderType & ~BORDER_ISOLATED);
pj = pj < 0 ? noval : pj;
}
else
{
pj = filter::borderInterpolate(offset_x + y - data->anchor_x, full_width, data->borderType);
pj = pj < 0 ? noval : pj - offset_x;
}
return pj;
};
const float* kx = reinterpret_cast<const float*>(data->kernelx_data);
auto process = [&](int x, int y) {
float sum = 0;
for (int i = 0; i < ksize; i++)
{
int p = access(y + i);
if (p != noval)
{
sum += kx[i] * src_data[x * src_step + p];
}
}
dst_data[x * width + y] = sum;
};
for (int i = start; i < end; i++)
{
const int left = ksize - 1, right = width - (ksize - 1);
if (left >= right)
{
for (int j = 0; j < width; j++)
process(i, j);
}
else
{
for (int j = 0; j < left; j++)
process(i, j);
for (int j = right; j < width; j++)
process(i, j);
int vl;
for (int j = left; j < right; j += vl)
{
vl = __riscv_vsetvl_e8m2(right - j);
const uchar* extra = src_data + i * src_step + j - data->anchor_x;
auto sum = __riscv_vfmv_v_f_f32m8(0, vl);
auto src = __riscv_vfwcvt_f(__riscv_vwcvtu_x(__riscv_vle8_v_u8m2(extra, vl), vl), vl);
sum = __riscv_vfmacc(sum, kx[0], src, vl);
src = __riscv_vfslide1down(src, extra[vl], vl);
sum = __riscv_vfmacc(sum, kx[1], src, vl);
src = __riscv_vfslide1down(src, extra[vl + 1], vl);
sum = __riscv_vfmacc(sum, kx[2], src, vl);
if (ksize == 5)
{
src = __riscv_vfslide1down(src, extra[vl + 2], vl);
sum = __riscv_vfmacc(sum, kx[3], src, vl);
src = __riscv_vfslide1down(src, extra[vl + 3], vl);
sum = __riscv_vfmacc(sum, kx[4], src, vl);
}
__riscv_vse32(dst_data + i * width + j, sum, vl);
}
}
}
return CV_HAL_ERROR_OK;
}
template<int ksize>
static inline int sepFilterCol(int start, int end, sepFilter2D* data, const float* src_data, uchar* dst_data, size_t dst_step, int width, int height, int full_height, int offset_y)
{
constexpr int noval = std::numeric_limits<int>::max();
auto access = [&](int x) {
int pi;
if (data->borderType & BORDER_ISOLATED)
{
pi = filter::borderInterpolate(x - data->anchor_y, height, data->borderType & ~BORDER_ISOLATED);
pi = pi < 0 ? noval : pi;
}
else
{
pi = filter::borderInterpolate(offset_y + x - data->anchor_y, full_height, data->borderType);
pi = pi < 0 ? noval : pi - offset_y;
}
return pi;
};
const float* ky = reinterpret_cast<const float*>(data->kernely_data);
for (int i = start; i < end; i++)
{
const float* row0 = access(i ) == noval ? nullptr : src_data + access(i ) * width;
const float* row1 = access(i + 1) == noval ? nullptr : src_data + access(i + 1) * width;
const float* row2 = access(i + 2) == noval ? nullptr : src_data + access(i + 2) * width;
const float* row3, *row4;
if (ksize == 5)
{
row3 = access(i + 3) == noval ? nullptr : src_data + access(i + 3) * width;
row4 = access(i + 4) == noval ? nullptr : src_data + access(i + 4) * width;
}
int vl;
for (int j = 0; j < width; j += vl)
{
vl = __riscv_vsetvl_e32m4(width - j);
auto v0 = row0 ? __riscv_vle32_v_f32m4(row0 + j, vl) : __riscv_vfmv_v_f_f32m4(0, vl);
auto v1 = row1 ? __riscv_vle32_v_f32m4(row1 + j, vl) : __riscv_vfmv_v_f_f32m4(0, vl);
auto v2 = row2 ? __riscv_vle32_v_f32m4(row2 + j, vl) : __riscv_vfmv_v_f_f32m4(0, vl);
auto sum = __riscv_vfmacc(__riscv_vfmacc(__riscv_vfmacc(__riscv_vfmv_v_f_f32m4(data->delta, vl), ky[0], v0, vl), ky[1], v1, vl), ky[2], v2, vl);
if (ksize == 5)
{
auto v3 = row3 ? __riscv_vle32_v_f32m4(row3 + j, vl) : __riscv_vfmv_v_f_f32m4(0, vl);
auto v4 = row4 ? __riscv_vle32_v_f32m4(row4 + j, vl) : __riscv_vfmv_v_f_f32m4(0, vl);
sum = __riscv_vfmacc(__riscv_vfmacc(sum, ky[3], v3, vl), ky[4], v4, vl);
}
if (data->dst_type == CV_16SC1)
{
__riscv_vse16(reinterpret_cast<short*>(dst_data + i * dst_step) + j, __riscv_vfncvt_x(sum, vl), vl);
}
else
{
__riscv_vse32(reinterpret_cast<float*>(dst_data + i * dst_step) + j, sum, vl);
}
}
}
return CV_HAL_ERROR_OK;
}
inline int sepFilter(cvhalFilter2D *context, uchar *src_data, size_t src_step, uchar* dst_data, size_t dst_step, int width, int height, int full_width, int full_height, int offset_x, int offset_y)
{
sepFilter2D* data = reinterpret_cast<sepFilter2D*>(context);
const int padding = data->kernelx_length - 1;
std::vector<float> _result(width * (height + 2 * padding));
float* result = _result.data() + width * padding;
int res = CV_HAL_ERROR_NOT_IMPLEMENTED;
switch (data->kernelx_length)
{
case 3:
res = filter::invoke(-std::min(offset_y, padding), height + std::min(full_height - height - offset_y, padding), {sepFilterRow<3>}, data, src_data, src_step, result, width, full_width, offset_x);
break;
case 5:
res = filter::invoke(-std::min(offset_y, padding), height + std::min(full_height - height - offset_y, padding), {sepFilterRow<5>}, data, src_data, src_step, result, width, full_width, offset_x);
break;
}
if (res == CV_HAL_ERROR_NOT_IMPLEMENTED)
return CV_HAL_ERROR_NOT_IMPLEMENTED;
switch (data->kernelx_length)
{
case 3:
return filter::invoke(0, height, {sepFilterCol<3>}, data, result, dst_data, dst_step, width, height, full_height, offset_y);
case 5:
return filter::invoke(0, height, {sepFilterCol<5>}, data, result, dst_data, dst_step, width, height, full_height, offset_y);
}
return CV_HAL_ERROR_NOT_IMPLEMENTED;
}
inline int sepFilterFree(cvhalFilter2D* context)
{
delete reinterpret_cast<sepFilter2D*>(context);
return CV_HAL_ERROR_OK;
}
} // cv::cv_hal_rvv::sepFilter
namespace morph {
#undef cv_hal_morphInit
#undef cv_hal_morph
#undef cv_hal_morphFree
#define cv_hal_morphInit cv::cv_hal_rvv::morph::morphInit
#define cv_hal_morph cv::cv_hal_rvv::morph::morph
#define cv_hal_morphFree cv::cv_hal_rvv::morph::morphFree
struct Morph2D
{
int operation;
int src_type;
int dst_type;
int kernel_type;
uchar *kernel_data;
size_t kernel_step;
int kernel_width;
int kernel_height;
int anchor_x;
int anchor_y;
int borderType;
const uchar* borderValue;
};
inline int morphInit(cvhalFilter2D** context, int operation, int src_type, int dst_type, int /*max_width*/, int /*max_height*/, int kernel_type, uchar *kernel_data, size_t kernel_step, int kernel_width, int kernel_height, int anchor_x, int anchor_y, int borderType, const double borderValue[4], int iterations, bool /*allowSubmatrix*/, bool /*allowInplace*/)
{
if (kernel_type != CV_8UC1 || src_type != dst_type)
return CV_HAL_ERROR_NOT_IMPLEMENTED;
if (src_type != CV_8UC1 && src_type != CV_8UC4)
return CV_HAL_ERROR_NOT_IMPLEMENTED;
if (kernel_width != kernel_height || kernel_width != 3)
return CV_HAL_ERROR_NOT_IMPLEMENTED;
if (iterations != 1)
return CV_HAL_ERROR_NOT_IMPLEMENTED;
if (operation != CV_HAL_MORPH_ERODE && operation != CV_HAL_MORPH_DILATE)
return CV_HAL_ERROR_NOT_IMPLEMENTED;
if ((borderType & ~BORDER_ISOLATED) == BORDER_WRAP)
return CV_HAL_ERROR_NOT_IMPLEMENTED;
uchar* borderV;
if (src_type == CV_8UC1)
{
borderV = new uchar{static_cast<uchar>(borderValue[0])};
if (operation == CV_HAL_MORPH_DILATE && borderValue[0] == DBL_MAX)
borderV[0] = 0;
}
else
{
borderV = new uchar[4]{static_cast<uchar>(borderValue[0]), static_cast<uchar>(borderValue[1]), static_cast<uchar>(borderValue[2]), static_cast<uchar>(borderValue[3])};
if (operation == CV_HAL_MORPH_DILATE)
{
if (borderValue[0] == DBL_MAX)
borderV[0] = 0;
if (borderValue[1] == DBL_MAX)
borderV[1] = 0;
if (borderValue[2] == DBL_MAX)
borderV[2] = 0;
if (borderValue[3] == DBL_MAX)
borderV[3] = 0;
}
}
anchor_x = anchor_x < 0 ? kernel_width / 2 : anchor_x;
anchor_y = anchor_y < 0 ? kernel_height / 2 : anchor_y;
*context = reinterpret_cast<cvhalFilter2D*>(new Morph2D{operation, src_type, dst_type, kernel_type, kernel_data, kernel_step, kernel_width, kernel_height, anchor_x, anchor_y, borderType, borderV});
return CV_HAL_ERROR_OK;
}
template<int op> struct rvv;
template<> struct rvv<CV_HAL_MORPH_ERODE>
{
static inline uchar init() { return std::numeric_limits<uchar>::max(); }
static inline uchar mop(uchar a, uchar b) { return a < b ? a : b; }
static inline vuint8m4_t vop(vuint8m4_t a, vuint8m4_t b, size_t c) { return __riscv_vminu(a, b, c); }
static inline vuint8m4_t vop(vuint8m4_t a, uchar b, size_t c) { return __riscv_vminu(a, b, c); }
};
template<> struct rvv<CV_HAL_MORPH_DILATE>
{
static inline uchar init() { return std::numeric_limits<uchar>::min(); }
static inline uchar mop(uchar a, uchar b) { return a > b ? a : b; }
static inline vuint8m4_t vop(vuint8m4_t a, vuint8m4_t b, size_t c) { return __riscv_vmaxu(a, b, c); }
static inline vuint8m4_t vop(vuint8m4_t a, uchar b, size_t c) { return __riscv_vmaxu(a, b, c); }
};
// the algorithm is copied from 3rdparty/carotene/src/morph.cpp,
// in the function template void morph3x3
template<int op>
static inline int morph(int start, int end, Morph2D* data, const uchar* src_data, size_t src_step, uchar* dst_data, int width, int height, int full_width, int full_height, int offset_x, int offset_y)
{
bool kernel[9];
for (int i = 0; i < 9; i++)
{
kernel[i] = data->kernel_data[(i / 3) * data->kernel_step + i % 3] != 0;
}
constexpr int noval = std::numeric_limits<int>::max();
auto access = [&](int x, int y) {
int pi, pj;
if (data->borderType & BORDER_ISOLATED)
{
pi = filter::borderInterpolate(x - data->anchor_y, height, data->borderType & ~BORDER_ISOLATED);
pj = filter::borderInterpolate(y - data->anchor_x, width , data->borderType & ~BORDER_ISOLATED);
pi = pi < 0 ? noval : pi;
pj = pj < 0 ? noval : pj;
}
else
{
pi = filter::borderInterpolate(offset_y + x - data->anchor_y, full_height, data->borderType);
pj = filter::borderInterpolate(offset_x + y - data->anchor_x, full_width , data->borderType);
pi = pi < 0 ? noval : pi - offset_y;
pj = pj < 0 ? noval : pj - offset_x;
}
return std::make_pair(pi, pj);
};
auto process = [&](int x, int y) {
if (data->src_type == CV_8UC1)
{
uchar val = rvv<op>::init();
for (int i = 0; i < 9; i++)
{
if (kernel[i])
{
auto p = access(x + i / 3, y + i % 3);
if (p.first != noval && p.second != noval)
{
val = rvv<op>::mop(val, src_data[p.first * src_step + p.second]);
}
else
{
val = rvv<op>::mop(val, data->borderValue[0]);
}
}
}
dst_data[x * width + y] = val;
}
else
{
uchar val0, val1, val2, val3;
val0 = val1 = val2 = val3 = rvv<op>::init();
for (int i = 0; i < 9; i++)
{
if (kernel[i])
{
auto p = access(x + i / 3, y + i % 3);
if (p.first != noval && p.second != noval)
{
val0 = rvv<op>::mop(val0, src_data[p.first * src_step + p.second * 4 ]);
val1 = rvv<op>::mop(val1, src_data[p.first * src_step + p.second * 4 + 1]);
val2 = rvv<op>::mop(val2, src_data[p.first * src_step + p.second * 4 + 2]);
val3 = rvv<op>::mop(val3, src_data[p.first * src_step + p.second * 4 + 3]);
}
else
{
val0 = rvv<op>::mop(val0, data->borderValue[0]);
val1 = rvv<op>::mop(val1, data->borderValue[1]);
val2 = rvv<op>::mop(val2, data->borderValue[2]);
val3 = rvv<op>::mop(val3, data->borderValue[3]);
}
}
}
dst_data[(x * width + y) * 4 ] = val0;
dst_data[(x * width + y) * 4 + 1] = val1;
dst_data[(x * width + y) * 4 + 2] = val2;
dst_data[(x * width + y) * 4 + 3] = val3;
}
};
for (int i = start; i < end; i++)
{
const int left = 2, right = width - 2;
if (left >= right)
{
for (int j = 0; j < width; j++)
process(i, j);
}
else
{
for (int j = 0; j < left; j++)
process(i, j);
for (int j = right; j < width; j++)
process(i, j);
const uchar* row0 = access(i , 0).first == noval ? nullptr : src_data + access(i , 0).first * src_step;
const uchar* row1 = access(i + 1, 0).first == noval ? nullptr : src_data + access(i + 1, 0).first * src_step;
const uchar* row2 = access(i + 2, 0).first == noval ? nullptr : src_data + access(i + 2, 0).first * src_step;
if (data->src_type == CV_8UC1)
{
int vl;
for (int j = left; j < right; j += vl)
{
vl = __riscv_vsetvl_e8m4(right - j);
auto m0 = __riscv_vmv_v_x_u8m4(rvv<op>::init(), vl);
auto loadsrc = [&](const uchar* row, bool k0, bool k1, bool k2) {
if (!row)
{
m0 = rvv<op>::vop(m0, data->borderValue[0], vl);
return;
}
const uchar* extra = row + j - data->anchor_x;
auto v0 = __riscv_vle8_v_u8m4(extra, vl);
if (k0) m0 = rvv<op>::vop(m0, v0, vl);
v0 = __riscv_vslide1down(v0, extra[vl], vl);
if (k1) m0 = rvv<op>::vop(m0, v0, vl);
if (!k2) return;
v0 = __riscv_vslide1down(v0, extra[vl + 1], vl);
m0 = rvv<op>::vop(m0, v0, vl);
};
loadsrc(row0, kernel[0], kernel[1], kernel[2]);
loadsrc(row1, kernel[3], kernel[4], kernel[5]);
loadsrc(row2, kernel[6], kernel[7], kernel[8]);
__riscv_vse8(dst_data + i * width + j, m0, vl);
}
}
else
{
int vl, vl0, vl1;
for (int j = left; j < right; j += vl)
{
vl = __riscv_vsetvl_e8m4(right - j);
vl0 = std::min(vl, (int)__riscv_vlenb() * 2);
vl1 = vl - vl0;
auto m0 = __riscv_vmv_v_x_u8m4(rvv<op>::init(), vl);
auto m1 = __riscv_vmv_v_x_u8m4(rvv<op>::init(), vl);
auto m2 = __riscv_vmv_v_x_u8m4(rvv<op>::init(), vl);
auto m3 = __riscv_vmv_v_x_u8m4(rvv<op>::init(), vl);
auto opshift = [&](vuint8m4_t a, vuint8m4_t b, bool k0, bool k1, bool k2, uchar r1, uchar r2) {
if (k0) a = rvv<op>::vop(a, b, vl);
b = __riscv_vslide1down(b, r1, vl);
if (k1) a = rvv<op>::vop(a, b, vl);
if (!k2) return a;
b = __riscv_vslide1down(b, r2, vl);
return rvv<op>::vop(a, b, vl);
};
auto loadsrc = [&](const uchar* row, bool k0, bool k1, bool k2) {
if (!row)
{
m0 = rvv<op>::vop(m0, data->borderValue[0], vl);
m1 = rvv<op>::vop(m1, data->borderValue[1], vl);
m2 = rvv<op>::vop(m2, data->borderValue[2], vl);
m3 = rvv<op>::vop(m3, data->borderValue[3], vl);
return;
}
vuint8m4_t v0{}, v1{}, v2{}, v3{};
const uchar* extra = row + (j - data->anchor_x) * 4;
auto src = __riscv_vlseg4e8_v_u8m2x4(extra, vl0);
v0 = __riscv_vset_v_u8m2_u8m4(v0, 0, __riscv_vget_v_u8m2x4_u8m2(src, 0));
v1 = __riscv_vset_v_u8m2_u8m4(v1, 0, __riscv_vget_v_u8m2x4_u8m2(src, 1));
v2 = __riscv_vset_v_u8m2_u8m4(v2, 0, __riscv_vget_v_u8m2x4_u8m2(src, 2));
v3 = __riscv_vset_v_u8m2_u8m4(v3, 0, __riscv_vget_v_u8m2x4_u8m2(src, 3));
src = __riscv_vlseg4e8_v_u8m2x4(extra + vl0 * 4, vl1);
v0 = __riscv_vset_v_u8m2_u8m4(v0, 1, __riscv_vget_v_u8m2x4_u8m2(src, 0));
v1 = __riscv_vset_v_u8m2_u8m4(v1, 1, __riscv_vget_v_u8m2x4_u8m2(src, 1));
v2 = __riscv_vset_v_u8m2_u8m4(v2, 1, __riscv_vget_v_u8m2x4_u8m2(src, 2));
v3 = __riscv_vset_v_u8m2_u8m4(v3, 1, __riscv_vget_v_u8m2x4_u8m2(src, 3));
m0 = opshift(m0, v0, k0, k1, k2, extra[vl * 4 ], extra[vl * 4 + 4]);
m1 = opshift(m1, v1, k0, k1, k2, extra[vl * 4 + 1], extra[vl * 4 + 5]);
m2 = opshift(m2, v2, k0, k1, k2, extra[vl * 4 + 2], extra[vl * 4 + 6]);
m3 = opshift(m3, v3, k0, k1, k2, extra[vl * 4 + 3], extra[vl * 4 + 7]);
};
loadsrc(row0, kernel[0], kernel[1], kernel[2]);
loadsrc(row1, kernel[3], kernel[4], kernel[5]);
loadsrc(row2, kernel[6], kernel[7], kernel[8]);
vuint8m2x4_t val{};
val = __riscv_vset_v_u8m2_u8m2x4(val, 0, __riscv_vget_v_u8m4_u8m2(m0, 0));
val = __riscv_vset_v_u8m2_u8m2x4(val, 1, __riscv_vget_v_u8m4_u8m2(m1, 0));
val = __riscv_vset_v_u8m2_u8m2x4(val, 2, __riscv_vget_v_u8m4_u8m2(m2, 0));
val = __riscv_vset_v_u8m2_u8m2x4(val, 3, __riscv_vget_v_u8m4_u8m2(m3, 0));
__riscv_vsseg4e8(dst_data + (i * width + j) * 4, val, vl0);
val = __riscv_vset_v_u8m2_u8m2x4(val, 0, __riscv_vget_v_u8m4_u8m2(m0, 1));
val = __riscv_vset_v_u8m2_u8m2x4(val, 1, __riscv_vget_v_u8m4_u8m2(m1, 1));
val = __riscv_vset_v_u8m2_u8m2x4(val, 2, __riscv_vget_v_u8m4_u8m2(m2, 1));
val = __riscv_vset_v_u8m2_u8m2x4(val, 3, __riscv_vget_v_u8m4_u8m2(m3, 1));
__riscv_vsseg4e8(dst_data + (i * width + j + vl0) * 4, val, vl1);
}
}
}
}
return CV_HAL_ERROR_OK;
}
inline int morph(cvhalFilter2D* context, uchar *src_data, size_t src_step, uchar *dst_data, size_t dst_step, int width, int height, int src_full_width, int src_full_height, int src_roi_x, int src_roi_y, int /*dst_full_width*/, int /*dst_full_height*/, int /*dst_roi_x*/, int /*dst_roi_y*/)
{
Morph2D* data = reinterpret_cast<Morph2D*>(context);
int cn = data->src_type == CV_8UC1 ? 1 : 4;
std::vector<uchar> dst(width * height * cn);
int res = CV_HAL_ERROR_NOT_IMPLEMENTED;
switch (data->operation)
{
case CV_HAL_MORPH_ERODE:
res = filter::invoke(0, height, {morph<CV_HAL_MORPH_ERODE>}, data, src_data, src_step, dst.data(), width, height, src_full_width, src_full_height, src_roi_x, src_roi_y);
break;
case CV_HAL_MORPH_DILATE:
res = filter::invoke(0, height, {morph<CV_HAL_MORPH_DILATE>}, data, src_data, src_step, dst.data(), width, height, src_full_width, src_full_height, src_roi_x, src_roi_y);
break;
}
for (int i = 0; i < height; i++)
std::copy(dst.data() + i * width * cn, dst.data() + (i + 1) * width * cn, dst_data + i * dst_step);
return res;
}
inline int morphFree(cvhalFilter2D* context)
{
delete reinterpret_cast<Morph2D*>(context)->borderValue;
delete reinterpret_cast<Morph2D*>(context);
return CV_HAL_ERROR_OK;
}
} // cv::cv_hal_rvv::morph
}}
#endif
+33 -56
View File
@@ -5,7 +5,7 @@
#include <riscv_vector.h>
#include <opencv2/core/base.hpp>
#include <opencv2/core/utility.hpp>
#include "hal_rvv_1p0/types.hpp"
namespace cv { namespace cv_hal_rvv {
@@ -14,62 +14,33 @@ namespace cv { namespace cv_hal_rvv {
struct FlipVlen256
{
using TableElemType = uchar;
using TableType = vuint8m8_t;
using SrcType = RVV_U8M8;
using TabType = RVV_U8M8;
using TabVecType = typename TabType::VecType;
static inline size_t setvlmax()
static inline void gather(const uchar* src, TabVecType tab, uchar* dst, size_t vl)
{
return __riscv_vsetvlmax_e8m8();
}
static inline TableType vid(size_t vl)
{
return __riscv_vid_v_u8m8(vl);
}
static inline TableType loadTable(const TableElemType* ptr, size_t vl)
{
return __riscv_vle8_v_u8m8(ptr, vl);
}
static inline void gather(const uchar* src, TableType tab, uchar* dst, size_t vl)
{
auto v = __riscv_vle8_v_u8m8(src, vl);
__riscv_vse8(dst, __riscv_vrgather(v, tab, vl), vl);
auto src_v = SrcType::vload(src, vl);
SrcType::vstore(dst, __riscv_vrgather(src_v, tab, vl), vl);
}
};
struct FlipVlen512
struct FlipVlen512 : RVV_U8M8
{
using TableElemType = uint16_t;
using TableType = vuint16m8_t;
using SrcType = RVV_U8M4;
using TabType = RVV_U16M8;
using TabVecType = typename TabType::VecType;
static inline size_t setvlmax()
static inline void gather(const uchar* src, TabVecType tab, uchar* dst, size_t vl)
{
return __riscv_vsetvlmax_e8m4();
}
static inline TableType vid(size_t vl)
{
return __riscv_vid_v_u16m8(vl);
}
static inline TableType loadTable(const TableElemType* ptr, size_t vl)
{
return __riscv_vle16_v_u16m8(ptr, vl);
}
static inline void gather(const uchar* src, TableType tab, uchar* dst, size_t vl)
{
auto v = __riscv_vle8_v_u8m4(src, vl);
__riscv_vse8(dst, __riscv_vrgatherei16(v, tab, vl), vl);
auto src_v = SrcType::vload(src, vl);
SrcType::vstore(dst, __riscv_vrgatherei16(src_v, tab, vl), vl);
}
};
template <typename T>
inline void flipFillBuffer(cv::AutoBuffer<T>& _buf, size_t len, int esz)
inline void flipFillBuffer(T* buf, size_t len, int esz)
{
T* buf = _buf.data();
for (int i = (int)len - esz; i >= 0; i -= esz, buf += esz)
for (int j = 0; j < esz; j++)
buf[j] = (T)(i + j);
@@ -107,7 +78,9 @@ inline void flipX(int esz,
}
}
template <typename FlipVlen>
template <typename FlipVlen,
typename SrcType = typename FlipVlen::SrcType,
typename TabType = typename FlipVlen::TabType>
inline void flipY(int esz,
const uchar* src_data,
size_t src_step,
@@ -117,15 +90,16 @@ inline void flipY(int esz,
size_t dst_step)
{
size_t w = (size_t)src_width * esz;
size_t vl = std::min(FlipVlen::setvlmax() / esz * esz, w);
typename FlipVlen::TableType tab_v;
size_t vl = std::min(SrcType::setvlmax() / esz * esz, w);
typename TabType::VecType tab_v;
if (esz == 1)
tab_v = __riscv_vrsub(FlipVlen::vid(vl), vl - 1, vl);
tab_v = __riscv_vrsub(TabType::vid(vl), vl - 1, vl);
else
{
cv::AutoBuffer<typename FlipVlen::TableElemType> buf(vl);
// max vlen supported is 1024 (vlmax of u8m4 for vlen 1024 is 512)
typename TabType::ElemType buf[512];
flipFillBuffer(buf, vl, esz);
tab_v = FlipVlen::loadTable(buf.data(), vl);
tab_v = TabType::vload(buf, vl);
}
if (vl == w)
for (; src_height; src_height--, src_data += src_step, dst_data += dst_step)
@@ -143,7 +117,9 @@ inline void flipY(int esz,
}
}
template <typename FlipVlen>
template <typename FlipVlen,
typename SrcType = typename FlipVlen::SrcType,
typename TabType = typename FlipVlen::TabType>
inline void flipXY(int esz,
const uchar* src_data,
size_t src_step,
@@ -153,15 +129,16 @@ inline void flipXY(int esz,
size_t dst_step)
{
size_t w = (size_t)src_width * esz;
size_t vl = std::min(FlipVlen::setvlmax() / esz * esz, w);
typename FlipVlen::TableType tab_v;
size_t vl = std::min(SrcType::setvlmax() / esz * esz, w);
typename TabType::VecType tab_v;
if (esz == 1)
tab_v = __riscv_vrsub(FlipVlen::vid(vl), vl - 1, vl);
tab_v = __riscv_vrsub(TabType::vid(vl), vl - 1, vl);
else
{
cv::AutoBuffer<typename FlipVlen::TableElemType> buf(vl);
// max vlen supported is 1024 (vlmax of u8m4 for vlen 1024 is 512)
typename TabType::ElemType buf[512];
flipFillBuffer(buf, vl, esz);
tab_v = FlipVlen::loadTable(buf.data(), vl);
tab_v = TabType::vload(buf, vl);
}
auto src0 = src_data, src1 = src_data + src_step * (src_height - 1);
auto dst0 = dst_data, dst1 = dst_data + dst_step * (src_height - 1);
+381
View File
@@ -0,0 +1,381 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level
// directory of this distribution and at http://opencv.org/license.html.
#pragma once
#include <riscv_vector.h>
namespace cv { namespace cv_hal_rvv {
#undef cv_hal_log32f
#define cv_hal_log32f cv::cv_hal_rvv::log32f
#undef cv_hal_log64f
#define cv_hal_log64f cv::cv_hal_rvv::log64f
namespace detail {
static constexpr size_t log_scale = 8;
static constexpr size_t log_tab_size = ((size_t)1 << log_scale) * 2;
static constexpr size_t log_mask = log_tab_size - 2;
static constexpr double ln_2 = 0.69314718055994530941723212145818;
static constexpr size_t log32f_mask = ((size_t)1 << (23 - log_scale)) - 1;
static constexpr double log32f_a0 = 0.3333333333333333333333333f;
static constexpr double log32f_a1 = -0.5f;
static constexpr double log32f_a2 = 1.f;
static constexpr size_t log64f_mask = ((size_t)1 << (52 - log_scale)) - 1;
static constexpr double log64f_a0 = -0.125;
static constexpr double log64f_a1 = 0.1428571428571428769682682968777953647077083587646484375;
static constexpr double log64f_a2 = -0.1666666666666666574148081281236954964697360992431640625;
static constexpr double log64f_a3 = 0.2;
static constexpr double log64f_a4 = -0.25;
static constexpr double log64f_a5 = 0.333333333333333314829616256247390992939472198486328125;
static constexpr double log64f_a6 = -0.5;
static constexpr double log64f_a7 = 1.0;
#define LOG_TAB_VALUE \
{ \
0.0000000000000000000000000000000000000000, 1.000000000000000000000000000000000000000, \
.00389864041565732288852075271279318258166, .9961089494163424124513618677042801556420, \
.00778214044205494809292034119607706088573, .9922480620155038759689922480620155038760, \
.01165061721997527263705585198749759001657, .9884169884169884169884169884169884169884, \
.01550418653596525274396267235488267033361, .9846153846153846153846153846153846153846, \
.01934296284313093139406447562578250654042, .9808429118773946360153256704980842911877, \
.02316705928153437593630670221500622574241, .9770992366412213740458015267175572519084, \
.02697658769820207233514075539915211265906, .9733840304182509505703422053231939163498, \
.03077165866675368732785500469617545604706, .9696969696969696969696969696969696969697, \
.03455238150665972812758397481047722976656, .9660377358490566037735849056603773584906, \
.03831886430213659461285757856785494368522, .9624060150375939849624060150375939849624, \
.04207121392068705056921373852674150839447, .9588014981273408239700374531835205992509, \
.04580953603129420126371940114040626212953, .9552238805970149253731343283582089552239, \
.04953393512227662748292900118940451648088, .9516728624535315985130111524163568773234, \
.05324451451881227759255210685296333394944, .9481481481481481481481481481481481481481, \
.05694137640013842427411105973078520037234, .9446494464944649446494464944649446494465, \
.06062462181643483993820353816772694699466, .9411764705882352941176470588235294117647, \
.06429435070539725460836422143984236754475, .9377289377289377289377289377289377289377, \
.06795066190850773679699159401934593915938, .9343065693430656934306569343065693430657, \
.07159365318700880442825962290953611955044, .9309090909090909090909090909090909090909, \
.07522342123758751775142172846244648098944, .9275362318840579710144927536231884057971, \
.07884006170777602129362549021607264876369, .9241877256317689530685920577617328519856, \
.08244366921107458556772229485432035289706, .9208633093525179856115107913669064748201, \
.08603433734180314373940490213499288074675, .9175627240143369175627240143369175627240, \
.08961215868968712416897659522874164395031, .9142857142857142857142857142857142857143, \
.09317722485418328259854092721070628613231, .9110320284697508896797153024911032028470, \
.09672962645855109897752299730200320482256, .9078014184397163120567375886524822695035, \
.10026945316367513738597949668474029749630, .9045936395759717314487632508833922261484, \
.10379679368164355934833764649738441221420, .9014084507042253521126760563380281690141, \
.10731173578908805021914218968959175981580, .8982456140350877192982456140350877192982, \
.11081436634029011301105782649756292812530, .8951048951048951048951048951048951048951, \
.11430477128005862852422325204315711744130, .8919860627177700348432055749128919860627, \
.11778303565638344185817487641543266363440, .8888888888888888888888888888888888888889, \
.12124924363286967987640707633545389398930, .8858131487889273356401384083044982698962, \
.12470347850095722663787967121606925502420, .8827586206896551724137931034482758620690, \
.12814582269193003360996385708858724683530, .8797250859106529209621993127147766323024, \
.13157635778871926146571524895989568904040, .8767123287671232876712328767123287671233, \
.13499516453750481925766280255629681050780, .8737201365187713310580204778156996587031, \
.13840232285911913123754857224412262439730, .8707482993197278911564625850340136054422, \
.14179791186025733629172407290752744302150, .8677966101694915254237288135593220338983, \
.14518200984449788903951628071808954700830, .8648648648648648648648648648648648648649, \
.14855469432313711530824207329715136438610, .8619528619528619528619528619528619528620, \
.15191604202584196858794030049466527998450, .8590604026845637583892617449664429530201, \
.15526612891112392955683674244937719777230, .8561872909698996655518394648829431438127, \
.15860503017663857283636730244325008243330, .8533333333333333333333333333333333333333, \
.16193282026931324346641360989451641216880, .8504983388704318936877076411960132890365, \
.16524957289530714521497145597095368430010, .8476821192052980132450331125827814569536, \
.16855536102980664403538924034364754334090, .8448844884488448844884488448844884488449, \
.17185025692665920060697715143760433420540, .8421052631578947368421052631578947368421, \
.17513433212784912385018287750426679849630, .8393442622950819672131147540983606557377, \
.17840765747281828179637841458315961062910, .8366013071895424836601307189542483660131, \
.18167030310763465639212199675966985523700, .8338762214983713355048859934853420195440, \
.18492233849401198964024217730184318497780, .8311688311688311688311688311688311688312, \
.18816383241818296356839823602058459073300, .8284789644012944983818770226537216828479, \
.19139485299962943898322009772527962923050, .8258064516129032258064516129032258064516, \
.19461546769967164038916962454095482826240, .8231511254019292604501607717041800643087, \
.19782574332991986754137769821682013571260, .8205128205128205128205128205128205128205, \
.20102574606059073203390141770796617493040, .8178913738019169329073482428115015974441, \
.20421554142869088876999228432396193966280, .8152866242038216560509554140127388535032, \
.20739519434607056602715147164417430758480, .8126984126984126984126984126984126984127, \
.21056476910734961416338251183333341032260, .8101265822784810126582278481012658227848, \
.21372432939771812687723695489694364368910, .8075709779179810725552050473186119873817, \
.21687393830061435506806333251006435602900, .8050314465408805031446540880503144654088, \
.22001365830528207823135744547471404075630, .8025078369905956112852664576802507836991, \
.22314355131420973710199007200571941211830, .8000000000000000000000000000000000000000, \
.22626367865045338145790765338460914790630, .7975077881619937694704049844236760124611, \
.22937410106484582006380890106811420992010, .7950310559006211180124223602484472049689, \
.23247487874309405442296849741978803649550, .7925696594427244582043343653250773993808, \
.23556607131276688371634975283086532726890, .7901234567901234567901234567901234567901, \
.23864773785017498464178231643018079921600, .7876923076923076923076923076923076923077, \
.24171993688714515924331749374687206000090, .7852760736196319018404907975460122699387, \
.24478272641769091566565919038112042471760, .7828746177370030581039755351681957186544, \
.24783616390458124145723672882013488560910, .7804878048780487804878048780487804878049, \
.25088030628580937353433455427875742316250, .7781155015197568389057750759878419452888, \
.25391520998096339667426946107298135757450, .7757575757575757575757575757575757575758, \
.25694093089750041913887912414793390780680, .7734138972809667673716012084592145015106, \
.25995752443692604627401010475296061486000, .7710843373493975903614457831325301204819, \
.26296504550088134477547896494797896593800, .7687687687687687687687687687687687687688, \
.26596354849713793599974565040611196309330, .7664670658682634730538922155688622754491, \
.26895308734550393836570947314612567424780, .7641791044776119402985074626865671641791, \
.27193371548364175804834985683555714786050, .7619047619047619047619047619047619047619, \
.27490548587279922676529508862586226314300, .7596439169139465875370919881305637982196, \
.27786845100345625159121709657483734190480, .7573964497041420118343195266272189349112, \
.28082266290088775395616949026589281857030, .7551622418879056047197640117994100294985, \
.28376817313064456316240580235898960381750, .7529411764705882352941176470588235294118, \
.28670503280395426282112225635501090437180, .7507331378299120234604105571847507331378, \
.28963329258304265634293983566749375313530, .7485380116959064327485380116959064327485, \
.29255300268637740579436012922087684273730, .7463556851311953352769679300291545189504, \
.29546421289383584252163927885703742504130, .7441860465116279069767441860465116279070, \
.29836697255179722709783618483925238251680, .7420289855072463768115942028985507246377, \
.30126133057816173455023545102449133992200, .7398843930635838150289017341040462427746, \
.30414733546729666446850615102448500692850, .7377521613832853025936599423631123919308, \
.30702503529491181888388950937951449304830, .7356321839080459770114942528735632183908, \
.30989447772286465854207904158101882785550, .7335243553008595988538681948424068767908, \
.31275571000389684739317885942000430077330, .7314285714285714285714285714285714285714, \
.31560877898630329552176476681779604405180, .7293447293447293447293447293447293447293, \
.31845373111853458869546784626436419785030, .7272727272727272727272727272727272727273, \
.32129061245373424782201254856772720813750, .7252124645892351274787535410764872521246, \
.32411946865421192853773391107097268104550, .7231638418079096045197740112994350282486, \
.32694034499585328257253991068864706903700, .7211267605633802816901408450704225352113, \
.32975328637246797969240219572384376078850, .7191011235955056179775280898876404494382, \
.33255833730007655635318997155991382896900, .7170868347338935574229691876750700280112, \
.33535554192113781191153520921943709254280, .7150837988826815642458100558659217877095, \
.33814494400871636381467055798566434532400, .7130919220055710306406685236768802228412, \
.34092658697059319283795275623560883104800, .7111111111111111111111111111111111111111, \
.34370051385331840121395430287520866841080, .7091412742382271468144044321329639889197, \
.34646676734620857063262633346312213689100, .7071823204419889502762430939226519337017, \
.34922538978528827602332285096053965389730, .7052341597796143250688705234159779614325, \
.35197642315717814209818925519357435405250, .7032967032967032967032967032967032967033, \
.35471990910292899856770532096561510115850, .7013698630136986301369863013698630136986, \
.35745588892180374385176833129662554711100, .6994535519125683060109289617486338797814, \
.36018440357500774995358483465679455548530, .6975476839237057220708446866485013623978, \
.36290549368936841911903457003063522279280, .6956521739130434782608695652173913043478, \
.36561919956096466943762379742111079394830, .6937669376693766937669376693766937669377, \
.36832556115870762614150635272380895912650, .6918918918918918918918918918918918918919, \
.37102461812787262962487488948681857436900, .6900269541778975741239892183288409703504, \
.37371640979358405898480555151763837784530, .6881720430107526881720430107526881720430, \
.37640097516425302659470730759494472295050, .6863270777479892761394101876675603217158, \
.37907835293496944251145919224654790014030, .6844919786096256684491978609625668449198, \
.38174858149084833769393299007788300514230, .6826666666666666666666666666666666666667, \
.38441169891033200034513583887019194662580, .6808510638297872340425531914893617021277, \
.38706774296844825844488013899535872042180, .6790450928381962864721485411140583554377, \
.38971675114002518602873692543653305619950, .6772486772486772486772486772486772486772, \
.39235876060286384303665840889152605086580, .6754617414248021108179419525065963060686, \
.39499380824086893770896722344332374632350, .6736842105263157894736842105263157894737, \
.39762193064713846624158577469643205404280, .6719160104986876640419947506561679790026, \
.40024316412701266276741307592601515352730, .6701570680628272251308900523560209424084, \
.40285754470108348090917615991202183067800, .6684073107049608355091383812010443864230, \
.40546510810816432934799991016916465014230, .6666666666666666666666666666666666666667, \
.40806588980822172674223224930756259709600, .6649350649350649350649350649350649350649, \
.41065992498526837639616360320360399782650, .6632124352331606217616580310880829015544, \
.41324724855021932601317757871584035456180, .6614987080103359173126614987080103359173, \
.41582789514371093497757669865677598863850, .6597938144329896907216494845360824742268, \
.41840189913888381489925905043492093682300, .6580976863753213367609254498714652956298, \
.42096929464412963239894338585145305842150, .6564102564102564102564102564102564102564, \
.42353011550580327293502591601281892508280, .6547314578005115089514066496163682864450, \
.42608439531090003260516141381231136620050, .6530612244897959183673469387755102040816, \
.42863216738969872610098832410585600882780, .6513994910941475826972010178117048346056, \
.43117346481837132143866142541810404509300, .6497461928934010152284263959390862944162, \
.43370832042155937902094819946796633303180, .6481012658227848101265822784810126582278, \
.43623676677491801667585491486534010618930, .6464646464646464646464646464646464646465, \
.43875883620762790027214350629947148263450, .6448362720403022670025188916876574307305, \
.44127456080487520440058801796112675219780, .6432160804020100502512562814070351758794, \
.44378397241030093089975139264424797147500, .6416040100250626566416040100250626566416, \
.44628710262841947420398014401143882423650, .6400000000000000000000000000000000000000, \
.44878398282700665555822183705458883196130, .6384039900249376558603491271820448877805, \
.45127464413945855836729492693848442286250, .6368159203980099502487562189054726368159, \
.45375911746712049854579618113348260521900, .6352357320099255583126550868486352357320, \
.45623743348158757315857769754074979573500, .6336633663366336633663366336633663366337, \
.45870962262697662081833982483658473938700, .6320987654320987654320987654320987654321, \
.46117571512217014895185229761409573256980, .6305418719211822660098522167487684729064, \
.46363574096303250549055974261136725544930, .6289926289926289926289926289926289926290, \
.46608972992459918316399125615134835243230, .6274509803921568627450980392156862745098, \
.46853771156323925639597405279346276074650, .6259168704156479217603911980440097799511, \
.47097971521879100631480241645476780831830, .6243902439024390243902439024390243902439, \
.47341577001667212165614273544633761048330, .6228710462287104622871046228710462287105, \
.47584590486996386493601107758877333253630, .6213592233009708737864077669902912621359, \
.47827014848147025860569669930555392056700, .6198547215496368038740920096852300242131, \
.48068852934575190261057286988943815231330, .6183574879227053140096618357487922705314, \
.48310107575113581113157579238759353756900, .6168674698795180722891566265060240963855, \
.48550781578170076890899053978500887751580, .6153846153846153846153846153846153846154, \
.48790877731923892879351001283794175833480, .6139088729016786570743405275779376498801, \
.49030398804519381705802061333088204264650, .6124401913875598086124401913875598086124, \
.49269347544257524607047571407747454941280, .6109785202863961813842482100238663484487, \
.49507726679785146739476431321236304938800, .6095238095238095238095238095238095238095, \
.49745538920281889838648226032091770321130, .6080760095011876484560570071258907363420, \
.49982786955644931126130359189119189977650, .6066350710900473933649289099526066350711, \
.50219473456671548383667413872899487614650, .6052009456264775413711583924349881796690, \
.50455601075239520092452494282042607665050, .6037735849056603773584905660377358490566, \
.50691172444485432801997148999362252652650, .6023529411764705882352941176470588235294, \
.50926190178980790257412536448100581765150, .6009389671361502347417840375586854460094, \
.51160656874906207391973111953120678663250, .5995316159250585480093676814988290398126, \
.51394575110223428282552049495279788970950, .5981308411214953271028037383177570093458, \
.51627947444845445623684554448118433356300, .5967365967365967365967365967365967365967, \
.51860776420804555186805373523384332656850, .5953488372093023255813953488372093023256, \
.52093064562418522900344441950437612831600, .5939675174013921113689095127610208816705, \
.52324814376454775732838697877014055848100, .5925925925925925925925925925925925925926, \
.52556028352292727401362526507000438869000, .5912240184757505773672055427251732101617, \
.52786708962084227803046587723656557500350, .5898617511520737327188940092165898617512, \
.53016858660912158374145519701414741575700, .5885057471264367816091954022988505747126, \
.53246479886947173376654518506256863474850, .5871559633027522935779816513761467889908, \
.53475575061602764748158733709715306758900, .5858123569794050343249427917620137299771, \
.53704146589688361856929077475797384977350, .5844748858447488584474885844748858447489, \
.53932196859560876944783558428753167390800, .5831435079726651480637813211845102505695, \
.54159728243274429804188230264117009937750, .5818181818181818181818181818181818181818, \
.54386743096728351609669971367111429572100, .5804988662131519274376417233560090702948, \
.54613243759813556721383065450936555862450, .5791855203619909502262443438914027149321, \
.54839232556557315767520321969641372561450, .5778781038374717832957110609480812641084, \
.55064711795266219063194057525834068655950, .5765765765765765765765765765765765765766, \
.55289683768667763352766542084282264113450, .5752808988764044943820224719101123595506, \
.55514150754050151093110798683483153581600, .5739910313901345291479820627802690582960, \
.55738115013400635344709144192165695130850, .5727069351230425055928411633109619686801, \
.55961578793542265941596269840374588966350, .5714285714285714285714285714285714285714, \
.56184544326269181269140062795486301183700, .5701559020044543429844097995545657015590, \
.56407013828480290218436721261241473257550, .5688888888888888888888888888888888888889, \
.56628989502311577464155334382667206227800, .5676274944567627494456762749445676274945, \
.56850473535266865532378233183408156037350, .5663716814159292035398230088495575221239, \
.57071468100347144680739575051120482385150, .5651214128035320088300220750551876379691, \
.57291975356178548306473885531886480748650, .5638766519823788546255506607929515418502, \
.57511997447138785144460371157038025558000, .5626373626373626373626373626373626373626, \
.57731536503482350219940144597785547375700, .5614035087719298245614035087719298245614, \
.57950594641464214795689713355386629700650, .5601750547045951859956236323851203501094, \
.58169173963462239562716149521293118596100, .5589519650655021834061135371179039301310, \
.58387276558098266665552955601015128195300, .5577342047930283224400871459694989106754, \
.58604904500357812846544902640744112432000, .5565217391304347826086956521739130434783, \
.58822059851708596855957011939608491957200, .5553145336225596529284164859002169197397, \
.59038744660217634674381770309992134571100, .5541125541125541125541125541125541125541, \
.59254960960667157898740242671919986605650, .5529157667386609071274298056155507559395, \
.59470710774669277576265358220553025603300, .5517241379310344827586206896551724137931, \
.59685996110779382384237123915227130055450, .5505376344086021505376344086021505376344, \
.59900818964608337768851242799428291618800, .5493562231759656652360515021459227467811, \
.60115181318933474940990890900138765573500, .5481798715203426124197002141327623126338, \
.60329085143808425240052883964381180703650, .5470085470085470085470085470085470085470, \
.60542532396671688843525771517306566238400, .5458422174840085287846481876332622601279, \
.60755525022454170969155029524699784815300, .5446808510638297872340425531914893617021, \
.60968064953685519036241657886421307921400, .5435244161358811040339702760084925690021, \
.61180154110599282990534675263916142284850, .5423728813559322033898305084745762711864, \
.61391794401237043121710712512140162289150, .5412262156448202959830866807610993657505, \
.61602987721551394351138242200249806046500, .5400843881856540084388185654008438818565, \
.61813735955507864705538167982012964785100, .5389473684210526315789473684210526315789, \
.62024040975185745772080281312810257077200, .5378151260504201680672268907563025210084, \
.62233904640877868441606324267922900617100, .5366876310272536687631027253668763102725, \
.62443328801189346144440150965237990021700, .5355648535564853556485355648535564853556, \
.62652315293135274476554741340805776417250, .5344467640918580375782881002087682672234, \
.62860865942237409420556559780379757285100, .5333333333333333333333333333333333333333, \
.63068982562619868570408243613201193511500, .5322245322245322245322245322245322245322, \
.63276666957103777644277897707070223987100, .5311203319502074688796680497925311203320, \
.63483920917301017716738442686619237065300, .5300207039337474120082815734989648033126, \
.63690746223706917739093569252872839570050, .5289256198347107438016528925619834710744, \
.63897144645792069983514238629140891134750, .5278350515463917525773195876288659793814, \
.64103117942093124081992527862894348800200, .5267489711934156378600823045267489711934, \
.64308667860302726193566513757104985415950, .5256673511293634496919917864476386036961, \
.64513796137358470073053240412264131009600, .5245901639344262295081967213114754098361, \
.64718504499530948859131740391603671014300, .5235173824130879345603271983640081799591, \
.64922794662510974195157587018911726772800, .5224489795918367346938775510204081632653, \
.65126668331495807251485530287027359008800, .5213849287169042769857433808553971486762, \
.65330127201274557080523663898929953575150, .5203252032520325203252032520325203252033, \
.65533172956312757406749369692988693714150, .5192697768762677484787018255578093306288, \
.65735807270835999727154330685152672231200, .5182186234817813765182186234817813765182, \
.65938031808912778153342060249997302889800, .5171717171717171717171717171717171717172, \
.66139848224536490484126716182800009846700, .5161290322580645161290322580645161290323, \
.66341258161706617713093692145776003599150, .5150905432595573440643863179074446680080, \
.66542263254509037562201001492212526500250, .5140562248995983935742971887550200803213, \
.66742865127195616370414654738851822912700, .5130260521042084168336673346693386773547, \
.66943065394262923906154583164607174694550, .5120000000000000000000000000000000000000, \
.67142865660530226534774556057527661323550, .5109780439121756487025948103792415169661, \
.67342267521216669923234121597488410770900, .5099601593625498007968127490039840637450, \
.67541272562017662384192817626171745359900, .5089463220675944333996023856858846918489, \
.67739882359180603188519853574689477682100, .5079365079365079365079365079365079365079, \
.67938098479579733801614338517538271844400, .5069306930693069306930693069306930693069, \
.68135922480790300781450241629499942064300, .5059288537549407114624505928853754940711, \
.68333355911162063645036823800182901322850, .5049309664694280078895463510848126232742, \
.68530400309891936760919861626462079584600, .5039370078740157480314960629921259842520, \
.68727057207096020619019327568821609020250, .5029469548133595284872298624754420432220, \
.68923328123880889251040571252815425395950, .5019607843137254901960784313725490196078, \
.69314718055994530941723212145818, 5.0e-01, \
}
static constexpr float log_tab_32f[log_tab_size] = LOG_TAB_VALUE;
static constexpr double log_tab_64f[log_tab_size] = LOG_TAB_VALUE;
#undef LOG_TAB_VALUE
} // namespace detail
inline int log32f(const float* src, float* dst, int _len)
{
size_t vl = __riscv_vsetvlmax_e32m4();
auto log_a2 = __riscv_vfmv_v_f_f32m4(detail::log32f_a2, vl);
for (size_t len = _len; len > 0; len -= vl, src += vl, dst += vl)
{
vl = __riscv_vsetvl_e32m4(len);
auto i0 = __riscv_vle32_v_i32m4((const int32_t*)src, vl);
auto buf_i = __riscv_vor(__riscv_vand(i0, detail::log32f_mask, vl), 127 << 23, vl);
auto idx = __riscv_vreinterpret_u32m4(__riscv_vand(
__riscv_vsra(i0, 23 - detail::log_scale - 1 - 2, vl),
detail::log_mask << 2,
vl));
auto tab_v = __riscv_vluxei32(detail::log_tab_32f, idx, vl);
auto y0_i = __riscv_vsub(__riscv_vand(__riscv_vsra(i0, 23, vl), 0xff, vl), 127, vl);
auto y0 = __riscv_vfmadd(__riscv_vfcvt_f_x_v_f32m4(y0_i, vl), detail::ln_2, tab_v, vl);
tab_v = __riscv_vluxei32(detail::log_tab_32f, __riscv_vadd(idx, 4, vl), vl);
auto buf_f = __riscv_vreinterpret_f32m4(buf_i);
auto x0 = __riscv_vfmul(__riscv_vfsub(buf_f, 1.f, vl), tab_v, vl);
x0 = __riscv_vfsub_mu(__riscv_vmseq(idx, (uint32_t)510 * 4, vl), x0, x0, 1.f / 512, vl);
auto res = __riscv_vfadd(__riscv_vfmul(x0, detail::log32f_a0, vl), detail::log32f_a1, vl);
res = __riscv_vfmadd(res, x0, log_a2, vl);
res = __riscv_vfmadd(res, x0, y0, vl);
__riscv_vse32(dst, res, vl);
}
return CV_HAL_ERROR_OK;
}
inline int log64f(const double* src, double* dst, int _len)
{
size_t vl = __riscv_vsetvlmax_e64m4();
// all vector registers are used up, so not load more constants
auto log_a5 = __riscv_vfmv_v_f_f64m4(detail::log64f_a5, vl);
auto log_a6 = __riscv_vfmv_v_f_f64m4(detail::log64f_a6, vl);
auto log_a7 = __riscv_vfmv_v_f_f64m4(detail::log64f_a7, vl);
for (size_t len = _len; len > 0; len -= vl, src += vl, dst += vl)
{
vl = __riscv_vsetvl_e64m4(len);
auto i0 = __riscv_vle64_v_i64m4((const int64_t*)src, vl);
auto buf_i = __riscv_vor(__riscv_vand(i0, detail::log64f_mask, vl), (size_t)1023 << 52, vl);
auto idx = __riscv_vreinterpret_u64m4(__riscv_vand(
__riscv_vsra(i0, 52 - detail::log_scale - 1 - 3, vl),
detail::log_mask << 3,
vl));
auto tab_v = __riscv_vluxei64(detail::log_tab_64f, idx, vl);
auto y0_i = __riscv_vsub(__riscv_vand(__riscv_vsra(i0, 52, vl), 0x7ff, vl), 1023, vl);
auto y0 = __riscv_vfmadd(__riscv_vfcvt_f_x_v_f64m4(y0_i, vl), detail::ln_2, tab_v, vl);
tab_v = __riscv_vluxei64(detail::log_tab_64f, __riscv_vadd(idx, 8, vl), vl);
auto buf_f = __riscv_vreinterpret_f64m4(buf_i);
auto x0 = __riscv_vfmul(__riscv_vfsub(buf_f, 1.0, vl), tab_v, vl);
x0 = __riscv_vfsub_mu(__riscv_vmseq(idx, (uint64_t)510 * 8, vl), x0, x0, 1. / 512, vl);
auto res = __riscv_vfadd(__riscv_vfmul(x0, detail::log64f_a0, vl), detail::log64f_a1, vl);
res = __riscv_vfadd(__riscv_vfmul(x0, res, vl), detail::log64f_a2, vl);
res = __riscv_vfadd(__riscv_vfmul(x0, res, vl), detail::log64f_a3, vl);
res = __riscv_vfadd(__riscv_vfmul(x0, res, vl), detail::log64f_a4, vl);
res = __riscv_vfmadd(res, x0, log_a5, vl);
res = __riscv_vfmadd(res, x0, log_a6, vl);
res = __riscv_vfmadd(res, x0, log_a7, vl);
res = __riscv_vfmadd(res, x0, y0, vl);
__riscv_vse64(dst, res, vl);
}
return CV_HAL_ERROR_OK;
}
}} // namespace cv::cv_hal_rvv
+169
View File
@@ -0,0 +1,169 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#ifndef OPENCV_HAL_RVV_LU_HPP_INCLUDED
#define OPENCV_HAL_RVV_LU_HPP_INCLUDED
#include <cfloat>
#include <cmath>
#include <typeinfo>
#include <riscv_vector.h>
#include "hal_rvv_1p0/types.hpp"
namespace cv { namespace cv_hal_rvv { namespace lu {
#undef cv_hal_LU32f
#define cv_hal_LU32f cv::cv_hal_rvv::lu::LU<cv::cv_hal_rvv::RVV_F32M4>
#undef cv_hal_LU64f
#define cv_hal_LU64f cv::cv_hal_rvv::lu::LU<cv::cv_hal_rvv::RVV_F64M4>
// the algorithm is copied from core/src/matrix_decomp.cpp,
// in the function template static int cv::LUImpl
template<typename RVV_T, typename T = typename RVV_T::ElemType>
inline int LU(T* src1, size_t src1_step, int m, T* src2, size_t src2_step, int n, int* info)
{
T eps;
if( typeid(T) == typeid(float) )
eps = FLT_EPSILON*10;
else if( typeid(T) == typeid(double) )
eps = DBL_EPSILON*100;
else
return CV_HAL_ERROR_NOT_IMPLEMENTED;
int i, j, k, p = 1;
src1_step /= sizeof(src1[0]);
src2_step /= sizeof(src2[0]);
int vlmax = RVV_T::setvlmax(), vl;
if( src2 )
{
for( i = 0; i < m; i++ )
{
k = i;
for( j = i+1; j < m; j++ )
if( std::abs(src1[j*src1_step + i]) > std::abs(src1[k*src1_step + i]) )
k = j;
if( std::abs(src1[k*src1_step + i]) < eps )
{
*info = 0;
return CV_HAL_ERROR_OK;
}
if( k != i )
{
for( j = i; j < m; j += vl )
{
vl = RVV_T::setvl(m - j);
auto vec_src1 = RVV_T::vload(src1 + i * src1_step + j, vl);
auto vec_src2 = RVV_T::vload(src1 + k * src1_step + j, vl);
RVV_T::vstore(src1 + k * src1_step + j, vec_src1, vl);
RVV_T::vstore(src1 + i * src1_step + j, vec_src2, vl);
}
for( j = 0; j < n; j += vl )
{
vl = RVV_T::setvl(n - j);
auto vec_src1 = RVV_T::vload(src2 + i * src2_step + j, vl);
auto vec_src2 = RVV_T::vload(src2 + k * src2_step + j, vl);
RVV_T::vstore(src2 + k * src2_step + j, vec_src1, vl);
RVV_T::vstore(src2 + i * src2_step + j, vec_src2, vl);
}
p = -p;
}
T d = -1/src1[i*src1_step + i];
for( j = i+1; j < m; j++ )
{
T alpha = src1[j*src1_step + i]*d;
for( k = i+1; k < m; k += vl )
{
vl = RVV_T::setvl(m - k);
auto vec_src = RVV_T::vload(src1 + i * src1_step + k, vl);
auto vec_dst = RVV_T::vload(src1 + j * src1_step + k, vl);
vec_dst = __riscv_vfmacc(vec_dst, alpha, vec_src, vl);
RVV_T::vstore(src1 + j * src1_step + k, vec_dst, vl);
}
for( k = 0; k < n; k += vl )
{
vl = RVV_T::setvl(n - k);
auto vec_src = RVV_T::vload(src2 + i * src2_step + k, vl);
auto vec_dst = RVV_T::vload(src2 + j * src2_step + k, vl);
vec_dst = __riscv_vfmacc(vec_dst, alpha, vec_src, vl);
RVV_T::vstore(src2 + j * src2_step + k, vec_dst, vl);
}
}
}
for( i = m-1; i >= 0; i-- )
for( j = 0; j < n; j++ )
{
T s = src2[i*src2_step + j];
auto vec_sum = RVV_T::vmv(0, vlmax);
for( k = i+1; k < m; k += vl )
{
vl = RVV_T::setvl(m - k);
auto vec_src1 = RVV_T::vload(src1 + i * src1_step + k, vl);
auto vec_src2 = RVV_T::vload_stride(src2 + k * src2_step + j, sizeof(T) * src2_step, vl);
vec_sum = __riscv_vfmacc_tu(vec_sum, vec_src1, vec_src2, vl);
}
s -= __riscv_vfmv_f(__riscv_vfredosum(vec_sum, RVV_BaseType<RVV_T>::vmv_s(0, vlmax), vlmax));
src2[i*src2_step + j] = s/src1[i*src1_step + i];
}
}
else
{
for( i = 0; i < m; i++ )
{
k = i;
for( j = i+1; j < m; j++ )
if( std::abs(src1[j*src1_step + i]) > std::abs(src1[k*src1_step + i]) )
k = j;
if( std::abs(src1[k*src1_step + i]) < eps )
{
*info = 0;
return CV_HAL_ERROR_OK;
}
if( k != i )
{
for( j = i; j < m; j += vl )
{
vl = RVV_T::setvl(m - j);
auto vec_src1 = RVV_T::vload(src1 + i * src1_step + j, vl);
auto vec_src2 = RVV_T::vload(src1 + k * src1_step + j, vl);
RVV_T::vstore(src1 + k * src1_step + j, vec_src1, vl);
RVV_T::vstore(src1 + i * src1_step + j, vec_src2, vl);
}
p = -p;
}
T d = -1/src1[i*src1_step + i];
for( j = i+1; j < m; j++ )
{
T alpha = src1[j*src1_step + i]*d;
for( k = i+1; k < m; k += vl )
{
vl = RVV_T::setvl(m - k);
auto vec_src = RVV_T::vload(src1 + i * src1_step + k, vl);
auto vec_dst = RVV_T::vload(src1 + j * src1_step + k, vl);
vec_dst = __riscv_vfmacc(vec_dst, alpha, vec_src, vl);
RVV_T::vstore(src1 + j * src1_step + k, vec_dst, vl);
}
}
}
}
*info = p;
return CV_HAL_ERROR_OK;
}
}}}
#endif
+190
View File
@@ -0,0 +1,190 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#pragma once
#include <riscv_vector.h>
#include <opencv2/core/base.hpp>
#include <opencv2/core/utility.hpp>
#include "hal_rvv_1p0/types.hpp"
namespace cv { namespace cv_hal_rvv {
#undef cv_hal_lut
#define cv_hal_lut cv::cv_hal_rvv::lut
// need vlen >= 256
struct LUTCacheU8 : RVV_U8M8
{
using TabType = RVV_U8M8;
using SrcType = RVV_SameLen<uint8_t, TabType>;
using IdxType = RVV_SameLen<uint8_t, TabType>;
using ElemType = typename TabType::ElemType;
constexpr static size_t elem_size = sizeof(ElemType);
static inline typename TabType::VecType
gather(typename IdxType::VecType src_v, typename TabType::VecType lut_v, size_t vl)
{
return __riscv_vrgather(lut_v, src_v, vl);
}
};
// need vlen >= 512
struct LUTCacheU16 : RVV_U16M8
{
using TabType = RVV_U16M8;
using SrcType = RVV_SameLen<uint8_t, TabType>;
using IdxType = RVV_SameLen<uint16_t, TabType>;
using ElemType = typename TabType::ElemType;
constexpr static size_t elem_size = sizeof(ElemType);
static inline typename TabType::VecType
gather(typename IdxType::VecType src_v, typename TabType::VecType lut_v, size_t vl)
{
return __riscv_vrgather(lut_v, src_v, vl);
}
};
// need vlen >= 1024
struct LUTCacheU32 : RVV_U32M8
{
using TabType = RVV_U32M8;
using SrcType = RVV_SameLen<uint8_t, TabType>;
using IdxType = RVV_SameLen<uint16_t, TabType>;
using ElemType = typename TabType::ElemType;
constexpr static size_t elem_size = sizeof(ElemType);
static inline typename TabType::VecType
gather(typename IdxType::VecType src_v, typename TabType::VecType lut_v, size_t vl)
{
return __riscv_vrgatherei16(lut_v, src_v, vl);
}
};
template <typename LUT_TYPE>
class LUTParallelBody : public cv::ParallelLoopBody
{
using ElemType = typename LUT_TYPE::ElemType;
public:
const uchar* src_data;
const uchar* lut_data;
uchar* dst_data;
size_t src_step;
size_t dst_step;
size_t width;
LUTParallelBody(const uchar* src_data,
size_t src_step,
const uchar* lut_data,
uchar* dst_data,
size_t dst_step,
size_t width) :
src_data(src_data), lut_data(lut_data), dst_data(dst_data), src_step(src_step),
dst_step(dst_step), width(width)
{
}
void operator()(const cv::Range& range) const CV_OVERRIDE
{
auto src = src_data + range.start * src_step;
auto dst = dst_data + range.start * dst_step;
size_t h = range.size();
size_t w = width;
if (w == src_step && w * LUT_TYPE::elem_size == dst_step)
{
w = w * h;
h = 1;
}
auto lut = LUT_TYPE::vload((ElemType*)lut_data, 256);
size_t maxlv = LUT_TYPE::setvlmax();
for (; h; h--, src += src_step, dst += dst_step)
{
size_t vl = maxlv;
size_t l = w;
auto s = src;
auto d = (ElemType*)dst;
for (; l >= vl; l -= vl, s += vl, d += vl)
{
auto src_v = LUT_TYPE::SrcType::vload(s, vl);
auto idx_v = LUT_TYPE::IdxType::cast(src_v, vl);
auto dst_v = LUT_TYPE::gather(idx_v, lut, vl);
LUT_TYPE::vstore(d, dst_v, vl);
}
for (; l > 0; l -= vl, s += vl, d += vl)
{
vl = LUT_TYPE::setvl(l);
auto src_v = LUT_TYPE::SrcType::vload(s, vl);
auto idx_v = LUT_TYPE::IdxType::cast(src_v, vl);
auto dst_v = LUT_TYPE::gather(idx_v, lut, vl);
LUT_TYPE::vstore(d, dst_v, vl);
}
}
}
private:
LUTParallelBody(const LUTParallelBody&);
LUTParallelBody& operator=(const LUTParallelBody&);
};
inline int lut(const uchar* src_data,
size_t src_step,
size_t src_type,
const uchar* lut_data,
size_t lut_channel_size,
size_t lut_channels,
uchar* dst_data,
size_t dst_step,
int width,
int height)
{
if (width <= 0 || height <= 0)
return CV_HAL_ERROR_NOT_IMPLEMENTED;
size_t w = width;
size_t h = height;
size_t vlen = __riscv_vsetvlmax_e8m8();
if (lut_channels == 1)
{
w *= CV_MAT_CN(src_type);
// Actually, vlen 128 can use four u8m4 vectors to load the whole table, gather and merge
// the result, but the performance is almost the same as the scalar.
if (lut_channel_size == 1 && vlen >= 256)
{
LUTParallelBody<LUTCacheU8> body(src_data, src_step, lut_data, dst_data, dst_step, w);
Range all(0, height);
if (w * h >= (1 << 18))
cv::parallel_for_(all, body);
else
body(all);
return CV_HAL_ERROR_OK;
}
else if (lut_channel_size == 2 && vlen >= 512)
{
LUTParallelBody<LUTCacheU16> body(src_data, src_step, lut_data, dst_data, dst_step, w);
Range all(0, height);
if (w * h >= (1 << 18))
cv::parallel_for_(all, body);
else
body(all);
return CV_HAL_ERROR_OK;
}
else if (lut_channel_size == 4 && vlen >= 1024)
{
LUTParallelBody<LUTCacheU32> body(src_data, src_step, lut_data, dst_data, dst_step, w);
Range all(0, height);
if (w * h >= (1 << 18))
cv::parallel_for_(all, body);
else
body(all);
return CV_HAL_ERROR_OK;
}
}
return CV_HAL_ERROR_NOT_IMPLEMENTED;
}
}} // namespace cv::cv_hal_rvv
+60 -109
View File
@@ -1,76 +1,27 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#ifndef OPENCV_HAL_RVV_MINMAXIDX_HPP_INCLUDED
#define OPENCV_HAL_RVV_MINMAXIDX_HPP_INCLUDED
#ifndef OPENCV_HAL_RVV_MINMAX_HPP_INCLUDED
#define OPENCV_HAL_RVV_MINMAX_HPP_INCLUDED
#include <riscv_vector.h>
#include <opencv2/core/base.hpp>
#include "hal_rvv_1p0/types.hpp"
namespace cv { namespace cv_hal_rvv {
namespace cv { namespace cv_hal_rvv { namespace minmax {
#undef cv_hal_minMaxIdx
#define cv_hal_minMaxIdx cv::cv_hal_rvv::minMaxIdx
#define cv_hal_minMaxIdx cv::cv_hal_rvv::minmax::minMaxIdx
#undef cv_hal_minMaxIdxMaskStep
#define cv_hal_minMaxIdxMaskStep cv::cv_hal_rvv::minMaxIdx
#define cv_hal_minMaxIdxMaskStep cv::cv_hal_rvv::minmax::minMaxIdx
namespace
{
template<typename T> struct rvv;
#define HAL_RVV_GENERATOR(T, EEW, TYPE, IS_U, EMUL, M_EMUL, B_LEN) \
template<> struct rvv<T> \
{ \
using vec_t = v##IS_U##int##EEW##EMUL##_t; \
using bool_t = vbool##B_LEN##_t; \
static inline size_t vsetvlmax() { return __riscv_vsetvlmax_e##EEW##EMUL(); } \
static inline size_t vsetvl(size_t a) { return __riscv_vsetvl_e##EEW##EMUL(a); } \
static inline vec_t vmv_v_x(T a, size_t b) { return __riscv_vmv_v_x_##TYPE##EMUL(a, b); } \
static inline vec_t vle(const T* a, size_t b) { return __riscv_vle##EEW##_v_##TYPE##EMUL(a, b); } \
static inline vuint8##M_EMUL##_t vle_mask(const uchar* a, size_t b) { return __riscv_vle8_v_u8##M_EMUL(a, b); } \
static inline vec_t vmin_tu(vec_t a, vec_t b, vec_t c, size_t d) { return __riscv_vmin##IS_U##_tu(a, b, c, d); } \
static inline vec_t vmax_tu(vec_t a, vec_t b, vec_t c, size_t d) { return __riscv_vmax##IS_U##_tu(a, b, c, d); } \
static inline vec_t vmin_tumu(bool_t a, vec_t b, vec_t c, vec_t d, size_t e) { return __riscv_vmin##IS_U##_tumu(a, b, c, d, e); } \
static inline vec_t vmax_tumu(bool_t a, vec_t b, vec_t c, vec_t d, size_t e) { return __riscv_vmax##IS_U##_tumu(a, b, c, d, e); } \
static inline vec_t vredmin(vec_t a, vec_t b, size_t c) { return __riscv_vredmin##IS_U(a, b, c); } \
static inline vec_t vredmax(vec_t a, vec_t b, size_t c) { return __riscv_vredmax##IS_U(a, b, c); } \
};
HAL_RVV_GENERATOR(uchar , 8 , u8 , u, m1, m1 , 8 )
HAL_RVV_GENERATOR(schar , 8 , i8 , , m1, m1 , 8 )
HAL_RVV_GENERATOR(ushort, 16, u16, u, m1, mf2, 16)
HAL_RVV_GENERATOR(short , 16, i16, , m1, mf2, 16)
#undef HAL_RVV_GENERATOR
#define HAL_RVV_GENERATOR(T, NAME, EEW, TYPE, IS_F, F_OR_S, F_OR_X, EMUL, M_EMUL, P_EMUL, B_LEN) \
template<> struct rvv<T> \
{ \
using vec_t = v##NAME##EEW##EMUL##_t; \
using bool_t = vbool##B_LEN##_t; \
static inline size_t vsetvlmax() { return __riscv_vsetvlmax_e##EEW##EMUL(); } \
static inline size_t vsetvl(size_t a) { return __riscv_vsetvl_e##EEW##EMUL(a); } \
static inline vec_t vmv_v_x(T a, size_t b) { return __riscv_v##IS_F##mv_v_##F_OR_X##_##TYPE##EMUL(a, b); } \
static inline vuint32##P_EMUL##_t vid(size_t a) { return __riscv_vid_v_u32##P_EMUL(a); } \
static inline vuint32##P_EMUL##_t vundefined() { return __riscv_vundefined_u32##P_EMUL(); } \
static inline vec_t vle(const T* a, size_t b) { return __riscv_vle##EEW##_v_##TYPE##EMUL(a, b); } \
static inline vuint8##M_EMUL##_t vle_mask(const uchar* a, size_t b) { return __riscv_vle8_v_u8##M_EMUL(a, b); } \
static inline bool_t vmlt(vec_t a, vec_t b, size_t c) { return __riscv_vm##F_OR_S##lt(a, b, c); } \
static inline bool_t vmgt(vec_t a, vec_t b, size_t c) { return __riscv_vm##F_OR_S##gt(a, b, c); } \
static inline bool_t vmlt_mu(bool_t a, bool_t b, vec_t c, vec_t d, size_t e) { return __riscv_vm##F_OR_S##lt##_mu(a, b, c, d, e); } \
static inline bool_t vmgt_mu(bool_t a, bool_t b, vec_t c, vec_t d, size_t e) { return __riscv_vm##F_OR_S##gt##_mu(a, b, c, d, e); } \
static inline T vmv_x_s(vec_t a) { return __riscv_v##IS_F##mv_##F_OR_X(a); } \
};
HAL_RVV_GENERATOR(int , int , 32, i32, , s, x, m4, m1 , m4, 8 )
HAL_RVV_GENERATOR(float , float, 32, f32, f, f, f, m4, m1 , m4, 8 )
HAL_RVV_GENERATOR(double, float, 64, f64, f, f, f, m4, mf2, m2, 16)
#undef HAL_RVV_GENERATOR
}
template<typename T>
template<typename VEC_T, typename BOOL_T, typename T = typename VEC_T::ElemType>
inline int minMaxIdxReadTwice(const uchar* src_data, size_t src_step, int width, int height, double* minVal, double* maxVal,
int* minIdx, int* maxIdx, uchar* mask, size_t mask_step)
{
int vlmax = rvv<T>::vsetvlmax();
auto vec_min = rvv<T>::vmv_v_x(std::numeric_limits<T>::max(), vlmax);
auto vec_max = rvv<T>::vmv_v_x(std::numeric_limits<T>::lowest(), vlmax);
int vlmax = VEC_T::setvlmax();
auto vec_min = VEC_T::vmv(std::numeric_limits<T>::max(), vlmax);
auto vec_max = VEC_T::vmv(std::numeric_limits<T>::lowest(), vlmax);
T val_min, val_max;
if (mask)
@@ -82,19 +33,19 @@ inline int minMaxIdxReadTwice(const uchar* src_data, size_t src_step, int width,
int vl;
for (int j = 0; j < width; j += vl)
{
vl = rvv<T>::vsetvl(width - j);
auto vec_src = rvv<T>::vle(src_row + j, vl);
auto vec_mask = rvv<T>::vle_mask(mask_row + j, vl);
vl = VEC_T::setvl(width - j);
auto vec_src = VEC_T::vload(src_row + j, vl);
auto vec_mask = BOOL_T::vload(mask_row + j, vl);
auto bool_mask = __riscv_vmsne(vec_mask, 0, vl);
vec_min = rvv<T>::vmin_tumu(bool_mask, vec_min, vec_min, vec_src, vl);
vec_max = rvv<T>::vmax_tumu(bool_mask, vec_max, vec_max, vec_src, vl);
vec_min = VEC_T::vmin_tumu(bool_mask, vec_min, vec_min, vec_src, vl);
vec_max = VEC_T::vmax_tumu(bool_mask, vec_max, vec_max, vec_src, vl);
}
}
auto sc_minval = rvv<T>::vmv_v_x(std::numeric_limits<T>::max(), vlmax);
auto sc_maxval = rvv<T>::vmv_v_x(std::numeric_limits<T>::lowest(), vlmax);
sc_minval = rvv<T>::vredmin(vec_min, sc_minval, vlmax);
sc_maxval = rvv<T>::vredmax(vec_max, sc_maxval, vlmax);
auto sc_minval = VEC_T::vmv(std::numeric_limits<T>::max(), vlmax);
auto sc_maxval = VEC_T::vmv(std::numeric_limits<T>::lowest(), vlmax);
sc_minval = VEC_T::vredmin(vec_min, sc_minval, vlmax);
sc_maxval = VEC_T::vredmax(vec_max, sc_maxval, vlmax);
val_min = __riscv_vmv_x(sc_minval);
val_max = __riscv_vmv_x(sc_maxval);
@@ -106,9 +57,9 @@ inline int minMaxIdxReadTwice(const uchar* src_data, size_t src_step, int width,
int vl;
for (int j = 0; j < width && (!found_min || !found_max); j += vl)
{
vl = rvv<T>::vsetvl(width - j);
auto vec_src = rvv<T>::vle(src_row + j, vl);
auto vec_mask = rvv<T>::vle_mask(mask_row + j, vl);
vl = VEC_T::setvl(width - j);
auto vec_src = VEC_T::vload(src_row + j, vl);
auto vec_mask = BOOL_T::vload(mask_row + j, vl);
auto bool_mask = __riscv_vmsne(vec_mask, 0, vl);
auto bool_zero = __riscv_vmxor(bool_mask, bool_mask, vl);
if (!found_min)
@@ -148,17 +99,17 @@ inline int minMaxIdxReadTwice(const uchar* src_data, size_t src_step, int width,
int vl;
for (int j = 0; j < width; j += vl)
{
vl = rvv<T>::vsetvl(width - j);
auto vec_src = rvv<T>::vle(src_row + j, vl);
vec_min = rvv<T>::vmin_tu(vec_min, vec_min, vec_src, vl);
vec_max = rvv<T>::vmax_tu(vec_max, vec_max, vec_src, vl);
vl = VEC_T::setvl(width - j);
auto vec_src = VEC_T::vload(src_row + j, vl);
vec_min = VEC_T::vmin_tu(vec_min, vec_min, vec_src, vl);
vec_max = VEC_T::vmax_tu(vec_max, vec_max, vec_src, vl);
}
}
auto sc_minval = rvv<T>::vmv_v_x(std::numeric_limits<T>::max(), vlmax);
auto sc_maxval = rvv<T>::vmv_v_x(std::numeric_limits<T>::lowest(), vlmax);
sc_minval = rvv<T>::vredmin(vec_min, sc_minval, vlmax);
sc_maxval = rvv<T>::vredmax(vec_max, sc_maxval, vlmax);
auto sc_minval = VEC_T::vmv(std::numeric_limits<T>::max(), vlmax);
auto sc_maxval = VEC_T::vmv(std::numeric_limits<T>::lowest(), vlmax);
sc_minval = VEC_T::vredmin(vec_min, sc_minval, vlmax);
sc_maxval = VEC_T::vredmax(vec_max, sc_maxval, vlmax);
val_min = __riscv_vmv_x(sc_minval);
val_max = __riscv_vmv_x(sc_maxval);
@@ -169,8 +120,8 @@ inline int minMaxIdxReadTwice(const uchar* src_data, size_t src_step, int width,
int vl;
for (int j = 0; j < width && (!found_min || !found_max); j += vl)
{
vl = rvv<T>::vsetvl(width - j);
auto vec_src = rvv<T>::vle(src_row + j, vl);
vl = VEC_T::setvl(width - j);
auto vec_src = VEC_T::vload(src_row + j, vl);
if (!found_min)
{
auto bool_minpos = __riscv_vmseq(vec_src, val_min, vl);
@@ -212,15 +163,15 @@ inline int minMaxIdxReadTwice(const uchar* src_data, size_t src_step, int width,
return CV_HAL_ERROR_OK;
}
template<typename T>
template<typename VEC_T, typename BOOL_T, typename IDX_T, typename T = typename VEC_T::ElemType>
inline int minMaxIdxReadOnce(const uchar* src_data, size_t src_step, int width, int height, double* minVal, double* maxVal,
int* minIdx, int* maxIdx, uchar* mask, size_t mask_step)
{
int vlmax = rvv<T>::vsetvlmax();
auto vec_min = rvv<T>::vmv_v_x(std::numeric_limits<T>::max(), vlmax);
auto vec_max = rvv<T>::vmv_v_x(std::numeric_limits<T>::lowest(), vlmax);
auto vec_pos = rvv<T>::vid(vlmax);
auto vec_minpos = rvv<T>::vundefined(), vec_maxpos = rvv<T>::vundefined();
int vlmax = VEC_T::setvlmax();
auto vec_min = VEC_T::vmv(std::numeric_limits<T>::max(), vlmax);
auto vec_max = VEC_T::vmv(std::numeric_limits<T>::lowest(), vlmax);
auto vec_pos = IDX_T::vid(vlmax);
auto vec_minpos = IDX_T::vundefined(), vec_maxpos = IDX_T::vundefined();
T val_min, val_max;
if (mask)
@@ -232,14 +183,14 @@ inline int minMaxIdxReadOnce(const uchar* src_data, size_t src_step, int width,
int vl;
for (int j = 0; j < width; j += vl)
{
vl = rvv<T>::vsetvl(width - j);
auto vec_src = rvv<T>::vle(src_row + j, vl);
auto vec_mask = rvv<T>::vle_mask(mask_row + j, vl);
vl = VEC_T::setvl(width - j);
auto vec_src = VEC_T::vload(src_row + j, vl);
auto vec_mask = BOOL_T::vload(mask_row + j, vl);
auto bool_mask = __riscv_vmsne(vec_mask, 0, vl);
auto bool_zero = __riscv_vmxor(bool_mask, bool_mask, vl);
auto bool_minpos = rvv<T>::vmlt_mu(bool_mask, bool_zero, vec_src, vec_min, vl);
auto bool_maxpos = rvv<T>::vmgt_mu(bool_mask, bool_zero, vec_src, vec_max, vl);
auto bool_minpos = VEC_T::vmlt_mu(bool_mask, bool_zero, vec_src, vec_min, vl);
auto bool_maxpos = VEC_T::vmgt_mu(bool_mask, bool_zero, vec_src, vec_max, vl);
vec_minpos = __riscv_vmerge_tu(vec_minpos, vec_minpos, vec_pos, bool_minpos, vl);
vec_maxpos = __riscv_vmerge_tu(vec_maxpos, vec_maxpos, vec_pos, bool_maxpos, vl);
@@ -257,11 +208,11 @@ inline int minMaxIdxReadOnce(const uchar* src_data, size_t src_step, int width,
int vl;
for (int j = 0; j < width; j += vl)
{
vl = rvv<T>::vsetvl(width - j);
auto vec_src = rvv<T>::vle(src_row + j, vl);
vl = VEC_T::setvl(width - j);
auto vec_src = VEC_T::vload(src_row + j, vl);
auto bool_minpos = rvv<T>::vmlt(vec_src, vec_min, vl);
auto bool_maxpos = rvv<T>::vmgt(vec_src, vec_max, vl);
auto bool_minpos = VEC_T::vmlt(vec_src, vec_min, vl);
auto bool_maxpos = VEC_T::vmgt(vec_src, vec_max, vl);
vec_minpos = __riscv_vmerge_tu(vec_minpos, vec_minpos, vec_pos, bool_minpos, vl);
vec_maxpos = __riscv_vmerge_tu(vec_maxpos, vec_maxpos, vec_pos, bool_maxpos, vl);
@@ -276,9 +227,9 @@ inline int minMaxIdxReadOnce(const uchar* src_data, size_t src_step, int width,
val_max = std::numeric_limits<T>::lowest();
for (int i = 0; i < vlmax; i++)
{
if (val_min > rvv<T>::vmv_x_s(vec_min))
if (val_min > VEC_T::vmv_x(vec_min))
{
val_min = rvv<T>::vmv_x_s(vec_min);
val_min = VEC_T::vmv_x(vec_min);
if (minIdx)
{
minIdx[0] = __riscv_vmv_x(vec_minpos) / width;
@@ -287,9 +238,9 @@ inline int minMaxIdxReadOnce(const uchar* src_data, size_t src_step, int width,
std::swap(minIdx[0], minIdx[1]);
}
}
if (val_max < rvv<T>::vmv_x_s(vec_max))
if (val_max < VEC_T::vmv_x(vec_max))
{
val_max = rvv<T>::vmv_x_s(vec_max);
val_max = VEC_T::vmv_x(vec_max);
if (maxIdx)
{
maxIdx[0] = __riscv_vmv_x(vec_maxpos) / width;
@@ -324,24 +275,24 @@ inline int minMaxIdx(const uchar* src_data, size_t src_step, int width, int heig
switch (depth)
{
case CV_8UC1:
return minMaxIdxReadTwice<uchar>(src_data, src_step, width, height, minVal, maxVal, minIdx, maxIdx, mask, mask_step);
return minMaxIdxReadTwice<RVV_U8M1, RVV_U8M1>(src_data, src_step, width, height, minVal, maxVal, minIdx, maxIdx, mask, mask_step);
case CV_8SC1:
return minMaxIdxReadTwice<schar>(src_data, src_step, width, height, minVal, maxVal, minIdx, maxIdx, mask, mask_step);
return minMaxIdxReadTwice<RVV_I8M1, RVV_U8M1>(src_data, src_step, width, height, minVal, maxVal, minIdx, maxIdx, mask, mask_step);
case CV_16UC1:
return minMaxIdxReadTwice<ushort>(src_data, src_step, width, height, minVal, maxVal, minIdx, maxIdx, mask, mask_step);
return minMaxIdxReadTwice<RVV_U16M1, RVV_U8MF2>(src_data, src_step, width, height, minVal, maxVal, minIdx, maxIdx, mask, mask_step);
case CV_16SC1:
return minMaxIdxReadTwice<short>(src_data, src_step, width, height, minVal, maxVal, minIdx, maxIdx, mask, mask_step);
return minMaxIdxReadTwice<RVV_I16M1, RVV_U8MF2>(src_data, src_step, width, height, minVal, maxVal, minIdx, maxIdx, mask, mask_step);
case CV_32SC1:
return minMaxIdxReadOnce<int>(src_data, src_step, width, height, minVal, maxVal, minIdx, maxIdx, mask, mask_step);
return minMaxIdxReadOnce<RVV_I32M4, RVV_U8M1, RVV_U32M4>(src_data, src_step, width, height, minVal, maxVal, minIdx, maxIdx, mask, mask_step);
case CV_32FC1:
return minMaxIdxReadOnce<float>(src_data, src_step, width, height, minVal, maxVal, minIdx, maxIdx, mask, mask_step);
return minMaxIdxReadOnce<RVV_F32M4, RVV_U8M1, RVV_U32M4>(src_data, src_step, width, height, minVal, maxVal, minIdx, maxIdx, mask, mask_step);
case CV_64FC1:
return minMaxIdxReadOnce<double>(src_data, src_step, width, height, minVal, maxVal, minIdx, maxIdx, mask, mask_step);
return minMaxIdxReadOnce<RVV_F64M4, RVV_U8MF2, RVV_U32M2>(src_data, src_step, width, height, minVal, maxVal, minIdx, maxIdx, mask, mask_step);
}
return CV_HAL_ERROR_NOT_IMPLEMENTED;
}
}}
}}}
#endif
+3 -3
View File
@@ -6,10 +6,10 @@
#include <riscv_vector.h>
namespace cv { namespace cv_hal_rvv {
namespace cv { namespace cv_hal_rvv { namespace norm {
#undef cv_hal_norm
#define cv_hal_norm cv::cv_hal_rvv::norm
#define cv_hal_norm cv::cv_hal_rvv::norm::norm
inline int normInf_8UC1(const uchar* src, size_t src_step, const uchar* mask, size_t mask_step, int width, int height, double* result)
{
@@ -512,6 +512,6 @@ inline int norm(const uchar* src, size_t src_step, const uchar* mask, size_t mas
return CV_HAL_ERROR_NOT_IMPLEMENTED;
}
}}
}}}
#endif
+4 -4
View File
@@ -6,10 +6,10 @@
#include <riscv_vector.h>
namespace cv { namespace cv_hal_rvv {
namespace cv { namespace cv_hal_rvv { namespace norm_diff {
#undef cv_hal_normDiff
#define cv_hal_normDiff cv::cv_hal_rvv::normDiff
#define cv_hal_normDiff cv::cv_hal_rvv::norm_diff::normDiff
inline int normDiffInf_8UC1(const uchar* src1, size_t src1_step, const uchar* src2, size_t src2_step, const uchar* mask, size_t mask_step, int width, int height, double* result)
{
@@ -590,7 +590,7 @@ inline int normDiff(const uchar* src1, size_t src1_step, const uchar* src2, size
if(ret == CV_HAL_ERROR_OK && (norm_type & NORM_RELATIVE))
{
double result_;
ret = cv::cv_hal_rvv::norm(src2, src2_step, mask, mask_step, width, height, type, norm_type & ~NORM_RELATIVE, &result_);
ret = cv::cv_hal_rvv::norm::norm(src2, src2_step, mask, mask_step, width, height, type, norm_type & ~NORM_RELATIVE, &result_);
if(ret == CV_HAL_ERROR_OK)
{
*result /= result_ + DBL_EPSILON;
@@ -600,6 +600,6 @@ inline int normDiff(const uchar* src1, size_t src1_step, const uchar* src2, size
return ret;
}
}}
}}}
#endif
+600
View File
@@ -0,0 +1,600 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#ifndef OPENCV_HAL_RVV_PYRAMIDS_HPP_INCLUDED
#define OPENCV_HAL_RVV_PYRAMIDS_HPP_INCLUDED
#include <riscv_vector.h>
#include "hal_rvv_1p0/types.hpp"
namespace cv { namespace cv_hal_rvv { namespace pyramids {
#undef cv_hal_pyrdown
#define cv_hal_pyrdown cv::cv_hal_rvv::pyramids::pyrDown
#undef cv_hal_pyrup
#define cv_hal_pyrup cv::cv_hal_rvv::pyramids::pyrUp
template<typename T> struct rvv;
template<> struct rvv<uchar>
{
using T = RVV_U8M1;
using WT = RVV_SameLen<int, T>;
using MT = RVV_SameLen<uint, T>;
static inline WT::VecType vcvt_T_WT(T::VecType a, size_t b) { return WT::cast(MT::cast(a, b), b); }
static inline T::VecType vcvt_WT_T(WT::VecType a, int b, size_t c) { return T::cast(MT::cast(__riscv_vsra(__riscv_vadd(a, 1 << (b - 1), c), b, c), c), c); }
static inline WT::VecType down0(WT::VecType vec_src0, WT::VecType vec_src1, WT::VecType vec_src2, WT::VecType vec_src3, WT::VecType vec_src4, size_t vl) {
return __riscv_vadd(__riscv_vadd(__riscv_vadd(vec_src0, vec_src4, vl), __riscv_vadd(vec_src2, vec_src2, vl), vl),
__riscv_vsll(__riscv_vadd(__riscv_vadd(vec_src1, vec_src2, vl), vec_src3, vl), 2, vl), vl);
}
static inline WT::VecType down1(WT::VecType vec_src0, WT::VecType vec_src1, WT::VecType vec_src2, WT::VecType vec_src3, WT::VecType vec_src4, size_t vl) {
return down0(vec_src0, vec_src1, vec_src2, vec_src3, vec_src4, vl);
}
static inline WT::VecType up00(WT::VecType vec_src0, WT::VecType vec_src1, WT::VecType vec_src2, size_t vl) {
return __riscv_vadd(__riscv_vadd(vec_src0, vec_src2, vl), __riscv_vadd(__riscv_vsll(vec_src1, 2, vl), __riscv_vsll(vec_src1, 1, vl), vl), vl);
}
static inline WT::VecType up01(WT::VecType vec_src1, WT::VecType vec_src2, size_t vl) {
return __riscv_vsll(__riscv_vadd(vec_src1, vec_src2, vl), 2, vl);
}
static inline WT::VecType up10(WT::VecType vec_src0, WT::VecType vec_src1, WT::VecType vec_src2, size_t vl) {
return up00(vec_src0, vec_src1, vec_src2, vl);
}
static inline WT::VecType up11(WT::VecType vec_src1, WT::VecType vec_src2, size_t vl) {
return up01(vec_src1, vec_src2, vl);
}
};
template<> struct rvv<short>
{
using T = RVV_I16M2;
using WT = RVV_SameLen<int, T>;
using MT = RVV_SameLen<uint, T>;
static inline WT::VecType vcvt_T_WT(T::VecType a, size_t b) { return WT::cast(a, b); }
static inline T::VecType vcvt_WT_T(WT::VecType a, int b, size_t c) { return T::cast(__riscv_vsra(__riscv_vadd(a, 1 << (b - 1), c), b, c), c); }
static inline WT::VecType down0(WT::VecType vec_src0, WT::VecType vec_src1, WT::VecType vec_src2, WT::VecType vec_src3, WT::VecType vec_src4, size_t vl) {
return __riscv_vadd(__riscv_vadd(__riscv_vadd(vec_src0, vec_src4, vl), __riscv_vadd(vec_src2, vec_src2, vl), vl),
__riscv_vsll(__riscv_vadd(__riscv_vadd(vec_src1, vec_src2, vl), vec_src3, vl), 2, vl), vl);
}
static inline WT::VecType down1(WT::VecType vec_src0, WT::VecType vec_src1, WT::VecType vec_src2, WT::VecType vec_src3, WT::VecType vec_src4, size_t vl) {
return down0(vec_src0, vec_src1, vec_src2, vec_src3, vec_src4, vl);
}
static inline WT::VecType up00(WT::VecType vec_src0, WT::VecType vec_src1, WT::VecType vec_src2, size_t vl) {
return __riscv_vadd(__riscv_vadd(vec_src0, vec_src2, vl), __riscv_vadd(__riscv_vsll(vec_src1, 2, vl), __riscv_vsll(vec_src1, 1, vl), vl), vl);
}
static inline WT::VecType up01(WT::VecType vec_src1, WT::VecType vec_src2, size_t vl) {
return __riscv_vsll(__riscv_vadd(vec_src1, vec_src2, vl), 2, vl);
}
static inline WT::VecType up10(WT::VecType vec_src0, WT::VecType vec_src1, WT::VecType vec_src2, size_t vl) {
return up00(vec_src0, vec_src1, vec_src2, vl);
}
static inline WT::VecType up11(WT::VecType vec_src1, WT::VecType vec_src2, size_t vl) {
return up01(vec_src1, vec_src2, vl);
}
};
template<> struct rvv<float>
{
using T = RVV_F32M4;
using WT = RVV_SameLen<float, T>;
using MT = RVV_SameLen<uint, T>;
static inline WT::VecType vcvt_T_WT(T::VecType a, size_t b) { return WT::cast(a, b); }
static inline T::VecType vcvt_WT_T(WT::VecType a, [[maybe_unused]] int b, size_t c) { return T::cast(a, c); }
static inline WT::VecType down0(WT::VecType vec_src0, WT::VecType vec_src1, WT::VecType vec_src2, WT::VecType vec_src3, WT::VecType vec_src4, size_t vl) {
return __riscv_vfmadd(vec_src2, 6, __riscv_vfmadd(__riscv_vfadd(vec_src1, vec_src3, vl), 4, __riscv_vfadd(vec_src0, vec_src4, vl), vl), vl);
}
static inline WT::VecType down1(WT::VecType vec_src0, WT::VecType vec_src1, WT::VecType vec_src2, WT::VecType vec_src3, WT::VecType vec_src4, size_t vl) {
return __riscv_vfmul(down0(vec_src0, vec_src1, vec_src2, vec_src3, vec_src4, vl), 1.f / 256.f, vl);
}
static inline WT::VecType up00(WT::VecType vec_src0, WT::VecType vec_src1, WT::VecType vec_src2, size_t vl) {
return __riscv_vfadd(__riscv_vfmadd(vec_src1, 6, vec_src0, vl), vec_src2, vl);
}
static inline WT::VecType up01(WT::VecType vec_src1, WT::VecType vec_src2, size_t vl) {
return __riscv_vfmul(__riscv_vfadd(vec_src1, vec_src2, vl), 4, vl);
}
static inline WT::VecType up10(WT::VecType vec_src0, WT::VecType vec_src1, WT::VecType vec_src2, size_t vl) {
return __riscv_vfmul(__riscv_vfadd(__riscv_vfmadd(vec_src1, 6, vec_src0, vl), vec_src2, vl), 1.f / 64.f, vl);
}
static inline WT::VecType up11(WT::VecType vec_src1, WT::VecType vec_src2, size_t vl) {
return __riscv_vfmul(__riscv_vfadd(vec_src1, vec_src2, vl), 1.f / 16.f, vl);
}
};
template <typename RVV>
struct pyrDownVec0
{
using T = typename RVV::T::ElemType;
using WT = typename RVV::WT::ElemType;
void operator()(const T* src, WT* row, const uint* tabM, int start, int end)
{
int vl;
switch (start)
{
case 1:
for( int x = start; x < end; x += vl )
{
vl = RVV::WT::setvl(end - x);
auto vec_src0 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + x * 2 - 2, 2 * sizeof(T), vl), vl);
auto vec_src1 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + x * 2 - 1, 2 * sizeof(T), vl), vl);
auto vec_src2 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + x * 2, 2 * sizeof(T), vl), vl);
auto vec_src3 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + x * 2 + 1, 2 * sizeof(T), vl), vl);
auto vec_src4 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + x * 2 + 2, 2 * sizeof(T), vl), vl);
__riscv_vse32(row + x, RVV::down0(vec_src0, vec_src1, vec_src2, vec_src3, vec_src4, vl), vl);
}
break;
case 2:
for( int x = start / 2; x < end / 2; x += vl )
{
vl = RVV::WT::setvl(end / 2 - x);
auto vec_src0 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2 - 2) * 2, 4 * sizeof(T), vl), vl);
auto vec_src1 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2 - 1) * 2, 4 * sizeof(T), vl), vl);
auto vec_src2 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2) * 2, 4 * sizeof(T), vl), vl);
auto vec_src3 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2 + 1) * 2, 4 * sizeof(T), vl), vl);
auto vec_src4 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2 + 2) * 2, 4 * sizeof(T), vl), vl);
__riscv_vsse32(row + x * 2, 2 * sizeof(WT), RVV::down0(vec_src0, vec_src1, vec_src2, vec_src3, vec_src4, vl), vl);
vec_src0 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2 - 2) * 2 + 1, 4 * sizeof(T), vl), vl);
vec_src1 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2 - 1) * 2 + 1, 4 * sizeof(T), vl), vl);
vec_src2 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2) * 2 + 1, 4 * sizeof(T), vl), vl);
vec_src3 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2 + 1) * 2 + 1, 4 * sizeof(T), vl), vl);
vec_src4 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2 + 2) * 2 + 1, 4 * sizeof(T), vl), vl);
__riscv_vsse32(row + x * 2 + 1, 2 * sizeof(WT), RVV::down0(vec_src0, vec_src1, vec_src2, vec_src3, vec_src4, vl), vl);
}
break;
case 3:
for( int x = start / 3; x < end / 3; x += vl )
{
vl = RVV::WT::setvl(end / 3 - x);
auto vec_src0 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2 - 2) * 3, 6 * sizeof(T), vl), vl);
auto vec_src1 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2 - 1) * 3, 6 * sizeof(T), vl), vl);
auto vec_src2 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2) * 3, 6 * sizeof(T), vl), vl);
auto vec_src3 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2 + 1) * 3, 6 * sizeof(T), vl), vl);
auto vec_src4 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2 + 2) * 3, 6 * sizeof(T), vl), vl);
__riscv_vsse32(row + x * 3, 3 * sizeof(WT), RVV::down0(vec_src0, vec_src1, vec_src2, vec_src3, vec_src4, vl), vl);
vec_src0 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2 - 2) * 3 + 1, 6 * sizeof(T), vl), vl);
vec_src1 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2 - 1) * 3 + 1, 6 * sizeof(T), vl), vl);
vec_src2 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2) * 3 + 1, 6 * sizeof(T), vl), vl);
vec_src3 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2 + 1) * 3 + 1, 6 * sizeof(T), vl), vl);
vec_src4 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2 + 2) * 3 + 1, 6 * sizeof(T), vl), vl);
__riscv_vsse32(row + x * 3 + 1, 3 * sizeof(WT), RVV::down0(vec_src0, vec_src1, vec_src2, vec_src3, vec_src4, vl), vl);
vec_src0 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2 - 2) * 3 + 2, 6 * sizeof(T), vl), vl);
vec_src1 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2 - 1) * 3 + 2, 6 * sizeof(T), vl), vl);
vec_src2 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2) * 3 + 2, 6 * sizeof(T), vl), vl);
vec_src3 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2 + 1) * 3 + 2, 6 * sizeof(T), vl), vl);
vec_src4 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2 + 2) * 3 + 2, 6 * sizeof(T), vl), vl);
__riscv_vsse32(row + x * 3 + 2, 3 * sizeof(WT), RVV::down0(vec_src0, vec_src1, vec_src2, vec_src3, vec_src4, vl), vl);
}
break;
case 4:
for( int x = start / 4; x < end / 4; x += vl )
{
vl = RVV::WT::setvl(end / 4 - x);
auto vec_src0 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2 - 2) * 4, 8 * sizeof(T), vl), vl);
auto vec_src1 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2 - 1) * 4, 8 * sizeof(T), vl), vl);
auto vec_src2 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2) * 4, 8 * sizeof(T), vl), vl);
auto vec_src3 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2 + 1) * 4, 8 * sizeof(T), vl), vl);
auto vec_src4 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2 + 2) * 4, 8 * sizeof(T), vl), vl);
__riscv_vsse32(row + x * 4, 4 * sizeof(WT), RVV::down0(vec_src0, vec_src1, vec_src2, vec_src3, vec_src4, vl), vl);
vec_src0 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2 - 2) * 4 + 1, 8 * sizeof(T), vl), vl);
vec_src1 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2 - 1) * 4 + 1, 8 * sizeof(T), vl), vl);
vec_src2 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2) * 4 + 1, 8 * sizeof(T), vl), vl);
vec_src3 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2 + 1) * 4 + 1, 8 * sizeof(T), vl), vl);
vec_src4 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2 + 2) * 4 + 1, 8 * sizeof(T), vl), vl);
__riscv_vsse32(row + x * 4 + 1, 4 * sizeof(WT), RVV::down0(vec_src0, vec_src1, vec_src2, vec_src3, vec_src4, vl), vl);
vec_src0 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2 - 2) * 4 + 2, 8 * sizeof(T), vl), vl);
vec_src1 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2 - 1) * 4 + 2, 8 * sizeof(T), vl), vl);
vec_src2 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2) * 4 + 2, 8 * sizeof(T), vl), vl);
vec_src3 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2 + 1) * 4 + 2, 8 * sizeof(T), vl), vl);
vec_src4 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2 + 2) * 4 + 2, 8 * sizeof(T), vl), vl);
__riscv_vsse32(row + x * 4 + 2, 4 * sizeof(WT), RVV::down0(vec_src0, vec_src1, vec_src2, vec_src3, vec_src4, vl), vl);
vec_src0 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2 - 2) * 4 + 3, 8 * sizeof(T), vl), vl);
vec_src1 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2 - 1) * 4 + 3, 8 * sizeof(T), vl), vl);
vec_src2 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2) * 4 + 3, 8 * sizeof(T), vl), vl);
vec_src3 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2 + 1) * 4 + 3, 8 * sizeof(T), vl), vl);
vec_src4 = RVV::vcvt_T_WT(RVV::T::vload_stride(src + (x * 2 + 2) * 4 + 3, 8 * sizeof(T), vl), vl);
__riscv_vsse32(row + x * 4 + 3, 4 * sizeof(WT), RVV::down0(vec_src0, vec_src1, vec_src2, vec_src3, vec_src4, vl), vl);
}
break;
default:
for( int x = start; x < end; x += vl )
{
vl = RVV::WT::setvl(end - x);
auto vec_tabM = RVV::MT::vload(tabM + x, vl);
vec_tabM = __riscv_vmul(__riscv_vsub(vec_tabM, start * 2, vl), sizeof(T), vl);
auto vec_src0 = RVV::vcvt_T_WT(__riscv_vloxei32(src, vec_tabM, vl), vl);
vec_tabM = __riscv_vadd(vec_tabM, start * sizeof(T), vl);
auto vec_src1 = RVV::vcvt_T_WT(__riscv_vloxei32(src, vec_tabM, vl), vl);
vec_tabM = __riscv_vadd(vec_tabM, start * sizeof(T), vl);
auto vec_src2 = RVV::vcvt_T_WT(__riscv_vloxei32(src, vec_tabM, vl), vl);
vec_tabM = __riscv_vadd(vec_tabM, start * sizeof(T), vl);
auto vec_src3 = RVV::vcvt_T_WT(__riscv_vloxei32(src, vec_tabM, vl), vl);
vec_tabM = __riscv_vadd(vec_tabM, start * sizeof(T), vl);
auto vec_src4 = RVV::vcvt_T_WT(__riscv_vloxei32(src, vec_tabM, vl), vl);
__riscv_vse32(row + x, RVV::down0(vec_src0, vec_src1, vec_src2, vec_src3, vec_src4, vl), vl);
}
}
}
};
template <typename RVV>
struct pyrDownVec1
{
using T = typename RVV::T::ElemType;
using WT = typename RVV::WT::ElemType;
void operator()(WT* row0, WT* row1, WT* row2, WT* row3, WT* row4, T* dst, int end)
{
int vl;
for( int x = 0 ; x < end; x += vl )
{
vl = RVV::WT::setvl(end - x);
auto vec_src0 = RVV::WT::vload(row0 + x, vl);
auto vec_src1 = RVV::WT::vload(row1 + x, vl);
auto vec_src2 = RVV::WT::vload(row2 + x, vl);
auto vec_src3 = RVV::WT::vload(row3 + x, vl);
auto vec_src4 = RVV::WT::vload(row4 + x, vl);
RVV::T::vstore(dst + x, RVV::vcvt_WT_T(RVV::down1(vec_src0, vec_src1, vec_src2, vec_src3, vec_src4, vl), 8, vl), vl);
}
}
};
template <typename RVV>
struct pyrUpVec0
{
using T = typename RVV::T::ElemType;
using WT = typename RVV::WT::ElemType;
void operator()(const T* src, WT* row, const uint* dtab, int start, int end)
{
int vl;
for( int x = start; x < end; x += vl )
{
vl = RVV::WT::setvl(end - x);
auto vec_src0 = RVV::vcvt_T_WT(RVV::T::vload(src + x - start, vl), vl);
auto vec_src1 = RVV::vcvt_T_WT(RVV::T::vload(src + x, vl), vl);
auto vec_src2 = RVV::vcvt_T_WT(RVV::T::vload(src + x + start, vl), vl);
auto vec_dtab = RVV::MT::vload(dtab + x, vl);
vec_dtab = __riscv_vmul(vec_dtab, sizeof(WT), vl);
__riscv_vsoxei32(row, vec_dtab, RVV::up00(vec_src0, vec_src1, vec_src2, vl), vl);
__riscv_vsoxei32(row, __riscv_vadd(vec_dtab, start * sizeof(WT), vl), RVV::up01(vec_src1, vec_src2, vl), vl);
}
}
};
template <typename RVV>
struct pyrUpVec1
{
using T = typename RVV::T::ElemType;
using WT = typename RVV::WT::ElemType;
void operator()(WT* row0, WT* row1, WT* row2, T* dst0, T* dst1, int end)
{
int vl;
if (dst0 != dst1)
{
for( int x = 0 ; x < end; x += vl )
{
vl = RVV::WT::setvl(end - x);
auto vec_src0 = RVV::WT::vload(row0 + x, vl);
auto vec_src1 = RVV::WT::vload(row1 + x, vl);
auto vec_src2 = RVV::WT::vload(row2 + x, vl);
RVV::T::vstore(dst0 + x, RVV::vcvt_WT_T(RVV::up10(vec_src0, vec_src1, vec_src2, vl), 6, vl), vl);
RVV::T::vstore(dst1 + x, RVV::vcvt_WT_T(RVV::up11(vec_src1, vec_src2, vl), 6, vl), vl);
}
}
else
{
for( int x = 0 ; x < end; x += vl )
{
vl = RVV::WT::setvl(end - x);
auto vec_src0 = RVV::WT::vload(row0 + x, vl);
auto vec_src1 = RVV::WT::vload(row1 + x, vl);
auto vec_src2 = RVV::WT::vload(row2 + x, vl);
RVV::T::vstore(dst0 + x, RVV::vcvt_WT_T(RVV::up10(vec_src0, vec_src1, vec_src2, vl), 6, vl), vl);
}
}
}
};
template<typename RVV>
struct PyrDownInvoker : ParallelLoopBody
{
PyrDownInvoker(const uchar* _src_data, size_t _src_step, int _src_width, int _src_height, uchar* _dst_data, size_t _dst_step, int _dst_width, int _dst_height, int _cn, int _borderType, int* _tabR, int* _tabM, int* _tabL)
{
src_data = _src_data;
src_step = _src_step;
src_width = _src_width;
src_height = _src_height;
dst_data = _dst_data;
dst_step = _dst_step;
dst_width = _dst_width;
dst_height = _dst_height;
cn = _cn;
borderType = _borderType;
tabR = _tabR;
tabM = _tabM;
tabL = _tabL;
}
void operator()(const Range& range) const CV_OVERRIDE;
const uchar* src_data;
size_t src_step;
int src_width;
int src_height;
uchar* dst_data;
size_t dst_step;
int dst_width;
int dst_height;
int cn;
int borderType;
int* tabR;
int* tabM;
int* tabL;
};
static inline int borderInterpolate( int p, int len, int borderType )
{
if( (unsigned)p < (unsigned)len )
;
else if( borderType == BORDER_REPLICATE )
p = p < 0 ? 0 : len - 1;
else if( borderType == BORDER_REFLECT || borderType == BORDER_REFLECT_101 )
{
int delta = borderType == BORDER_REFLECT_101;
if( len == 1 )
return 0;
do
{
if( p < 0 )
p = -p - 1 + delta;
else
p = len - 1 - (p - len) - delta;
}
while( (unsigned)p >= (unsigned)len );
}
else if( borderType == BORDER_WRAP )
{
if( p < 0 )
p -= ((p-len+1)/len)*len;
if( p >= len )
p %= len;
}
else if( borderType == BORDER_CONSTANT )
p = -1;
return p;
}
// the algorithm is copied from imgproc/src/pyramids.cpp,
// in the function template void cv::pyrDown_
template <typename RVV>
inline int pyrDown(const uchar* src_data, size_t src_step, int src_width, int src_height, uchar* dst_data, size_t dst_step, int dst_width, int dst_height, int cn, int borderType)
{
const int PD_SZ = 5;
std::vector<int> _tabM(dst_width * cn), _tabL(cn * (PD_SZ + 2)), _tabR(cn * (PD_SZ + 2));
int *tabM = _tabM.data(), *tabL = _tabL.data(), *tabR = _tabR.data();
if( src_width <= 0 || src_height <= 0 ||
std::abs(dst_width*2 - src_width) > 2 ||
std::abs(dst_height*2 - src_height) > 2 )
{
return CV_HAL_ERROR_NOT_IMPLEMENTED;
}
int width0 = std::min((src_width-PD_SZ/2-1)/2 + 1, dst_width);
for (int x = 0; x <= PD_SZ+1; x++)
{
int sx0 = borderInterpolate(x - PD_SZ/2, src_width, borderType)*cn;
int sx1 = borderInterpolate(x + width0*2 - PD_SZ/2, src_width, borderType)*cn;
for (int k = 0; k < cn; k++)
{
tabL[x*cn + k] = sx0 + k;
tabR[x*cn + k] = sx1 + k;
}
}
for (int x = 0; x < dst_width*cn; x++)
tabM[x] = (x/cn)*2*cn + x % cn;
cv::parallel_for_(Range(0,dst_height), PyrDownInvoker<RVV>(src_data, src_step, src_width, src_height, dst_data, dst_step, dst_width, dst_height, cn, borderType, tabR, tabM, tabL), cv::getNumThreads());
return CV_HAL_ERROR_OK;
}
template <typename RVV>
void PyrDownInvoker<RVV>::operator()(const Range& range) const
{
using T = typename RVV::T::ElemType;
using WT = typename RVV::WT::ElemType;
const int PD_SZ = 5;
int bufstep = (dst_width*cn + 15) & -16;
std::vector<WT> _buf(bufstep*PD_SZ + 16);
WT* buf = (WT*)(((size_t)_buf.data() + 15) & -16);
WT* rows[PD_SZ];
int sy0 = -PD_SZ/2, sy = range.start * 2 + sy0, width0 = std::min((src_width-PD_SZ/2-1)/2 + 1, dst_width);
int _dst_width = dst_width * cn;
width0 *= cn;
for (int y = range.start; y < range.end; y++)
{
T* dst = reinterpret_cast<T*>(dst_data + dst_step * y);
WT *row0, *row1, *row2, *row3, *row4;
// fill the ring buffer (horizontal convolution and decimation)
int sy_limit = y*2 + 2;
for( ; sy <= sy_limit; sy++ )
{
WT* row = buf + ((sy - sy0) % PD_SZ)*bufstep;
int _sy = borderInterpolate(sy, src_height, borderType);
const T* src = reinterpret_cast<const T*>(src_data + src_step * _sy);
do {
int x = 0;
for( ; x < cn; x++ )
{
row[x] = src[tabL[x+cn*2]]*6 + (src[tabL[x+cn]] + src[tabL[x+cn*3]])*4 +
src[tabL[x]] + src[tabL[x+cn*4]];
}
if( x == _dst_width )
break;
pyrDownVec0<RVV>()(src, row, reinterpret_cast<const uint*>(tabM), cn, width0);
x = width0;
// tabR
for (int x_ = 0; x < _dst_width; x++, x_++)
{
row[x] = src[tabR[x_+cn*2]]*6 + (src[tabR[x_+cn]] + src[tabR[x_+cn*3]])*4 +
src[tabR[x_]] + src[tabR[x_+cn*4]];
}
} while (0);
}
// do vertical convolution and decimation and write the result to the destination image
for (int k = 0; k < PD_SZ; k++)
rows[k] = buf + ((y*2 - PD_SZ/2 + k - sy0) % PD_SZ)*bufstep;
row0 = rows[0]; row1 = rows[1]; row2 = rows[2]; row3 = rows[3]; row4 = rows[4];
pyrDownVec1<RVV>()(row0, row1, row2, row3, row4, dst, _dst_width);
}
}
// the algorithm is copied from imgproc/src/pyramids.cpp,
// in the function template void cv::pyrUp_
template <typename RVV>
inline int pyrUp(const uchar* src_data, size_t src_step, int src_width, int src_height, uchar* dst_data, size_t dst_step, int dst_width, int dst_height, int cn)
{
using T = typename RVV::T::ElemType;
using WT = typename RVV::WT::ElemType;
const int PU_SZ = 3;
int bufstep = ((dst_width+1)*cn + 15) & -16;
std::vector<WT> _buf(bufstep*PU_SZ + 16);
WT* buf = (WT*)(((size_t)_buf.data() + 15) & -16);
std::vector<int> _dtab(src_width*cn);
int* dtab = _dtab.data();
WT* rows[PU_SZ];
if( std::abs(dst_width - src_width*2) != dst_width % 2 ||
std::abs(dst_height - src_height*2) != dst_height % 2)
{
return CV_HAL_ERROR_NOT_IMPLEMENTED;
}
int k, x, sy0 = -PU_SZ/2, sy = sy0;
src_width *= cn;
dst_width *= cn;
for( x = 0; x < src_width; x++ )
dtab[x] = (x/cn)*2*cn + x % cn;
for( int y = 0; y < src_height; y++ )
{
T* dst0 = reinterpret_cast<T*>(dst_data + dst_step * (y*2));
T* dst1 = reinterpret_cast<T*>(dst_data + dst_step * (std::min(y*2+1, dst_height-1)));
WT *row0, *row1, *row2;
// fill the ring buffer (horizontal convolution and decimation)
for( ; sy <= y + 1; sy++ )
{
WT* row = buf + ((sy - sy0) % PU_SZ)*bufstep;
int _sy = borderInterpolate(sy*2, src_height*2, (int)BORDER_REFLECT_101)/2;
const T* src = reinterpret_cast<const T*>(src_data + src_step * _sy);
if( src_width == cn )
{
for( x = 0; x < cn; x++ )
row[x] = row[x + cn] = src[x]*8;
continue;
}
for( x = 0; x < cn; x++ )
{
int dx = dtab[x];
WT t0 = src[x]*6 + src[x + cn]*2;
WT t1 = (src[x] + src[x + cn])*4;
row[dx] = t0; row[dx + cn] = t1;
dx = dtab[src_width - cn + x];
int sx = src_width - cn + x;
t0 = src[sx - cn] + src[sx]*7;
t1 = src[sx]*8;
row[dx] = t0; row[dx + cn] = t1;
if (dst_width > src_width*2)
{
row[(dst_width-1) * cn + x] = row[dx + cn];
}
}
pyrUpVec0<RVV>()(src, row, reinterpret_cast<const uint*>(dtab), cn, src_width - cn);
}
// do vertical convolution and decimation and write the result to the destination image
for( k = 0; k < PU_SZ; k++ )
rows[k] = buf + ((y - PU_SZ/2 + k - sy0) % PU_SZ)*bufstep;
row0 = rows[0]; row1 = rows[1]; row2 = rows[2];
pyrUpVec1<RVV>()(row0, row1, row2, dst0, dst1, dst_width);
}
if (dst_height > src_height*2)
{
T* dst0 = reinterpret_cast<T*>(dst_data + dst_step * (src_height*2-2));
T* dst2 = reinterpret_cast<T*>(dst_data + dst_step * (src_height*2));
for(x = 0; x < dst_width ; x++ )
{
dst2[x] = dst0[x];
}
}
return CV_HAL_ERROR_OK;
}
inline int pyrDown(const uchar* src_data, size_t src_step, int src_width, int src_height, uchar* dst_data, size_t dst_step, int dst_width, int dst_height, int depth, int cn, int border_type)
{
if (border_type == BORDER_CONSTANT || (depth == CV_32F && cn == 1))
return CV_HAL_ERROR_NOT_IMPLEMENTED;
switch (depth)
{
case CV_8U:
return pyrDown<rvv<uchar>>(src_data, src_step, src_width, src_height, dst_data, dst_step, dst_width, dst_height, cn, border_type);
case CV_16S:
return pyrDown<rvv<short>>(src_data, src_step, src_width, src_height, dst_data, dst_step, dst_width, dst_height, cn, border_type);
case CV_32F:
return pyrDown<rvv<float>>(src_data, src_step, src_width, src_height, dst_data, dst_step, dst_width, dst_height, cn, border_type);
}
return CV_HAL_ERROR_NOT_IMPLEMENTED;
}
inline int pyrUp(const uchar* src_data, size_t src_step, int src_width, int src_height, uchar* dst_data, size_t dst_step, int dst_width, int dst_height, int depth, int cn, int border_type)
{
if (border_type != BORDER_DEFAULT)
return CV_HAL_ERROR_NOT_IMPLEMENTED;
switch (depth)
{
case CV_8U:
return pyrUp<rvv<uchar>>(src_data, src_step, src_width, src_height, dst_data, dst_step, dst_width, dst_height, cn);
case CV_16S:
return pyrUp<rvv<short>>(src_data, src_step, src_width, src_height, dst_data, dst_step, dst_width, dst_height, cn);
case CV_32F:
return pyrUp<rvv<float>>(src_data, src_step, src_width, src_height, dst_data, dst_step, dst_width, dst_height, cn);
}
return CV_HAL_ERROR_NOT_IMPLEMENTED;
}
}}}
#endif
+173
View File
@@ -0,0 +1,173 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#ifndef OPENCV_HAL_RVV_QR_HPP_INCLUDED
#define OPENCV_HAL_RVV_QR_HPP_INCLUDED
#include <cfloat>
#include <cmath>
#include <typeinfo>
#include <vector>
#include <riscv_vector.h>
#include "hal_rvv_1p0/types.hpp"
namespace cv { namespace cv_hal_rvv { namespace qr {
#undef cv_hal_QR32f
#define cv_hal_QR32f cv::cv_hal_rvv::qr::QR<cv::cv_hal_rvv::RVV_F32M4>
#undef cv_hal_QR64f
#define cv_hal_QR64f cv::cv_hal_rvv::qr::QR<cv::cv_hal_rvv::RVV_F64M4>
// the algorithm is copied from core/src/matrix_decomp.cpp,
// in the function template static int cv::QRImpl
template<typename RVV_T, typename T = typename RVV_T::ElemType>
inline int QR(T* src1, size_t src1_step, int m, int n, int k, T* src2, size_t src2_step, T* dst, int* info)
{
T eps;
if (typeid(T) == typeid(float))
eps = FLT_EPSILON*10;
else if (typeid(T) == typeid(double))
eps = DBL_EPSILON*400;
else
return CV_HAL_ERROR_NOT_IMPLEMENTED;
src1_step /= sizeof(T);
src2_step /= sizeof(T);
size_t buf_size = m ? m + n : dst != NULL;
std::vector<T> buffer(buf_size);
T* val = buffer.data();
if (dst == NULL)
dst = val + m;
int vlmax = RVV_T::setvlmax(), vl;
for (int l = 0; l < n; l++)
{
//generate val
int vlSize = m - l;
auto vec_sum = RVV_T::vmv(0, vlmax);
for (int i = 0; i < vlSize; i += vl)
{
vl = RVV_T::setvl(vlSize - i);
auto vec_src = RVV_T::vload_stride(src1 + (l + i) * src1_step + l, sizeof(T) * src1_step, vl);
RVV_T::vstore(val + i, vec_src, vl);
vec_sum = __riscv_vfmacc_tu(vec_sum, vec_src, vec_src, vl);
}
T vlNorm = __riscv_vfmv_f(__riscv_vfredosum(vec_sum, RVV_BaseType<RVV_T>::vmv_s(0, vlmax), vlmax));
T tmpV = val[0];
val[0] = val[0] + (val[0] >= 0 ? 1 : -1) * std::sqrt(vlNorm);
vlNorm = std::sqrt(vlNorm + val[0] * val[0] - tmpV*tmpV);
for (int i = 0; i < vlSize; i += vl)
{
vl = RVV_T::setvl(vlSize - i);
auto vec_src = RVV_T::vload(val + i, vl);
vec_src = __riscv_vfdiv(vec_src, vlNorm, vl);
RVV_T::vstore(val + i, vec_src, vl);
}
//multiply A_l*val
for (int j = l; j < n; j++)
{
vec_sum = RVV_T::vmv(0, vlmax);
for (int i = l; i < m; i += vl)
{
vl = RVV_T::setvl(m - i);
auto vec_src1 = RVV_T::vload(val + i - l, vl);
auto vec_src2 = RVV_T::vload_stride(src1 + i * src1_step + j, sizeof(T) * src1_step, vl);
vec_sum = __riscv_vfmacc_tu(vec_sum, vec_src1, vec_src2, vl);
}
T v_lA = 2 * __riscv_vfmv_f(__riscv_vfredosum(vec_sum, RVV_BaseType<RVV_T>::vmv_s(0, vlmax), vlmax));
for (int i = l; i < m; i += vl)
{
vl = RVV_T::setvl(m - i);
auto vec_src1 = RVV_T::vload(val + i - l, vl);
auto vec_src2 = RVV_T::vload_stride(src1 + i * src1_step + j, sizeof(T) * src1_step, vl);
vec_src2 = __riscv_vfnmsac(vec_src2, v_lA, vec_src1, vl);
RVV_T::vstore_stride(src1 + i * src1_step + j, sizeof(T) * src1_step, vec_src2, vl);
}
}
//save val and factors
dst[l] = val[0] * val[0];
for (int i = 1; i < vlSize; i += vl)
{
vl = RVV_T::setvl(vlSize - i);
auto vec_src = RVV_T::vload(val + i, vl);
vec_src = __riscv_vfdiv(vec_src, val[0], vl);
RVV_T::vstore_stride(src1 + (l + i) * src1_step + l, sizeof(T) * src1_step, vec_src, vl);
}
}
if (src2)
{
//generate new rhs
for (int l = 0; l < n; l++)
{
//unpack val
val[0] = (T)1;
for (int j = 1; j < m - l; j += vl)
{
vl = RVV_T::setvl(m - l - j);
auto vec_src = RVV_T::vload_stride(src1 + (j + l) * src1_step + l, sizeof(T) * src1_step, vl);
RVV_T::vstore(val + j, vec_src, vl);
}
//h_l*x
for (int j = 0; j < k; j++)
{
auto vec_sum = RVV_T::vmv(0, vlmax);
for (int i = l; i < m; i += vl)
{
vl = RVV_T::setvl(m - i);
auto vec_src1 = RVV_T::vload(val + i - l, vl);
auto vec_src2 = RVV_T::vload_stride(src2 + i * src2_step + j, sizeof(T) * src2_step, vl);
vec_sum = __riscv_vfmacc_tu(vec_sum, vec_src1, vec_src2, vl);
}
T v_lB = 2 * dst[l] * __riscv_vfmv_f(__riscv_vfredosum(vec_sum, RVV_BaseType<RVV_T>::vmv_s(0, vlmax), vlmax));
for (int i = l; i < m; i += vl)
{
vl = RVV_T::setvl(m - i);
auto vec_src1 = RVV_T::vload(val + i - l, vl);
auto vec_src2 = RVV_T::vload_stride(src2 + i * src2_step + j, sizeof(T) * src2_step, vl);
vec_src2 = __riscv_vfnmsac(vec_src2, v_lB, vec_src1, vl);
RVV_T::vstore_stride(src2 + i * src2_step + j, sizeof(T) * src2_step, vec_src2, vl);
}
}
}
//do back substitution
for (int i = n - 1; i >= 0; i--)
{
for (int j = n - 1; j > i; j--)
{
for (int p = 0; p < k; p += vl)
{
vl = RVV_T::setvl(k - p);
auto vec_src1 = RVV_T::vload(src2 + i * src2_step + p, vl);
auto vec_src2 = RVV_T::vload(src2 + j * src2_step + p, vl);
vec_src1 = __riscv_vfnmsac(vec_src1, src1[i*src1_step + j], vec_src2, vl);
RVV_T::vstore(src2 + i * src2_step + p, vec_src1, vl);
}
}
if (std::abs(src1[i*src1_step + i]) < eps)
{
*info = 0;
return CV_HAL_ERROR_OK;
}
for (int p = 0; p < k; p += vl)
{
vl = RVV_T::setvl(k - p);
auto vec_src = RVV_T::vload(src2 + i * src2_step + p, vl);
vec_src = __riscv_vfdiv(vec_src, src1[i*src1_step + i], vl);
RVV_T::vstore(src2 + i * src2_step + p, vec_src, vl);
}
}
}
*info = 1;
return CV_HAL_ERROR_OK;
}
}}}
#endif
+268
View File
@@ -0,0 +1,268 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#ifndef OPENCV_HAL_RVV_SVD_HPP_INCLUDED
#define OPENCV_HAL_RVV_SVD_HPP_INCLUDED
#include <cfloat>
#include <cmath>
#include <typeinfo>
#include <vector>
#include <riscv_vector.h>
#include "hal_rvv_1p0/types.hpp"
namespace cv { namespace cv_hal_rvv { namespace svd {
#undef cv_hal_SVD32f
#define cv_hal_SVD32f cv::cv_hal_rvv::svd::SVD<cv::cv_hal_rvv::RVV_F32M4>
#undef cv_hal_SVD64f
#define cv_hal_SVD64f cv::cv_hal_rvv::svd::SVD<cv::cv_hal_rvv::RVV_F64M4>
// the algorithm is copied from core/src/lapack.cpp,
// in the function template static void cv::JacobiSVDImpl_
template<typename RVV_T, typename T = typename RVV_T::ElemType>
inline int SVD(T* src, size_t src_step, T* w, T*, size_t, T* vt, size_t vt_step, int m, int n, int flags)
{
T minval, eps;
if( typeid(T) == typeid(float) )
{
minval = FLT_MIN;
eps = FLT_EPSILON*2;
}
else if( typeid(T) == typeid(double) )
{
minval = DBL_MIN;
eps = DBL_EPSILON*10;
}
else
return CV_HAL_ERROR_NOT_IMPLEMENTED;
int n1;
if( flags == CV_HAL_SVD_NO_UV )
n1 = 0;
else if( flags == (CV_HAL_SVD_SHORT_UV | CV_HAL_SVD_MODIFY_A) )
n1 = n;
else if( flags == (CV_HAL_SVD_FULL_UV | CV_HAL_SVD_MODIFY_A) )
n1 = m;
else
return CV_HAL_ERROR_NOT_IMPLEMENTED;
std::vector<double> Wbuf(n);
double* W = Wbuf.data();
int i, j, k, iter, max_iter = std::max(m, 30);
T c, s;
double sd;
src_step /= sizeof(src[0]);
vt_step /= sizeof(vt[0]);
int vlmax = RVV_T::setvlmax(), vl;
for( i = 0; i < n; i++ )
{
for( k = 0, sd = 0; k < m; k++ )
{
T t = src[i*src_step + k];
sd += (double)t*t;
}
W[i] = sd;
if( vt )
{
for( k = 0; k < n; k++ )
vt[i*vt_step + k] = 0;
vt[i*vt_step + i] = 1;
}
}
for( iter = 0; iter < max_iter; iter++ )
{
bool changed = false;
for( i = 0; i < n-1; i++ )
for( j = i+1; j < n; j++ )
{
T *Ai = src + i*src_step, *Aj = src + j*src_step;
double a = W[i], p = 0, b = W[j];
auto vec_sum1 = RVV_T::vmv(0, vlmax);
for( k = 0; k < m; k += vl )
{
vl = RVV_T::setvl(m - k);
auto vec_src1 = RVV_T::vload(Ai + k, vl);
auto vec_src2 = RVV_T::vload(Aj + k, vl);
vec_sum1 = __riscv_vfmacc_tu(vec_sum1, vec_src1, vec_src2, vl);
}
p = __riscv_vfmv_f(__riscv_vfredosum(vec_sum1, RVV_BaseType<RVV_T>::vmv_s(0, vlmax), vlmax));
if( std::abs(p) <= eps*std::sqrt((double)a*b) )
continue;
p *= 2;
double beta = a - b, gamma = hypot((double)p, beta);
if( beta < 0 )
{
double delta = (gamma - beta)*0.5;
s = (T)std::sqrt(delta/gamma);
c = (T)(p/(gamma*s*2));
}
else
{
c = (T)std::sqrt((gamma + beta)/(gamma*2));
s = (T)(p/(gamma*c*2));
}
vec_sum1 = RVV_T::vmv(0, vlmax);
auto vec_sum2 = RVV_T::vmv(0, vlmax);
for( k = 0; k < m; k += vl )
{
vl = RVV_T::setvl(m - k);
auto vec_src1 = RVV_T::vload(Ai + k, vl);
auto vec_src2 = RVV_T::vload(Aj + k, vl);
auto vec_t0 = __riscv_vfadd(__riscv_vfmul(vec_src1, c, vl), __riscv_vfmul(vec_src2, s, vl), vl);
auto vec_t1 = __riscv_vfsub(__riscv_vfmul(vec_src2, c, vl), __riscv_vfmul(vec_src1, s, vl), vl);
RVV_T::vstore(Ai + k, vec_t0, vl);
RVV_T::vstore(Aj + k, vec_t1, vl);
vec_sum1 = __riscv_vfmacc_tu(vec_sum1, vec_t0, vec_t0, vl);
vec_sum2 = __riscv_vfmacc_tu(vec_sum2, vec_t1, vec_t1, vl);
}
W[i] = __riscv_vfmv_f(__riscv_vfredosum(vec_sum1, RVV_BaseType<RVV_T>::vmv_s(0, vlmax), vlmax));
W[j] = __riscv_vfmv_f(__riscv_vfredosum(vec_sum2, RVV_BaseType<RVV_T>::vmv_s(0, vlmax), vlmax));
changed = true;
if( vt )
{
T *Vi = vt + i*vt_step, *Vj = vt + j*vt_step;
for( k = 0; k < n; k += vl )
{
vl = RVV_T::setvl(n - k);
auto vec_src1 = RVV_T::vload(Vi + k, vl);
auto vec_src2 = RVV_T::vload(Vj + k, vl);
auto vec_t0 = __riscv_vfadd(__riscv_vfmul(vec_src1, c, vl), __riscv_vfmul(vec_src2, s, vl), vl);
auto vec_t1 = __riscv_vfsub(__riscv_vfmul(vec_src2, c, vl), __riscv_vfmul(vec_src1, s, vl), vl);
RVV_T::vstore(Vi + k, vec_t0, vl);
RVV_T::vstore(Vj + k, vec_t1, vl);
}
}
}
if( !changed )
break;
}
for( i = 0; i < n; i++ )
{
auto vec_sum = RVV_T::vmv(0, vlmax);
for( k = 0; k < m; k += vl )
{
vl = RVV_T::setvl(m - k);
auto vec_src = RVV_T::vload(src + i * src_step + k, vl);
vec_sum = __riscv_vfmacc_tu(vec_sum, vec_src, vec_src, vl);
}
W[i] = std::sqrt(__riscv_vfmv_f(__riscv_vfredosum(vec_sum, RVV_BaseType<RVV_T>::vmv_s(0, vlmax), vlmax)));
}
for( i = 0; i < n-1; i++ )
{
j = i;
for( k = i+1; k < n; k++ )
{
if( W[j] < W[k] )
j = k;
}
if( i != j )
{
std::swap(W[i], W[j]);
if( vt )
{
for( k = 0; k < m; k++ )
std::swap(src[i*src_step + k], src[j*src_step + k]);
for( k = 0; k < n; k++ )
std::swap(vt[i*vt_step + k], vt[j*vt_step + k]);
}
}
}
for( i = 0; i < n; i++ )
w[i] = (T)W[i];
if( !vt )
return CV_HAL_ERROR_OK;
for( i = 0; i < n1; i++ )
{
sd = i < n ? W[i] : 0;
for( int ii = 0; ii < 100 && sd <= minval; ii++ )
{
// if we got a zero singular value, then in order to get the corresponding left singular vector
// we generate a random vector, project it to the previously computed left singular vectors,
// subtract the projection and normalize the difference.
const T val0 = (T)(1./m);
for( k = 0; k < m; k++ )
{
T val = (rand() & 256) != 0 ? val0 : -val0;
src[i*src_step + k] = val;
}
for( iter = 0; iter < 2; iter++ )
{
for( j = 0; j < i; j++ )
{
auto vec_sum = RVV_T::vmv(0, vlmax);
for( k = 0; k < m; k += vl )
{
vl = RVV_T::setvl(m - k);
auto vec_src1 = RVV_T::vload(src + i * src_step + k, vl);
auto vec_src2 = RVV_T::vload(src + j * src_step + k, vl);
vec_sum = __riscv_vfmacc_tu(vec_sum, vec_src1, vec_src2, vl);
}
sd = __riscv_vfmv_f(__riscv_vfredosum(vec_sum, RVV_BaseType<RVV_T>::vmv_s(0, vlmax), vlmax));
vec_sum = RVV_T::vmv(0, vlmax);
for( k = 0; k < m; k += vl )
{
vl = RVV_T::setvl(m - k);
auto vec_src1 = RVV_T::vload(src + i * src_step + k, vl);
auto vec_src2 = RVV_T::vload(src + j * src_step + k, vl);
vec_src1 = __riscv_vfnmsac(vec_src1, sd, vec_src2, vl);
RVV_T::vstore(src + i * src_step + k, vec_src1, vl);
vec_sum = __riscv_vfadd_tu(vec_sum, vec_sum, __riscv_vfabs(vec_src1, vl), vl);
}
T asum = __riscv_vfmv_f(__riscv_vfredosum(vec_sum, RVV_BaseType<RVV_T>::vmv_s(0, vlmax), vlmax));
asum = asum > eps*100 ? 1/asum : 0;
for( k = 0; k < m; k += vl )
{
vl = RVV_T::setvl(m - k);
auto vec_src = RVV_T::vload(src + i * src_step + k, vl);
vec_src = __riscv_vfmul(vec_src, asum, vl);
RVV_T::vstore(src + i * src_step + k, vec_src, vl);
}
}
}
auto vec_sum = RVV_T::vmv(0, vlmax);
for( k = 0; k < m; k += vl )
{
vl = RVV_T::setvl(m - k);
auto vec_src1 = RVV_T::vload(src + i * src_step + k, vl);
auto vec_src2 = RVV_T::vload(src + j * src_step + k, vl);
vec_sum = __riscv_vfmacc_tu(vec_sum, vec_src1, vec_src2, vl);
}
sd = std::sqrt(__riscv_vfmv_f(__riscv_vfredosum(vec_sum, RVV_BaseType<RVV_T>::vmv_s(0, vlmax), vlmax)));
}
s = (T)(sd > minval ? 1/sd : 0.);
for( k = 0; k < m; k += vl )
{
vl = RVV_T::setvl(m - k);
auto vec_src = RVV_T::vload(src + i * src_step + k, vl);
vec_src = __riscv_vfmul(vec_src, s, vl);
RVV_T::vstore(src + i * src_step + k, vec_src, vl);
}
}
return CV_HAL_ERROR_OK;
}
}}}
#endif
+485
View File
@@ -0,0 +1,485 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level
// directory of this distribution and at http://opencv.org/license.html.
#pragma once
#include <riscv_vector.h>
#include <type_traits>
namespace cv { namespace cv_hal_rvv {
enum RVV_LMUL
{
LMUL_1 = 1,
LMUL_2 = 2,
LMUL_4 = 4,
LMUL_8 = 8,
LMUL_f2,
LMUL_f4,
LMUL_f8,
};
template <typename T, RVV_LMUL LMUL>
struct RVV;
// -------------------------------Supported types--------------------------------
using RVV_U8M1 = struct RVV<uint8_t, LMUL_1>;
using RVV_U8M2 = struct RVV<uint8_t, LMUL_2>;
using RVV_U8M4 = struct RVV<uint8_t, LMUL_4>;
using RVV_U8M8 = struct RVV<uint8_t, LMUL_8>;
using RVV_U8MF2 = struct RVV<uint8_t, LMUL_f2>;
using RVV_U8MF4 = struct RVV<uint8_t, LMUL_f4>;
using RVV_U8MF8 = struct RVV<uint8_t, LMUL_f8>;
using RVV_I8M1 = struct RVV<int8_t, LMUL_1>;
using RVV_I8M2 = struct RVV<int8_t, LMUL_2>;
using RVV_I8M4 = struct RVV<int8_t, LMUL_4>;
using RVV_I8M8 = struct RVV<int8_t, LMUL_8>;
using RVV_I8MF2 = struct RVV<int8_t, LMUL_f2>;
using RVV_I8MF4 = struct RVV<int8_t, LMUL_f4>;
using RVV_I8MF8 = struct RVV<int8_t, LMUL_f8>;
using RVV_U16M1 = struct RVV<uint16_t, LMUL_1>;
using RVV_U16M2 = struct RVV<uint16_t, LMUL_2>;
using RVV_U16M4 = struct RVV<uint16_t, LMUL_4>;
using RVV_U16M8 = struct RVV<uint16_t, LMUL_8>;
using RVV_U16MF2 = struct RVV<uint16_t, LMUL_f2>;
using RVV_U16MF4 = struct RVV<uint16_t, LMUL_f4>;
using RVV_I16M1 = struct RVV<int16_t, LMUL_1>;
using RVV_I16M2 = struct RVV<int16_t, LMUL_2>;
using RVV_I16M4 = struct RVV<int16_t, LMUL_4>;
using RVV_I16M8 = struct RVV<int16_t, LMUL_8>;
using RVV_I16MF2 = struct RVV<int16_t, LMUL_f2>;
using RVV_I16MF4 = struct RVV<int16_t, LMUL_f4>;
using RVV_U32M1 = struct RVV<uint32_t, LMUL_1>;
using RVV_U32M2 = struct RVV<uint32_t, LMUL_2>;
using RVV_U32M4 = struct RVV<uint32_t, LMUL_4>;
using RVV_U32M8 = struct RVV<uint32_t, LMUL_8>;
using RVV_U32MF2 = struct RVV<uint32_t, LMUL_f2>;
using RVV_I32M1 = struct RVV<int32_t, LMUL_1>;
using RVV_I32M2 = struct RVV<int32_t, LMUL_2>;
using RVV_I32M4 = struct RVV<int32_t, LMUL_4>;
using RVV_I32M8 = struct RVV<int32_t, LMUL_8>;
using RVV_I32MF2 = struct RVV<int32_t, LMUL_f2>;
using RVV_U64M1 = struct RVV<uint64_t, LMUL_1>;
using RVV_U64M2 = struct RVV<uint64_t, LMUL_2>;
using RVV_U64M4 = struct RVV<uint64_t, LMUL_4>;
using RVV_U64M8 = struct RVV<uint64_t, LMUL_8>;
using RVV_I64M1 = struct RVV<int64_t, LMUL_1>;
using RVV_I64M2 = struct RVV<int64_t, LMUL_2>;
using RVV_I64M4 = struct RVV<int64_t, LMUL_4>;
using RVV_I64M8 = struct RVV<int64_t, LMUL_8>;
using RVV_F32M1 = struct RVV<float, LMUL_1>;
using RVV_F32M2 = struct RVV<float, LMUL_2>;
using RVV_F32M4 = struct RVV<float, LMUL_4>;
using RVV_F32M8 = struct RVV<float, LMUL_8>;
using RVV_F32MF2 = struct RVV<float, LMUL_f2>;
using RVV_F64M1 = struct RVV<double, LMUL_1>;
using RVV_F64M2 = struct RVV<double, LMUL_2>;
using RVV_F64M4 = struct RVV<double, LMUL_4>;
using RVV_F64M8 = struct RVV<double, LMUL_8>;
// Only for dst type lmul >= 1
template <typename Dst_T, typename RVV_T>
using RVV_SameLen =
RVV<Dst_T, RVV_LMUL(RVV_T::lmul / sizeof(typename RVV_T::ElemType) * sizeof(Dst_T))>;
template <typename RVV_T>
using RVV_BaseType = RVV<typename RVV_T::ElemType, LMUL_1>;
// -------------------------------Supported operations--------------------------------
#define HAL_RVV_SIZE_RELATED(EEW, TYPE, LMUL, S_OR_F, X_OR_F, IS_U, IS_F) \
static inline size_t setvlmax() { return __riscv_vsetvlmax_e##EEW##LMUL(); } \
static inline size_t setvl(size_t vl) { return __riscv_vsetvl_e##EEW##LMUL(vl); } \
static inline VecType vload(const ElemType* ptr, size_t vl) { \
return __riscv_vle##EEW##_v_##TYPE##LMUL(ptr, vl); \
} \
static inline VecType vload(BoolType vm, const ElemType* ptr, size_t vl) { \
return __riscv_vle##EEW(vm, ptr, vl); \
} \
static inline VecType vload_stride(const ElemType* ptr, ptrdiff_t unit, size_t vl) { \
return __riscv_vlse##EEW##_v_##TYPE##LMUL(ptr, unit, vl); \
} \
static inline VecType vload_stride(BoolType vm, const ElemType* ptr, ptrdiff_t unit, size_t vl) { \
return __riscv_vlse##EEW(vm, ptr, unit, vl); \
} \
static inline void vstore(ElemType* ptr, VecType v, size_t vl) { \
__riscv_vse##EEW(ptr, v, vl); \
} \
static inline void vstore(BoolType vm, ElemType* ptr, VecType v, size_t vl) { \
__riscv_vse##EEW(vm, ptr, v, vl); \
} \
static inline void vstore_stride(ElemType* ptr, ptrdiff_t unit, VecType v, size_t vl) { \
__riscv_vsse##EEW(ptr, unit, v, vl); \
} \
static inline void vstore_stride(BoolType vm, ElemType* ptr, ptrdiff_t unit, VecType v, size_t vl) { \
__riscv_vsse##EEW(vm, ptr, unit, v, vl); \
} \
static inline VecType vundefined() { return __riscv_vundefined_##TYPE##LMUL(); } \
static inline VecType vmv(ElemType a, size_t vl) { \
return __riscv_v##IS_F##mv_v_##X_OR_F##_##TYPE##LMUL(a, vl); \
} \
static inline VecType vmv_s(ElemType a, size_t vl) { \
return __riscv_v##IS_F##mv_s_##X_OR_F##_##TYPE##LMUL(a, vl); \
} \
HAL_RVV_SIZE_RELATED_CUSTOM(EEW, TYPE, LMUL)
#define HAL_RVV_SIZE_UNRELATED(S_OR_F, X_OR_F, IS_U, IS_F) \
static inline ElemType vmv_x(VecType vs2) { return __riscv_v##IS_F##mv_##X_OR_F(vs2); } \
\
static inline BoolType vmlt(VecType vs2, VecType vs1, size_t vl) { \
return __riscv_vm##S_OR_F##lt##IS_U(vs2, vs1, vl); \
} \
static inline BoolType vmle(VecType vs2, VecType vs1, size_t vl) { \
return __riscv_vm##S_OR_F##le##IS_U(vs2, vs1, vl); \
} \
static inline BoolType vmgt(VecType vs2, VecType vs1, size_t vl) { \
return __riscv_vm##S_OR_F##gt##IS_U(vs2, vs1, vl); \
} \
static inline BoolType vmge(VecType vs2, VecType vs1, size_t vl) { \
return __riscv_vm##S_OR_F##ge##IS_U(vs2, vs1, vl); \
} \
static inline BoolType vmlt_mu(BoolType vm, BoolType vd, VecType vs2, VecType vs1, size_t vl) { \
return __riscv_vm##S_OR_F##lt##IS_U##_mu(vm, vd, vs2, vs1, vl); \
} \
static inline BoolType vmle_mu(BoolType vm, BoolType vd, VecType vs2, VecType vs1, size_t vl) { \
return __riscv_vm##S_OR_F##le##IS_U##_mu(vm, vd, vs2, vs1, vl); \
} \
static inline BoolType vmgt_mu(BoolType vm, BoolType vd, VecType vs2, VecType vs1, size_t vl) { \
return __riscv_vm##S_OR_F##gt##IS_U##_mu(vm, vd, vs2, vs1, vl); \
} \
static inline BoolType vmge_mu(BoolType vm, BoolType vd, VecType vs2, VecType vs1, size_t vl) { \
return __riscv_vm##S_OR_F##ge##IS_U##_mu(vm, vd, vs2, vs1, vl); \
} \
\
static inline VecType vmin(VecType vs2, VecType vs1, size_t vl) { \
return __riscv_v##IS_F##min##IS_U(vs2, vs1, vl); \
} \
static inline VecType vmax(VecType vs2, VecType vs1, size_t vl) { \
return __riscv_v##IS_F##max##IS_U(vs2, vs1, vl); \
} \
static inline VecType vmin_tu(VecType vd, VecType vs2, VecType vs1, size_t vl) { \
return __riscv_v##IS_F##min##IS_U##_tu(vd, vs2, vs1, vl); \
} \
static inline VecType vmax_tu(VecType vd, VecType vs2, VecType vs1, size_t vl) { \
return __riscv_v##IS_F##max##IS_U##_tu(vd, vs2, vs1, vl); \
} \
static inline VecType vmin_tumu(BoolType vm, VecType vd, VecType vs2, VecType vs1, size_t vl) { \
return __riscv_v##IS_F##min##IS_U##_tumu(vm, vd, vs2, vs1, vl); \
} \
static inline VecType vmax_tumu(BoolType vm, VecType vd, VecType vs2, VecType vs1, size_t vl) { \
return __riscv_v##IS_F##max##IS_U##_tumu(vm, vd, vs2, vs1, vl); \
} \
\
static inline BaseType vredmin(VecType vs2, BaseType vs1, size_t vl) { \
return __riscv_v##IS_F##redmin##IS_U(vs2, vs1, vl); \
} \
static inline BaseType vredmax(VecType vs2, BaseType vs1, size_t vl) { \
return __riscv_v##IS_F##redmax##IS_U(vs2, vs1, vl); \
}
#define HAL_RVV_BOOL_TYPE(S_OR_F, X_OR_F, IS_U, IS_F) \
decltype(__riscv_vm##S_OR_F##eq(std::declval<VecType>(), std::declval<VecType>(), 0))
#define HAL_RVV_DEFINE_ONE(ELEM_TYPE, VEC_TYPE, LMUL_TYPE, \
EEW, TYPE, LMUL, ...) \
template <> struct RVV<ELEM_TYPE, LMUL_TYPE> \
{ \
using ElemType = ELEM_TYPE; \
using VecType = v##VEC_TYPE##LMUL##_t; \
using BoolType = HAL_RVV_BOOL_TYPE(__VA_ARGS__); \
using BaseType = v##VEC_TYPE##m1_t; \
\
static constexpr size_t lmul = LMUL_TYPE; \
\
HAL_RVV_SIZE_RELATED(EEW, TYPE, LMUL, __VA_ARGS__) \
HAL_RVV_SIZE_UNRELATED(__VA_ARGS__) \
\
template <typename FROM> \
inline static VecType cast(FROM v, size_t vl); \
}; \
\
template <> \
inline RVV<ELEM_TYPE, LMUL_TYPE>::VecType \
RVV<ELEM_TYPE, LMUL_TYPE>::cast( \
RVV<ELEM_TYPE, LMUL_TYPE>::VecType v, \
[[maybe_unused]] size_t vl \
) \
{ \
return v; \
}
// -------------------------------Define all types--------------------------------
#define HAL_RVV_DEFINE_ALL(ELEM_TYPE, VEC_TYPE, \
EEW, TYPE, ...) \
HAL_RVV_DEFINE_ONE(ELEM_TYPE, VEC_TYPE, LMUL_1, \
EEW, TYPE, m1, __VA_ARGS__) \
HAL_RVV_DEFINE_ONE(ELEM_TYPE, VEC_TYPE, LMUL_2, \
EEW, TYPE, m2, __VA_ARGS__) \
HAL_RVV_DEFINE_ONE(ELEM_TYPE, VEC_TYPE, LMUL_4, \
EEW, TYPE, m4, __VA_ARGS__) \
HAL_RVV_DEFINE_ONE(ELEM_TYPE, VEC_TYPE, LMUL_8, \
EEW, TYPE, m8, __VA_ARGS__)
#define HAL_RVV_SIGNED_PARAM s,x, ,
#define HAL_RVV_UNSIGNED_PARAM s,x,u,
#define HAL_RVV_FLOAT_PARAM f,f, ,f
// -------------------------------Define Unsigned Integer--------------------------------
#define HAL_RVV_SIZE_RELATED_CUSTOM(EEW, TYPE, LMUL) \
static inline VecType vid(size_t vl) { return __riscv_vid_v_##TYPE##LMUL(vl); }
// LMUL = 1, 2, 4, 8
HAL_RVV_DEFINE_ALL( uint8_t, uint8, 8, u8, HAL_RVV_UNSIGNED_PARAM)
HAL_RVV_DEFINE_ALL(uint16_t, uint16, 16, u16, HAL_RVV_UNSIGNED_PARAM)
HAL_RVV_DEFINE_ALL(uint32_t, uint32, 32, u32, HAL_RVV_UNSIGNED_PARAM)
HAL_RVV_DEFINE_ALL(uint64_t, uint64, 64, u64, HAL_RVV_UNSIGNED_PARAM)
// LMUL = f2
HAL_RVV_DEFINE_ONE( uint8_t, uint8, LMUL_f2, 8, u8, mf2, HAL_RVV_UNSIGNED_PARAM)
HAL_RVV_DEFINE_ONE(uint16_t, uint16, LMUL_f2, 16, u16, mf2, HAL_RVV_UNSIGNED_PARAM)
HAL_RVV_DEFINE_ONE(uint32_t, uint32, LMUL_f2, 32, u32, mf2, HAL_RVV_UNSIGNED_PARAM)
// LMUL = f4
HAL_RVV_DEFINE_ONE( uint8_t, uint8, LMUL_f4, 8, u8, mf4, HAL_RVV_UNSIGNED_PARAM)
HAL_RVV_DEFINE_ONE(uint16_t, uint16, LMUL_f4, 16, u16, mf4, HAL_RVV_UNSIGNED_PARAM)
// LMUL = f8
HAL_RVV_DEFINE_ONE( uint8_t, uint8, LMUL_f8, 8, u8, mf8, HAL_RVV_UNSIGNED_PARAM)
#undef HAL_RVV_SIZE_RELATED_CUSTOM
// -------------------------------Define Signed Integer--------------------------------
#define HAL_RVV_SIZE_RELATED_CUSTOM(EEW, TYPE, LMUL)
// LMUL = 1, 2, 4, 8
HAL_RVV_DEFINE_ALL( int8_t, int8, 8, i8, HAL_RVV_SIGNED_PARAM)
HAL_RVV_DEFINE_ALL(int16_t, int16, 16, i16, HAL_RVV_SIGNED_PARAM)
HAL_RVV_DEFINE_ALL(int32_t, int32, 32, i32, HAL_RVV_SIGNED_PARAM)
HAL_RVV_DEFINE_ALL(int64_t, int64, 64, i64, HAL_RVV_SIGNED_PARAM)
// LMUL = f2
HAL_RVV_DEFINE_ONE( int8_t, int8, LMUL_f2, 8, i8, mf2, HAL_RVV_SIGNED_PARAM)
HAL_RVV_DEFINE_ONE(int16_t, int16, LMUL_f2, 16, i16, mf2, HAL_RVV_SIGNED_PARAM)
HAL_RVV_DEFINE_ONE(int32_t, int32, LMUL_f2, 32, i32, mf2, HAL_RVV_SIGNED_PARAM)
// LMUL = f4
HAL_RVV_DEFINE_ONE( int8_t, int8, LMUL_f4, 8, i8, mf4, HAL_RVV_SIGNED_PARAM)
HAL_RVV_DEFINE_ONE(int16_t, int16, LMUL_f4, 16, i16, mf4, HAL_RVV_SIGNED_PARAM)
// LMUL = f8
HAL_RVV_DEFINE_ONE( int8_t, int8, LMUL_f8, 8, i8, mf8, HAL_RVV_SIGNED_PARAM)
// -------------------------------Define Floating Point--------------------------------
// LMUL = 1, 2, 4, 8
HAL_RVV_DEFINE_ALL( float, float32, 32, f32, HAL_RVV_FLOAT_PARAM)
HAL_RVV_DEFINE_ALL(double, float64, 64, f64, HAL_RVV_FLOAT_PARAM)
// LMUL = f2
HAL_RVV_DEFINE_ONE( float, float32, LMUL_f2, 32, f32, mf2, HAL_RVV_FLOAT_PARAM)
#undef HAL_RVV_SIZE_RELATED_CUSTOM
#undef HAL_RVV_DEFINE_ALL
#undef HAL_RVV_DEFINE_ONE
#undef HAL_RVV_BOOL_TYPE
#undef HAL_RVV_SIZE_UNRELATED
#undef HAL_RVV_SIZE_RELATED
// -------------------------------Define cast--------------------------------
#define HAL_RVV_CVT(ONE, TWO) \
template <> \
inline ONE::VecType ONE::cast(TWO::VecType v, size_t vl) { return __riscv_vncvt_x(v, vl); } \
template <> \
inline TWO::VecType TWO::cast(ONE::VecType v, size_t vl) { return __riscv_vwcvt_x(v, vl); }
HAL_RVV_CVT(RVV_I8M4, RVV_I16M8)
HAL_RVV_CVT(RVV_I8M2, RVV_I16M4)
HAL_RVV_CVT(RVV_I8M1, RVV_I16M2)
HAL_RVV_CVT(RVV_I8MF2, RVV_I16M1)
HAL_RVV_CVT(RVV_I8MF4, RVV_I16MF2)
HAL_RVV_CVT(RVV_I8MF8, RVV_I16MF4)
HAL_RVV_CVT(RVV_I16M4, RVV_I32M8)
HAL_RVV_CVT(RVV_I16M2, RVV_I32M4)
HAL_RVV_CVT(RVV_I16M1, RVV_I32M2)
HAL_RVV_CVT(RVV_I16MF2, RVV_I32M1)
HAL_RVV_CVT(RVV_I16MF4, RVV_I32MF2)
HAL_RVV_CVT(RVV_I32M4, RVV_I64M8)
HAL_RVV_CVT(RVV_I32M2, RVV_I64M4)
HAL_RVV_CVT(RVV_I32M1, RVV_I64M2)
HAL_RVV_CVT(RVV_I32MF2, RVV_I64M1)
#undef HAL_RVV_CVT
#define HAL_RVV_CVT(ONE, TWO) \
template <> \
inline ONE::VecType ONE::cast(TWO::VecType v, size_t vl) { return __riscv_vncvt_x(v, vl); } \
template <> \
inline TWO::VecType TWO::cast(ONE::VecType v, size_t vl) { return __riscv_vwcvtu_x(v, vl); }
HAL_RVV_CVT(RVV_U8M4, RVV_U16M8)
HAL_RVV_CVT(RVV_U8M2, RVV_U16M4)
HAL_RVV_CVT(RVV_U8M1, RVV_U16M2)
HAL_RVV_CVT(RVV_U8MF2, RVV_U16M1)
HAL_RVV_CVT(RVV_U8MF4, RVV_U16MF2)
HAL_RVV_CVT(RVV_U8MF8, RVV_U16MF4)
HAL_RVV_CVT(RVV_U16M4, RVV_U32M8)
HAL_RVV_CVT(RVV_U16M2, RVV_U32M4)
HAL_RVV_CVT(RVV_U16M1, RVV_U32M2)
HAL_RVV_CVT(RVV_U16MF2, RVV_U32M1)
HAL_RVV_CVT(RVV_U16MF4, RVV_U32MF2)
HAL_RVV_CVT(RVV_U32M4, RVV_U64M8)
HAL_RVV_CVT(RVV_U32M2, RVV_U64M4)
HAL_RVV_CVT(RVV_U32M1, RVV_U64M2)
HAL_RVV_CVT(RVV_U32MF2, RVV_U64M1)
#undef HAL_RVV_CVT
#define HAL_RVV_CVT(ONE, FOUR) \
template <> \
inline FOUR::VecType FOUR::cast(ONE::VecType v, size_t vl) { return __riscv_vsext_vf4(v, vl); } \
template <> \
inline ONE::VecType ONE::cast(FOUR::VecType v, size_t vl) { \
return __riscv_vncvt_x(__riscv_vncvt_x(v, vl), vl); \
}
HAL_RVV_CVT(RVV_I8M2, RVV_I32M8)
HAL_RVV_CVT(RVV_I8M1, RVV_I32M4)
HAL_RVV_CVT(RVV_I8MF2, RVV_I32M2)
HAL_RVV_CVT(RVV_I8MF4, RVV_I32M1)
HAL_RVV_CVT(RVV_I8MF8, RVV_I32MF2)
HAL_RVV_CVT(RVV_I16M2, RVV_I64M8)
HAL_RVV_CVT(RVV_I16M1, RVV_I64M4)
HAL_RVV_CVT(RVV_I16MF2, RVV_I64M2)
HAL_RVV_CVT(RVV_I16MF4, RVV_I64M1)
#undef HAL_RVV_CVT
#define HAL_RVV_CVT(ONE, FOUR) \
template <> \
inline FOUR::VecType FOUR::cast(ONE::VecType v, size_t vl) { return __riscv_vzext_vf4(v, vl); } \
template <> \
inline ONE::VecType ONE::cast(FOUR::VecType v, size_t vl) { \
return __riscv_vncvt_x(__riscv_vncvt_x(v, vl), vl); \
}
HAL_RVV_CVT(RVV_U8M2, RVV_U32M8)
HAL_RVV_CVT(RVV_U8M1, RVV_U32M4)
HAL_RVV_CVT(RVV_U8MF2, RVV_U32M2)
HAL_RVV_CVT(RVV_U8MF4, RVV_U32M1)
HAL_RVV_CVT(RVV_U8MF8, RVV_U32MF2)
HAL_RVV_CVT(RVV_U16M2, RVV_U64M8)
HAL_RVV_CVT(RVV_U16M1, RVV_U64M4)
HAL_RVV_CVT(RVV_U16MF2, RVV_U64M2)
HAL_RVV_CVT(RVV_U16MF4, RVV_U64M1)
#undef HAL_RVV_CVT
#define HAL_RVV_CVT(ONE, EIGHT) \
template <> \
inline EIGHT::VecType EIGHT::cast(ONE::VecType v, size_t vl) { return __riscv_vsext_vf8(v, vl); } \
template <> \
inline ONE::VecType ONE::cast(EIGHT::VecType v, size_t vl) { \
return __riscv_vncvt_x(__riscv_vncvt_x(__riscv_vncvt_x(v ,vl), vl), vl); \
}
HAL_RVV_CVT(RVV_I8M1, RVV_I64M8)
HAL_RVV_CVT(RVV_I8MF2, RVV_I64M4)
HAL_RVV_CVT(RVV_I8MF4, RVV_I64M2)
HAL_RVV_CVT(RVV_I8MF8, RVV_I64M1)
#undef HAL_RVV_CVT
#define HAL_RVV_CVT(ONE, EIGHT) \
template <> \
inline EIGHT::VecType EIGHT::cast(ONE::VecType v, size_t vl) { return __riscv_vzext_vf8(v, vl); } \
template <> \
inline ONE::VecType ONE::cast(EIGHT::VecType v, size_t vl) { \
return __riscv_vncvt_x(__riscv_vncvt_x(__riscv_vncvt_x(v ,vl), vl), vl); \
}
HAL_RVV_CVT(RVV_U8M1, RVV_U64M8)
HAL_RVV_CVT(RVV_U8MF2, RVV_U64M4)
HAL_RVV_CVT(RVV_U8MF4, RVV_U64M2)
HAL_RVV_CVT(RVV_U8MF8, RVV_U64M1)
#undef HAL_RVV_CVT
#define HAL_RVV_CVT(F32, F64) \
template <> \
inline F32::VecType F32::cast(F64::VecType v, size_t vl) { return __riscv_vfncvt_f(v, vl); } \
template <> \
inline F64::VecType F64::cast(F32::VecType v, size_t vl) { return __riscv_vfwcvt_f(v, vl); }
HAL_RVV_CVT(RVV_F32M4, RVV_F64M8)
HAL_RVV_CVT(RVV_F32M2, RVV_F64M4)
HAL_RVV_CVT(RVV_F32M1, RVV_F64M2)
HAL_RVV_CVT(RVV_F32MF2, RVV_F64M1)
#undef HAL_RVV_CVT
#define HAL_RVV_CVT(A, B, A_TYPE, B_TYPE, LMUL_TYPE, LMUL) \
template <> \
inline RVV<A, LMUL_TYPE>::VecType RVV<A, LMUL_TYPE>::cast( \
RVV<B, LMUL_TYPE>::VecType v, [[maybe_unused]] size_t vl \
) { \
return __riscv_vreinterpret_##A_TYPE##LMUL(v); \
} \
template <> \
inline RVV<B, LMUL_TYPE>::VecType RVV<B, LMUL_TYPE>::cast( \
RVV<A, LMUL_TYPE>::VecType v, [[maybe_unused]] size_t vl \
) { \
return __riscv_vreinterpret_##B_TYPE##LMUL(v); \
}
#define HAL_RVV_CVT2(A, B, A_TYPE, B_TYPE) \
HAL_RVV_CVT(A, B, A_TYPE, B_TYPE, LMUL_1, m1) \
HAL_RVV_CVT(A, B, A_TYPE, B_TYPE, LMUL_2, m2) \
HAL_RVV_CVT(A, B, A_TYPE, B_TYPE, LMUL_4, m4) \
HAL_RVV_CVT(A, B, A_TYPE, B_TYPE, LMUL_8, m8)
HAL_RVV_CVT2( uint8_t, int8_t, u8, i8)
HAL_RVV_CVT2(uint16_t, int16_t, u16, i16)
HAL_RVV_CVT2(uint32_t, int32_t, u32, i32)
HAL_RVV_CVT2(uint64_t, int64_t, u64, i64)
HAL_RVV_CVT2( int32_t, float, i32, f32)
HAL_RVV_CVT2(uint32_t, float, u32, f32)
HAL_RVV_CVT2( int64_t, double, i64, f64)
HAL_RVV_CVT2(uint64_t, double, u64, f64)
#undef HAL_RVV_CVT2
HAL_RVV_CVT( uint8_t, int8_t, u8, i8, LMUL_f2, mf2)
HAL_RVV_CVT(uint16_t, int16_t, u16, i16, LMUL_f2, mf2)
HAL_RVV_CVT(uint32_t, int32_t, u32, i32, LMUL_f2, mf2)
HAL_RVV_CVT( int32_t, float, i32, f32, LMUL_f2, mf2)
HAL_RVV_CVT(uint32_t, float, u32, f32, LMUL_f2, mf2)
HAL_RVV_CVT( uint8_t, int8_t, u8, i8, LMUL_f4, mf4)
HAL_RVV_CVT(uint16_t, int16_t, u16, i16, LMUL_f4, mf4)
HAL_RVV_CVT( uint8_t, int8_t, u8, i8, LMUL_f8, mf8)
#undef HAL_RVV_CVT
}} // namespace cv::cv_hal_rvv
+2 -2
View File
@@ -18,7 +18,7 @@ if(CV_GCC AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13)
ocv_warnings_disable(CMAKE_C_FLAGS -Wstringop-overflow)
endif()
set(VERSION 3.0.3)
set(VERSION 3.1.0)
set(COPYRIGHT_YEAR "1991-2024")
string(REPLACE "." ";" VERSION_TRIPLET ${VERSION})
list(GET VERSION_TRIPLET 0 VERSION_MAJOR)
@@ -203,7 +203,7 @@ check_type_size("size_t" SIZE_T)
check_type_size("unsigned long" UNSIGNED_LONG)
if(ENABLE_LIBJPEG_TURBO_SIMD)
add_subdirectory(src/simd)
add_subdirectory(simd)
if(NEON_INTRINSICS)
add_definitions(-DNEON_INTRINSICS)
endif()
+1 -1
View File
@@ -94,7 +94,7 @@ intended solely for clarification.
The Modified (3-clause) BSD License
===================================
Copyright (C)2009-2023 D. R. Commander. All Rights Reserved.<br>
Copyright (C)2009-2024 D. R. Commander. All Rights Reserved.<br>
Copyright (C)2015 Viktor Szathmáry. All Rights Reserved.
Redistribution and use in source and binary forms, with or without
+14 -12
View File
@@ -36,16 +36,18 @@ TO DO Plans for future IJG releases.
Other documentation files in the distribution are:
User documentation:
usage.txt Usage instructions for cjpeg, djpeg, jpegtran,
rdjpgcom, and wrjpgcom.
*.1 Unix-style man pages for programs (same info as usage.txt).
wizard.txt Advanced usage instructions for JPEG wizards only.
change.log Version-to-version change highlights.
doc/usage.txt Usage instructions for cjpeg, djpeg, jpegtran,
rdjpgcom, and wrjpgcom.
doc/*.1 Unix-style man pages for programs (same info as
usage.txt).
doc/wizard.txt Advanced usage instructions for JPEG wizards only.
doc/change.log Version-to-version change highlights.
Programmer and internal documentation:
libjpeg.txt How to use the JPEG library in your own programs.
example.c Sample code for calling the JPEG library.
structure.txt Overview of the JPEG library's internal structure.
coderules.txt Coding style rules --- please read if you contribute code.
doc/libjpeg.txt How to use the JPEG library in your own programs.
src/example.c Sample code for calling the JPEG library.
doc/structure.txt Overview of the JPEG library's internal structure.
doc/coderules.txt Coding style rules --- please read if you contribute
code.
Please read at least usage.txt. Some information can also be found in the JPEG
FAQ (Frequently Asked Questions) article. See ARCHIVE LOCATIONS below to find
@@ -89,9 +91,9 @@ The library is intended to be reused in other applications.
In order to support file conversion and viewing software, we have included
considerable functionality beyond the bare JPEG coding/decoding capability;
for example, the color quantization modules are not strictly part of JPEG
decoding, but they are essential for output to colormapped file formats or
colormapped displays. These extra functions can be compiled out of the
library if not required for a particular application.
decoding, but they are essential for output to colormapped file formats. These
extra functions can be compiled out of the library if not required for a
particular application.
We have also included "jpegtran", a utility for lossless transcoding between
different JPEG processes, and "rdjpgcom" and "wrjpgcom", two simple
+13 -9
View File
@@ -69,9 +69,12 @@ JPEG images:
generating planar YUV images and performing multiple simultaneous lossless
transforms on an image. The Java interface for libjpeg-turbo is written on
top of the TurboJPEG API. The TurboJPEG API is recommended for first-time
users of libjpeg-turbo. Refer to [tjexample.c](tjexample.c) and
[TJExample.java](java/TJExample.java) for examples of its usage and to
<http://libjpeg-turbo.org/Documentation/Documentation> for API documentation.
users of libjpeg-turbo. Refer to [tjcomp.c](src/tjcomp.c),
[tjdecomp.c](src/tjdecomp.c), [tjtran.c](src/tjtran.c),
[TJComp.java](java/TJComp.java), [TJDecomp.java](java/TJDecomp.java), and
[TJTran.java](java/TJTran.java) for examples of its usage and to
<https://libjpeg-turbo.org/Documentation/Documentation> for API
documentation.
- **libjpeg API**<br>
This is the de facto industry-standard API for compressing and decompressing
@@ -79,8 +82,9 @@ JPEG images:
more powerful. The libjpeg API implementation in libjpeg-turbo is both
API/ABI-compatible and mathematically compatible with libjpeg v6b. It can
also optionally be configured to be API/ABI-compatible with libjpeg v7 and v8
(see below.) Refer to [cjpeg.c](cjpeg.c) and [djpeg.c](djpeg.c) for examples
of its usage and to [libjpeg.txt](libjpeg.txt) for API documentation.
(see below.) Refer to [cjpeg.c](src/cjpeg.c) and [djpeg.c](src/djpeg.c) for
examples of its usage and to [libjpeg.txt](doc/libjpeg.txt) for API
documentation.
There is no significant performance advantage to either API when both are used
to perform similar operations.
@@ -132,9 +136,9 @@ extensions at compile time with:
#ifdef JCS_ALPHA_EXTENSIONS
[jcstest.c](jcstest.c), located in the libjpeg-turbo source tree, demonstrates
how to check for the existence of the colorspace extensions at compile time and
run time.
[jcstest.c](src/jcstest.c), located in the libjpeg-turbo source tree,
demonstrates how to check for the existence of the colorspace extensions at
compile time and run time.
libjpeg v7 and v8 API/ABI Emulation
-----------------------------------
@@ -199,7 +203,7 @@ supported and which aren't.
NOTE: As of this writing, extensive research has been conducted into the
usefulness of DCT scaling as a means of data reduction and SmartScale as a
means of quality improvement. Readers are invited to peruse the research at
<http://www.libjpeg-turbo.org/About/SmartScale> and draw their own conclusions,
<https://libjpeg-turbo.org/About/SmartScale> and draw their own conclusions,
but it is the general belief of our project that these features have not
demonstrated sufficient usefulness to justify inclusion in libjpeg-turbo.
@@ -273,48 +273,33 @@ endif()
check_c_source_compiles("
#include <arm_neon.h>
int main(int argc, char **argv) {
int16_t input[] = {
(int16_t)argc, (int16_t)argc, (int16_t)argc, (int16_t)argc,
(int16_t)argc, (int16_t)argc, (int16_t)argc, (int16_t)argc,
(int16_t)argc, (int16_t)argc, (int16_t)argc, (int16_t)argc
};
int16x4x3_t output = vld1_s16_x3(input);
int16_t input[12];
int16x4x3_t output;
int i;
for (i = 0; i < 12; i++) input[i] = (int16_t)argc;
output = vld1_s16_x3(input);
vst3_s16(input, output);
return (int)input[0];
}" HAVE_VLD1_S16_X3)
check_c_source_compiles("
#include <arm_neon.h>
int main(int argc, char **argv) {
uint16_t input[] = {
(uint16_t)argc, (uint16_t)argc, (uint16_t)argc, (uint16_t)argc,
(uint16_t)argc, (uint16_t)argc, (uint16_t)argc, (uint16_t)argc
};
uint16x4x2_t output = vld1_u16_x2(input);
uint16_t input[8];
uint16x4x2_t output;
int i;
for (i = 0; i < 8; i++) input[i] = (uint16_t)argc;
output = vld1_u16_x2(input);
vst2_u16(input, output);
return (int)input[0];
}" HAVE_VLD1_U16_X2)
check_c_source_compiles("
#include <arm_neon.h>
int main(int argc, char **argv) {
uint8_t input[] = {
(uint8_t)argc, (uint8_t)argc, (uint8_t)argc, (uint8_t)argc,
(uint8_t)argc, (uint8_t)argc, (uint8_t)argc, (uint8_t)argc,
(uint8_t)argc, (uint8_t)argc, (uint8_t)argc, (uint8_t)argc,
(uint8_t)argc, (uint8_t)argc, (uint8_t)argc, (uint8_t)argc,
(uint8_t)argc, (uint8_t)argc, (uint8_t)argc, (uint8_t)argc,
(uint8_t)argc, (uint8_t)argc, (uint8_t)argc, (uint8_t)argc,
(uint8_t)argc, (uint8_t)argc, (uint8_t)argc, (uint8_t)argc,
(uint8_t)argc, (uint8_t)argc, (uint8_t)argc, (uint8_t)argc,
(uint8_t)argc, (uint8_t)argc, (uint8_t)argc, (uint8_t)argc,
(uint8_t)argc, (uint8_t)argc, (uint8_t)argc, (uint8_t)argc,
(uint8_t)argc, (uint8_t)argc, (uint8_t)argc, (uint8_t)argc,
(uint8_t)argc, (uint8_t)argc, (uint8_t)argc, (uint8_t)argc,
(uint8_t)argc, (uint8_t)argc, (uint8_t)argc, (uint8_t)argc,
(uint8_t)argc, (uint8_t)argc, (uint8_t)argc, (uint8_t)argc,
(uint8_t)argc, (uint8_t)argc, (uint8_t)argc, (uint8_t)argc,
(uint8_t)argc, (uint8_t)argc, (uint8_t)argc, (uint8_t)argc
};
uint8x16x4_t output = vld1q_u8_x4(input);
uint8_t input[64];
uint8x16x4_t output;
int i;
for (i = 0; i < 64; i++) input[i] = (uint8_t)argc;
output = vld1q_u8_x4(input);
vst4q_u8(input, output);
return (int)input[0];
}" HAVE_VLD1Q_U8_X4)
@@ -369,7 +354,8 @@ if(NOT NEON_INTRINSICS)
separate_arguments(CMAKE_ASM_FLAGS_SEP UNIX_COMMAND "${CMAKE_ASM_FLAGS}")
execute_process(COMMAND ${CMAKE_ASM_COMPILER} ${CMAKE_ASM_FLAGS_SEP}
-x assembler-with-cpp -c ${CMAKE_CURRENT_BINARY_DIR}/gastest.S
RESULT_VARIABLE RESULT OUTPUT_VARIABLE OUTPUT ERROR_VARIABLE ERROR)
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} RESULT_VARIABLE RESULT
OUTPUT_VARIABLE OUTPUT ERROR_VARIABLE ERROR)
if(NOT RESULT EQUAL 0)
message(WARNING "GAS appears to be broken. Using the full Neon SIMD intrinsics implementation.")
set(NEON_INTRINSICS 1 CACHE INTERNAL "" FORCE)
@@ -2,6 +2,7 @@
* jchuff-neon.c - Huffman entropy encoding (32-bit Arm Neon)
*
* Copyright (C) 2020, Arm Limited. All Rights Reserved.
* Copyright (C) 2024, D. R. Commander. All Rights Reserved.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -24,11 +25,11 @@
*/
#define JPEG_INTERNALS
#include "../../../jinclude.h"
#include "../../../jpeglib.h"
#include "../../../jsimd.h"
#include "../../../jdct.h"
#include "../../../jsimddct.h"
#include "../../../src/jinclude.h"
#include "../../../src/jpeglib.h"
#include "../../../src/jsimd.h"
#include "../../../src/jdct.h"
#include "../../../src/jsimddct.h"
#include "../../jsimd.h"
#include "../jchuff.h"
#include "neon-compat.h"
@@ -3,7 +3,7 @@
*
* Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
* Copyright (C) 2011, Nokia Corporation and/or its subsidiary(-ies).
* Copyright (C) 2009-2011, 2013-2014, 2016, 2018, 2022, D. R. Commander.
* Copyright (C) 2009-2011, 2013-2014, 2016, 2018, 2022, 2024, D. R. Commander.
* Copyright (C) 2015-2016, 2018, 2022, Matthieu Darbois.
* Copyright (C) 2019, Google LLC.
* Copyright (C) 2020, Arm Limited.
@@ -18,11 +18,11 @@
*/
#define JPEG_INTERNALS
#include "../../../jinclude.h"
#include "../../../jpeglib.h"
#include "../../../jsimd.h"
#include "../../../jdct.h"
#include "../../../jsimddct.h"
#include "../../../src/jinclude.h"
#include "../../../src/jpeglib.h"
#include "../../../src/jsimd.h"
#include "../../../src/jdct.h"
#include "../../../src/jsimddct.h"
#include "../../jsimd.h"
#include <ctype.h>
@@ -2,7 +2,7 @@
* jchuff-neon.c - Huffman entropy encoding (64-bit Arm Neon)
*
* Copyright (C) 2020-2021, Arm Limited. All Rights Reserved.
* Copyright (C) 2020, 2022, D. R. Commander. All Rights Reserved.
* Copyright (C) 2020, 2022, 2024, D. R. Commander. All Rights Reserved.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -25,11 +25,11 @@
*/
#define JPEG_INTERNALS
#include "../../../jinclude.h"
#include "../../../jpeglib.h"
#include "../../../jsimd.h"
#include "../../../jdct.h"
#include "../../../jsimddct.h"
#include "../../../src/jinclude.h"
#include "../../../src/jpeglib.h"
#include "../../../src/jsimd.h"
#include "../../../src/jdct.h"
#include "../../../src/jsimddct.h"
#include "../../jsimd.h"
#include "../align.h"
#include "../jchuff.h"
@@ -3,7 +3,8 @@
*
* Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
* Copyright (C) 2011, Nokia Corporation and/or its subsidiary(-ies).
* Copyright (C) 2009-2011, 2013-2014, 2016, 2018, 2020, 2022, D. R. Commander.
* Copyright (C) 2009-2011, 2013-2014, 2016, 2018, 2020, 2022, 2024,
* D. R. Commander.
* Copyright (C) 2015-2016, 2018, 2022, Matthieu Darbois.
* Copyright (C) 2020, Arm Limited.
*
@@ -17,11 +18,11 @@
*/
#define JPEG_INTERNALS
#include "../../../jinclude.h"
#include "../../../jpeglib.h"
#include "../../../jsimd.h"
#include "../../../jdct.h"
#include "../../../jsimddct.h"
#include "../../../src/jinclude.h"
#include "../../../src/jpeglib.h"
#include "../../../src/jsimd.h"
#include "../../../src/jdct.h"
#include "../../../src/jsimddct.h"
#include "../../jsimd.h"
#include <ctype.h>
@@ -2,7 +2,7 @@
* jccolor-neon.c - colorspace conversion (Arm Neon)
*
* Copyright (C) 2020, Arm Limited. All Rights Reserved.
* Copyright (C) 2020, D. R. Commander. All Rights Reserved.
* Copyright (C) 2020, 2024, D. R. Commander. All Rights Reserved.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -22,11 +22,11 @@
*/
#define JPEG_INTERNALS
#include "../../jinclude.h"
#include "../../jpeglib.h"
#include "../../jsimd.h"
#include "../../jdct.h"
#include "../../jsimddct.h"
#include "../../src/jinclude.h"
#include "../../src/jpeglib.h"
#include "../../src/jsimd.h"
#include "../../src/jdct.h"
#include "../../src/jsimddct.h"
#include "../jsimd.h"
#include "align.h"
#include "neon-compat.h"
@@ -2,6 +2,7 @@
* jcgray-neon.c - grayscale colorspace conversion (Arm Neon)
*
* Copyright (C) 2020, Arm Limited. All Rights Reserved.
* Copyright (C) 2024, D. R. Commander. All Rights Reserved.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -21,13 +22,14 @@
*/
#define JPEG_INTERNALS
#include "../../jinclude.h"
#include "../../jpeglib.h"
#include "../../jsimd.h"
#include "../../jdct.h"
#include "../../jsimddct.h"
#include "../../src/jinclude.h"
#include "../../src/jpeglib.h"
#include "../../src/jsimd.h"
#include "../../src/jdct.h"
#include "../../src/jsimddct.h"
#include "../jsimd.h"
#include "align.h"
#include "neon-compat.h"
#include <arm_neon.h>
@@ -3,7 +3,7 @@
*
* Copyright (C) 2020-2021, Arm Limited. All Rights Reserved.
* Copyright (C) 2022, Matthieu Darbois. All Rights Reserved.
* Copyright (C) 2022, D. R. Commander. All Rights Reserved.
* Copyright (C) 2022, 2024, D. R. Commander. All Rights Reserved.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -23,11 +23,11 @@
*/
#define JPEG_INTERNALS
#include "../../jinclude.h"
#include "../../jpeglib.h"
#include "../../jsimd.h"
#include "../../jdct.h"
#include "../../jsimddct.h"
#include "../../src/jinclude.h"
#include "../../src/jpeglib.h"
#include "../../src/jsimd.h"
#include "../../src/jdct.h"
#include "../../src/jsimddct.h"
#include "../jsimd.h"
#include "neon-compat.h"
@@ -2,6 +2,7 @@
* jcsample-neon.c - downsampling (Arm Neon)
*
* Copyright (C) 2020, Arm Limited. All Rights Reserved.
* Copyright (C) 2024, D. R. Commander. All Rights Reserved.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -21,13 +22,14 @@
*/
#define JPEG_INTERNALS
#include "../../jinclude.h"
#include "../../jpeglib.h"
#include "../../jsimd.h"
#include "../../jdct.h"
#include "../../jsimddct.h"
#include "../../src/jinclude.h"
#include "../../src/jpeglib.h"
#include "../../src/jsimd.h"
#include "../../src/jdct.h"
#include "../../src/jsimddct.h"
#include "../jsimd.h"
#include "align.h"
#include "neon-compat.h"
#include <arm_neon.h>
@@ -2,6 +2,7 @@
* jdcolor-neon.c - colorspace conversion (Arm Neon)
*
* Copyright (C) 2020, Arm Limited. All Rights Reserved.
* Copyright (C) 2024, D. R. Commander. All Rights Reserved.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -21,13 +22,14 @@
*/
#define JPEG_INTERNALS
#include "../../jinclude.h"
#include "../../jpeglib.h"
#include "../../jsimd.h"
#include "../../jdct.h"
#include "../../jsimddct.h"
#include "../../src/jinclude.h"
#include "../../src/jpeglib.h"
#include "../../src/jsimd.h"
#include "../../src/jdct.h"
#include "../../src/jsimddct.h"
#include "../jsimd.h"
#include "align.h"
#include "neon-compat.h"
#include <arm_neon.h>
@@ -2,6 +2,7 @@
* jdmerge-neon.c - merged upsampling/color conversion (Arm Neon)
*
* Copyright (C) 2020, Arm Limited. All Rights Reserved.
* Copyright (C) 2024, D. R. Commander. All Rights Reserved.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -21,13 +22,14 @@
*/
#define JPEG_INTERNALS
#include "../../jinclude.h"
#include "../../jpeglib.h"
#include "../../jsimd.h"
#include "../../jdct.h"
#include "../../jsimddct.h"
#include "../../src/jinclude.h"
#include "../../src/jpeglib.h"
#include "../../src/jsimd.h"
#include "../../src/jdct.h"
#include "../../src/jsimddct.h"
#include "../jsimd.h"
#include "align.h"
#include "neon-compat.h"
#include <arm_neon.h>
@@ -2,7 +2,7 @@
* jdsample-neon.c - upsampling (Arm Neon)
*
* Copyright (C) 2020, Arm Limited. All Rights Reserved.
* Copyright (C) 2020, D. R. Commander. All Rights Reserved.
* Copyright (C) 2020, 2024, D. R. Commander. All Rights Reserved.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -22,12 +22,13 @@
*/
#define JPEG_INTERNALS
#include "../../jinclude.h"
#include "../../jpeglib.h"
#include "../../jsimd.h"
#include "../../jdct.h"
#include "../../jsimddct.h"
#include "../../src/jinclude.h"
#include "../../src/jpeglib.h"
#include "../../src/jsimd.h"
#include "../../src/jdct.h"
#include "../../src/jsimddct.h"
#include "../jsimd.h"
#include "neon-compat.h"
#include <arm_neon.h>
@@ -2,6 +2,7 @@
* jfdctfst-neon.c - fast integer FDCT (Arm Neon)
*
* Copyright (C) 2020, Arm Limited. All Rights Reserved.
* Copyright (C) 2024, D. R. Commander. All Rights Reserved.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -21,13 +22,14 @@
*/
#define JPEG_INTERNALS
#include "../../jinclude.h"
#include "../../jpeglib.h"
#include "../../jsimd.h"
#include "../../jdct.h"
#include "../../jsimddct.h"
#include "../../src/jinclude.h"
#include "../../src/jpeglib.h"
#include "../../src/jsimd.h"
#include "../../src/jdct.h"
#include "../../src/jsimddct.h"
#include "../jsimd.h"
#include "align.h"
#include "neon-compat.h"
#include <arm_neon.h>
@@ -2,7 +2,7 @@
* jfdctint-neon.c - accurate integer FDCT (Arm Neon)
*
* Copyright (C) 2020, Arm Limited. All Rights Reserved.
* Copyright (C) 2020, D. R. Commander. All Rights Reserved.
* Copyright (C) 2020, 2024, D. R. Commander. All Rights Reserved.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -22,11 +22,11 @@
*/
#define JPEG_INTERNALS
#include "../../jinclude.h"
#include "../../jpeglib.h"
#include "../../jsimd.h"
#include "../../jdct.h"
#include "../../jsimddct.h"
#include "../../src/jinclude.h"
#include "../../src/jpeglib.h"
#include "../../src/jsimd.h"
#include "../../src/jdct.h"
#include "../../src/jsimddct.h"
#include "../jsimd.h"
#include "align.h"
#include "neon-compat.h"
@@ -2,6 +2,7 @@
* jidctfst-neon.c - fast integer IDCT (Arm Neon)
*
* Copyright (C) 2020, Arm Limited. All Rights Reserved.
* Copyright (C) 2024, D. R. Commander. All Rights Reserved.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -21,13 +22,14 @@
*/
#define JPEG_INTERNALS
#include "../../jinclude.h"
#include "../../jpeglib.h"
#include "../../jsimd.h"
#include "../../jdct.h"
#include "../../jsimddct.h"
#include "../../src/jinclude.h"
#include "../../src/jpeglib.h"
#include "../../src/jsimd.h"
#include "../../src/jdct.h"
#include "../../src/jsimddct.h"
#include "../jsimd.h"
#include "align.h"
#include "neon-compat.h"
#include <arm_neon.h>
@@ -2,7 +2,7 @@
* jidctint-neon.c - accurate integer IDCT (Arm Neon)
*
* Copyright (C) 2020, Arm Limited. All Rights Reserved.
* Copyright (C) 2020, D. R. Commander. All Rights Reserved.
* Copyright (C) 2020, 2024, D. R. Commander. All Rights Reserved.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -22,11 +22,11 @@
*/
#define JPEG_INTERNALS
#include "../../jinclude.h"
#include "../../jpeglib.h"
#include "../../jsimd.h"
#include "../../jdct.h"
#include "../../jsimddct.h"
#include "../../src/jinclude.h"
#include "../../src/jpeglib.h"
#include "../../src/jsimd.h"
#include "../../src/jdct.h"
#include "../../src/jsimddct.h"
#include "../jsimd.h"
#include "align.h"
#include "neon-compat.h"
@@ -2,7 +2,7 @@
* jidctred-neon.c - reduced-size IDCT (Arm Neon)
*
* Copyright (C) 2020, Arm Limited. All Rights Reserved.
* Copyright (C) 2020, D. R. Commander. All Rights Reserved.
* Copyright (C) 2020, 2024, D. R. Commander. All Rights Reserved.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -22,11 +22,11 @@
*/
#define JPEG_INTERNALS
#include "../../jinclude.h"
#include "../../jpeglib.h"
#include "../../jsimd.h"
#include "../../jdct.h"
#include "../../jsimddct.h"
#include "../../src/jinclude.h"
#include "../../src/jpeglib.h"
#include "../../src/jsimd.h"
#include "../../src/jdct.h"
#include "../../src/jsimddct.h"
#include "../jsimd.h"
#include "align.h"
#include "neon-compat.h"
@@ -2,6 +2,7 @@
* jquanti-neon.c - sample data conversion and quantization (Arm Neon)
*
* Copyright (C) 2020-2021, Arm Limited. All Rights Reserved.
* Copyright (C) 2024, D. R. Commander. All Rights Reserved.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -21,12 +22,13 @@
*/
#define JPEG_INTERNALS
#include "../../jinclude.h"
#include "../../jpeglib.h"
#include "../../jsimd.h"
#include "../../jdct.h"
#include "../../jsimddct.h"
#include "../../src/jinclude.h"
#include "../../src/jpeglib.h"
#include "../../src/jsimd.h"
#include "../../src/jdct.h"
#include "../../src/jsimddct.h"
#include "../jsimd.h"
#include "neon-compat.h"
#include <arm_neon.h>
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2020, D. R. Commander. All Rights Reserved.
* Copyright (C) 2020, 2024, D. R. Commander. All Rights Reserved.
* Copyright (C) 2020-2021, Arm Limited. All Rights Reserved.
*
* This software is provided 'as-is', without any express or implied
@@ -35,3 +35,11 @@
#else
#error "Unknown compiler"
#endif
#if defined(__clang__)
#pragma clang diagnostic ignored "-Wdeclaration-after-statement"
#pragma clang diagnostic ignored "-Wc99-extensions"
#elif defined(__GNUC__)
#pragma GCC diagnostic ignored "-Wdeclaration-after-statement"
#pragma GCC diagnostic ignored "-Wpedantic"
#endif
@@ -8,11 +8,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
%include "jcolsamp.inc"
@@ -8,11 +8,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
%include "jcolsamp.inc"
@@ -7,11 +7,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
%include "jcolsamp.inc"
@@ -8,11 +8,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
%include "jsimdext.inc"
@@ -8,11 +8,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
%include "jsimdext.inc"
@@ -7,11 +7,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
%include "jsimdext.inc"
@@ -8,11 +8,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
%include "jsimdext.inc"
@@ -8,11 +8,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
%include "jsimdext.inc"
@@ -7,11 +7,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
%include "jsimdext.inc"
@@ -8,11 +8,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
%include "jcolsamp.inc"
@@ -8,11 +8,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
%include "jcolsamp.inc"
@@ -7,11 +7,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
%include "jcolsamp.inc"
@@ -9,11 +9,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
;
; This file contains an SSE2 implementation for Huffman coding of one block.
; The following code is based on jchuff.c; see jchuff.c for more details.
@@ -7,11 +7,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
;
; This file contains an SSE2 implementation of data preparation for progressive
; Huffman encoding. See jcphuff.c for more details.
@@ -9,11 +9,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
%include "jsimdext.inc"
@@ -8,11 +8,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
%include "jsimdext.inc"
@@ -8,11 +8,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
%include "jsimdext.inc"
@@ -9,11 +9,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
%include "jcolsamp.inc"
@@ -8,11 +8,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
%include "jcolsamp.inc"
@@ -8,11 +8,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
%include "jcolsamp.inc"
@@ -9,11 +9,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
%include "jsimdext.inc"
@@ -8,11 +8,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
%include "jsimdext.inc"
@@ -8,11 +8,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
%include "jsimdext.inc"
@@ -9,11 +9,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
%include "jsimdext.inc"
@@ -8,11 +8,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
%include "jsimdext.inc"
@@ -8,11 +8,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
%include "jsimdext.inc"
@@ -9,11 +9,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
%include "jcolsamp.inc"
@@ -8,11 +8,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
%include "jcolsamp.inc"
@@ -8,11 +8,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
%include "jcolsamp.inc"
@@ -9,11 +9,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
%include "jsimdext.inc"
@@ -8,11 +8,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
%include "jsimdext.inc"
@@ -8,11 +8,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
%include "jsimdext.inc"
@@ -8,11 +8,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
;
; This file contains a floating-point implementation of the forward DCT
; (Discrete Cosine Transform). The following code is based directly on
@@ -8,11 +8,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
;
; This file contains a floating-point implementation of the forward DCT
; (Discrete Cosine Transform). The following code is based directly on
@@ -8,11 +8,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
;
; This file contains a fast, not so accurate integer implementation of
; the forward DCT (Discrete Cosine Transform). The following code is
@@ -8,11 +8,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
;
; This file contains a fast, not so accurate integer implementation of
; the forward DCT (Discrete Cosine Transform). The following code is
@@ -8,11 +8,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
;
; This file contains a slower but more accurate integer implementation of the
; forward DCT (Discrete Cosine Transform). The following code is based
@@ -8,11 +8,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
;
; This file contains a slower but more accurate integer implementation of the
; forward DCT (Discrete Cosine Transform). The following code is based
@@ -8,11 +8,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
;
; This file contains a slower but more accurate integer implementation of the
; forward DCT (Discrete Cosine Transform). The following code is based
@@ -8,11 +8,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
;
; This file contains a floating-point implementation of the inverse DCT
; (Discrete Cosine Transform). The following code is based directly on
@@ -8,11 +8,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
;
; This file contains a floating-point implementation of the inverse DCT
; (Discrete Cosine Transform). The following code is based directly on
@@ -8,11 +8,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
;
; This file contains a floating-point implementation of the inverse DCT
; (Discrete Cosine Transform). The following code is based directly on
@@ -8,11 +8,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
;
; This file contains a fast, not so accurate integer implementation of
; the inverse DCT (Discrete Cosine Transform). The following code is
@@ -8,11 +8,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
;
; This file contains a fast, not so accurate integer implementation of
; the inverse DCT (Discrete Cosine Transform). The following code is
@@ -8,11 +8,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
;
; This file contains a slower but more accurate integer implementation of the
; inverse DCT (Discrete Cosine Transform). The following code is based
@@ -8,11 +8,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
;
; This file contains a slower but more accurate integer implementation of the
; inverse DCT (Discrete Cosine Transform). The following code is based
@@ -8,11 +8,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
;
; This file contains a slower but more accurate integer implementation of the
; inverse DCT (Discrete Cosine Transform). The following code is based
@@ -8,11 +8,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
;
; This file contains inverse-DCT routines that produce reduced-size
; output: either 4x4 or 2x2 pixels from an 8x8 DCT block.
@@ -8,11 +8,7 @@
; Copyright (C) 1999-2006, MIYASAKA Masaru.
; For conditions of distribution and use, see copyright notice in jsimdext.inc
;
; This file should be assembled with NASM (Netwide Assembler),
; can *not* be assembled with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler).
; NASM is available from http://nasm.sourceforge.net/ or
; http://sourceforge.net/project/showfiles.php?group_id=6208
; This file should be assembled with NASM (Netwide Assembler) or Yasm.
;
; This file contains inverse-DCT routines that produce reduced-size
; output: either 4x4 or 2x2 pixels from an 8x8 DCT block.

Some files were not shown because too many files have changed in this diff Show More