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

Merge pull request #27175 from fengyuentau:4x/hal_rvv/div_recip

HAL: implemented cv_hal_div* and cv_hal_recip* in hal_rvv #27175

### Pull Request Readiness Checklist

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

- [x] I agree to contribute to the project under Apache 2 License.
- [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV
- [x] The PR is proposed to the proper branch
- [ ] There is a reference to the original bug report and related work
- [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable
      Patch to opencv_extra has the same branch name.
- [ ] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
Yuantao Feng
2025-04-07 15:36:19 +08:00
committed by GitHub
parent 0b3155980a
commit 81859255ca
2 changed files with 269 additions and 0 deletions
+1
View File
@@ -46,6 +46,7 @@
#include "hal_rvv_1p0/svd.hpp" // core
#include "hal_rvv_1p0/sqrt.hpp" // core
#include "hal_rvv_1p0/copy_mask.hpp" // core
#include "hal_rvv_1p0/div.hpp" // core
#include "hal_rvv_1p0/moments.hpp" // imgproc
#include "hal_rvv_1p0/filter.hpp" // imgproc
+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.
//
// Copyright (C) 2025, SpaceMIT Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
#ifndef OPENCV_HAL_RVV_DIV_HPP_INCLUDED
#define OPENCV_HAL_RVV_DIV_HPP_INCLUDED
#include <riscv_vector.h>
#include <limits>
namespace cv { namespace cv_hal_rvv { namespace div {
namespace {
inline size_t setvl(int l) { return __riscv_vsetvl_e8m2(l); }
inline vuint8m2_t vle(const uint8_t *p, int vl) { return __riscv_vle8_v_u8m2(p, vl); }
inline vint8m2_t vle(const int8_t *p, int vl) { return __riscv_vle8_v_i8m2(p, vl); }
inline vuint16m4_t vle(const uint16_t *p, int vl) { return __riscv_vle16_v_u16m4(p, vl); }
inline vint16m4_t vle(const int16_t *p, int vl) { return __riscv_vle16_v_i16m4(p, vl); }
inline vint32m8_t vle(const int *p, int vl) { return __riscv_vle32_v_i32m8(p, vl); }
inline vfloat32m8_t vle(const float *p, int vl) { return __riscv_vle32_v_f32m8(p, vl); }
inline void vse(uint8_t *p, const vuint8m2_t &v, int vl) { __riscv_vse8(p, v, vl); }
inline void vse(int8_t *p, const vint8m2_t &v, int vl) { __riscv_vse8(p, v, vl); }
inline void vse(uint16_t *p, const vuint16m4_t &v, int vl) { __riscv_vse16(p, v, vl); }
inline void vse(int16_t *p, const vint16m4_t &v, int vl) { __riscv_vse16(p, v, vl); }
inline void vse(int *p, const vint32m8_t &v, int vl) { __riscv_vse32(p, v, vl); }
inline void vse(float *p, const vfloat32m8_t &v, int vl) { __riscv_vse32(p, v, vl); }
inline vuint16m4_t ext(const vuint8m2_t &v, const int vl) { return __riscv_vzext_vf2(v, vl); }
inline vint16m4_t ext(const vint8m2_t &v, const int vl) { return __riscv_vsext_vf2(v, vl); }
inline vuint32m8_t ext(const vuint16m4_t &v, const int vl) { return __riscv_vzext_vf2(v, vl); }
inline vint32m8_t ext(const vint16m4_t &v, const int vl) { return __riscv_vsext_vf2(v, vl); }
inline vuint8m2_t nclip(const vuint16m4_t &v, const int vl) { return __riscv_vnclipu(v, 0, __RISCV_VXRM_RNU, vl); }
inline vint8m2_t nclip(const vint16m4_t &v, const int vl) { return __riscv_vnclip(v, 0, __RISCV_VXRM_RNU, vl); }
inline vuint16m4_t nclip(const vuint32m8_t &v, const int vl) { return __riscv_vnclipu(v, 0, __RISCV_VXRM_RNU, vl); }
inline vint16m4_t nclip(const vint32m8_t &v, const int vl) { return __riscv_vnclip(v, 0, __RISCV_VXRM_RNU, vl); }
template <typename VT> inline
VT div_sat(const VT &v1, const VT &v2, const float scale, const int vl) {
return nclip(div_sat(ext(v1, vl), ext(v2, vl), scale, vl), vl);
}
template <> inline
vint32m8_t div_sat(const vint32m8_t &v1, const vint32m8_t &v2, const float scale, const int vl) {
auto f1 = __riscv_vfcvt_f(v1, vl);
auto f2 = __riscv_vfcvt_f(v2, vl);
auto res = __riscv_vfmul(f1, __riscv_vfrdiv(f2, scale, vl), vl);
return __riscv_vfcvt_x(res, vl);
}
template <> inline
vuint32m8_t div_sat(const vuint32m8_t &v1, const vuint32m8_t &v2, const float scale, const int vl) {
auto f1 = __riscv_vfcvt_f(v1, vl);
auto f2 = __riscv_vfcvt_f(v2, vl);
auto res = __riscv_vfmul(f1, __riscv_vfrdiv(f2, scale, vl), vl);
return __riscv_vfcvt_xu(res, vl);
}
template <typename VT> inline
VT recip_sat(const VT &v, const float scale, const int vl) {
return nclip(recip_sat(ext(v, vl), scale, vl), vl);
}
template <> inline
vint32m8_t recip_sat(const vint32m8_t &v, const float scale, const int vl) {
auto f = __riscv_vfcvt_f(v, vl);
auto res = __riscv_vfrdiv(f, scale, vl);
return __riscv_vfcvt_x(res, vl);
}
template <> inline
vuint32m8_t recip_sat(const vuint32m8_t &v, const float scale, const int vl) {
auto f = __riscv_vfcvt_f(v, vl);
auto res = __riscv_vfrdiv(f, scale, vl);
return __riscv_vfcvt_xu(res, vl);
}
} // anonymous
#undef cv_hal_div8u
#define cv_hal_div8u cv::cv_hal_rvv::div::div<uint8_t>
#undef cv_hal_div8s
#define cv_hal_div8s cv::cv_hal_rvv::div::div<int8_t>
#undef cv_hal_div16u
#define cv_hal_div16u cv::cv_hal_rvv::div::div<uint16_t>
#undef cv_hal_div16s
#define cv_hal_div16s cv::cv_hal_rvv::div::div<int16_t>
#undef cv_hal_div32s
#define cv_hal_div32s cv::cv_hal_rvv::div::div<int>
#undef cv_hal_div32f
#define cv_hal_div32f cv::cv_hal_rvv::div::div<float>
// #undef cv_hal_div64f
// #define cv_hal_div64f cv::cv_hal_rvv::div::div<double>
template <typename ST> inline
int div(const ST *src1, size_t step1, const ST *src2, size_t step2,
ST *dst, size_t step, int width, int height, float scale) {
if (scale == 0.f ||
(scale * static_cast<float>(std::numeric_limits<ST>::max())) < 1.f &&
(scale * static_cast<float>(std::numeric_limits<ST>::max())) > -1.f) {
for (int h = 0; h < height; h++) {
ST *dst_h = reinterpret_cast<ST*>((uchar*)dst + h * step);
std::memset(dst_h, 0, sizeof(ST) * width);
}
return CV_HAL_ERROR_OK;
}
for (int h = 0; h < height; h++) {
const ST *src1_h = reinterpret_cast<const ST*>((const uchar*)src1 + h * step1);
const ST *src2_h = reinterpret_cast<const ST*>((const uchar*)src2 + h * step2);
ST *dst_h = reinterpret_cast<ST*>((uchar*)dst + h * step);
int vl;
for (int w = 0; w < width; w += vl) {
vl = setvl(width - w);
auto v1 = vle(src1_h + w, vl);
auto v2 = vle(src2_h + w, vl);
auto mask = __riscv_vmseq(v2, 0, vl);
vse(dst_h + w, __riscv_vmerge(div_sat(v1, v2, scale, vl), 0, mask, vl), vl);
}
}
return CV_HAL_ERROR_OK;
}
template <> inline
int div(const float *src1, size_t step1, const float *src2, size_t step2,
float *dst, size_t step, int width, int height, float scale) {
if (scale == 0.f) {
for (int h = 0; h < height; h++) {
float *dst_h = reinterpret_cast<float*>((uchar*)dst + h * step);
std::memset(dst_h, 0, sizeof(float) * width);
}
return CV_HAL_ERROR_OK;
}
if (std::fabs(scale - 1.f) < FLT_EPSILON) {
for (int h = 0; h < height; h++) {
const float *src1_h = reinterpret_cast<const float*>((const uchar*)src1 + h * step1);
const float *src2_h = reinterpret_cast<const float*>((const uchar*)src2 + h * step2);
float *dst_h = reinterpret_cast<float*>((uchar*)dst + h * step);
int vl;
for (int w = 0; w < width; w += vl) {
vl = setvl(width - w);
auto v1 = vle(src1_h + w, vl);
auto v2 = vle(src2_h + w, vl);
vse(dst_h + w, __riscv_vfmul(v1, __riscv_vfrdiv(v2, 1.f, vl), vl), vl);
}
}
} else {
for (int h = 0; h < height; h++) {
const float *src1_h = reinterpret_cast<const float*>((const uchar*)src1 + h * step1);
const float *src2_h = reinterpret_cast<const float*>((const uchar*)src2 + h * step2);
float *dst_h = reinterpret_cast<float*>((uchar*)dst + h * step);
int vl;
for (int w = 0; w < width; w += vl) {
vl = setvl(width - w);
auto v1 = vle(src1_h + w, vl);
auto v2 = vle(src2_h + w, vl);
vse(dst_h + w, __riscv_vfmul(v1, __riscv_vfrdiv(v2, scale, vl), vl), vl);
}
}
}
return CV_HAL_ERROR_OK;
}
#undef cv_hal_recip8u
#define cv_hal_recip8u cv::cv_hal_rvv::div::recip<uint8_t>
#undef cv_hal_recip8s
#define cv_hal_recip8s cv::cv_hal_rvv::div::recip<int8_t>
#undef cv_hal_recip16u
#define cv_hal_recip16u cv::cv_hal_rvv::div::recip<uint16_t>
#undef cv_hal_recip16s
#define cv_hal_recip16s cv::cv_hal_rvv::div::recip<int16_t>
#undef cv_hal_recip32s
#define cv_hal_recip32s cv::cv_hal_rvv::div::recip<int>
#undef cv_hal_recip32f
#define cv_hal_recip32f cv::cv_hal_rvv::div::recip<float>
// #undef cv_hal_recip64f
// #define cv_hal_recip64f cv::cv_hal_rvv::div::recip<double>
template <typename ST> inline
int recip(const ST *src_data, size_t src_step, ST *dst_data, size_t dst_step,
int width, int height, float scale) {
if (scale == 0.f || scale < 1.f && scale > -1.f) {
for (int h = 0; h < height; h++) {
ST *dst_h = reinterpret_cast<ST*>((uchar*)dst_data + h * dst_step);
std::memset(dst_h, 0, sizeof(ST) * width);
}
return CV_HAL_ERROR_OK;
}
for (int h = 0; h < height; h++) {
const ST *src_h = reinterpret_cast<const ST*>((const uchar*)src_data + h * src_step);
ST *dst_h = reinterpret_cast<ST*>((uchar*)dst_data + h * dst_step);
int vl;
for (int w = 0; w < width; w += vl) {
vl = setvl(width - w);
auto v = vle(src_h + w, vl);
auto mask = __riscv_vmseq(v, 0, vl);
vse(dst_h + w, __riscv_vmerge(recip_sat(v, scale, vl), 0, mask, vl), vl);
}
}
return CV_HAL_ERROR_OK;
}
template <> inline
int recip(const float *src_data, size_t src_step, float *dst_data, size_t dst_step,
int width, int height, float scale) {
if (scale == 0.f) {
for (int h = 0; h < height; h++) {
float *dst_h = reinterpret_cast<float*>((uchar*)dst_data + h * dst_step);
std::memset(dst_h, 0, sizeof(float) * width);
}
return CV_HAL_ERROR_OK;
}
if (std::fabs(scale - 1.f) < FLT_EPSILON) {
for (int h = 0; h < height; h++) {
const float *src_h = reinterpret_cast<const float*>((const uchar*)src_data + h * src_step);
float *dst_h = reinterpret_cast<float*>((uchar*)dst_data + h * dst_step);
int vl;
for (int w = 0; w < width; w += vl) {
vl = setvl(width - w);
auto v = vle(src_h + w, vl);
vse(dst_h + w, __riscv_vfrdiv(v, 1.f, vl), vl);
}
}
} else {
for (int h = 0; h < height; h++) {
const float *src_h = reinterpret_cast<const float*>((const uchar*)src_data + h * src_step);
float *dst_h = reinterpret_cast<float*>((uchar*)dst_data + h * dst_step);
int vl;
for (int w = 0; w < width; w += vl) {
vl = setvl(width - w);
auto v = vle(src_h + w, vl);
vse(dst_h + w, __riscv_vfrdiv(v, scale, vl), vl);
}
}
}
return CV_HAL_ERROR_OK;
}
}}} // cv::cv_hal_rvv::div
#endif // OPENCV_HAL_RVV_DIV_HPP_INCLUDED