mirror of
https://github.com/opencv/opencv.git
synced 2026-07-29 23:33:05 +04:00
Merge pull request #29250 from amd:fast_lut8u_simd
imgproc: optimized LUT and equalizeHist with SIMD #29250 - optimized lut with SIMD - support equalizeHist with v_lut ### 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 - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
committed by
GitHub
parent
d0925fa360
commit
70a2c50b43
@@ -1598,6 +1598,20 @@ inline v_uint8x32 v256_lut(const uchar* tab, const int* idx) { return v_reinterp
|
||||
inline v_uint8x32 v256_lut_pairs(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v256_lut_pairs((const schar *)tab, idx)); }
|
||||
inline v_uint8x32 v256_lut_quads(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v256_lut_quads((const schar *)tab, idx)); }
|
||||
|
||||
inline v_uint8x32 v256_lut(const uchar* tab, const v_uint8x32& idx)
|
||||
{
|
||||
uchar CV_DECL_ALIGNED(32) indices[32], result[32];
|
||||
_mm256_store_si256((__m256i*)indices, idx.val);
|
||||
for (int i = 0; i < 32; i++) result[i] = tab[indices[i]];
|
||||
return v_uint8x32(_mm256_load_si256((const __m256i*)result));
|
||||
}
|
||||
inline v_int8x32 v256_lut(const schar* tab, const v_uint8x32& idx)
|
||||
{ return v_reinterpret_as_s8(v256_lut((const uchar *)tab, idx)); }
|
||||
|
||||
|
||||
inline v_uint8x32 v_lut(const uchar* tab, const v_uint8x32& idx) { return v256_lut(tab, idx); }
|
||||
inline v_int8x32 v_lut(const schar* tab, const v_uint8x32& idx) { return v256_lut(tab, idx); }
|
||||
|
||||
inline v_int16x16 v256_lut(const short* tab, const int* idx)
|
||||
{
|
||||
return v_int16x16(_mm256_setr_epi16(tab[idx[0]], tab[idx[1]], tab[idx[ 2]], tab[idx[ 3]], tab[idx[ 4]], tab[idx[ 5]], tab[idx[ 6]], tab[idx[ 7]],
|
||||
|
||||
@@ -1634,6 +1634,122 @@ inline v_uint8x64 v512_lut(const uchar* tab, const int* idx) { return v_reinterp
|
||||
inline v_uint8x64 v512_lut_pairs(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v512_lut_pairs((const schar *)tab, idx)); }
|
||||
inline v_uint8x64 v512_lut_quads(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v512_lut_quads((const schar *)tab, idx)); }
|
||||
|
||||
// Byte-indexed LUT: takes v_uint8x64 byte indices instead of int* indices
|
||||
// Table must have at least 256 entries (byte indices cover 0-255)
|
||||
// VBMI path uses vpermb (register-to-register), fallback uses gather
|
||||
inline v_uint8x64 v512_lut(const uchar* tab, const v_uint8x64& idx)
|
||||
{
|
||||
#if CV_AVX_512VBMI
|
||||
const __m512i lut0 = _mm512_loadu_si512(tab);
|
||||
const __m512i lut1 = _mm512_loadu_si512(tab + 64);
|
||||
const __m512i lut2 = _mm512_loadu_si512(tab + 128);
|
||||
const __m512i lut3 = _mm512_loadu_si512(tab + 192);
|
||||
|
||||
__m512i idx6 = _mm512_and_si512(idx.val, _mm512_set1_epi8(0x3F));
|
||||
|
||||
__m512i r0 = _mm512_permutexvar_epi8(idx6, lut0);
|
||||
__m512i r1 = _mm512_permutexvar_epi8(idx6, lut1);
|
||||
__m512i r2 = _mm512_permutexvar_epi8(idx6, lut2);
|
||||
__m512i r3 = _mm512_permutexvar_epi8(idx6, lut3);
|
||||
|
||||
__mmask64 k6 = _mm512_test_epi8_mask(idx.val, _mm512_set1_epi8(0x40));
|
||||
__mmask64 k7 = _mm512_test_epi8_mask(idx.val, _mm512_set1_epi8((char)0x80));
|
||||
|
||||
__m512i low = _mm512_mask_blend_epi8(k6, r0, r1);
|
||||
__m512i high = _mm512_mask_blend_epi8(k6, r2, r3);
|
||||
return v_uint8x64(_mm512_mask_blend_epi8(k7, low, high));
|
||||
#else
|
||||
uchar CV_DECL_ALIGNED(64) indices[64], result[64];
|
||||
_mm512_store_si512((__m512i*)indices, idx.val);
|
||||
for (int i = 0; i < 64; i++) result[i] = tab[indices[i]];
|
||||
return v_uint8x64(_mm512_load_si512((const __m512i*)result));
|
||||
#endif
|
||||
}
|
||||
inline v_int8x64 v512_lut(const schar* tab, const v_uint8x64& idx)
|
||||
{ return v_reinterpret_as_s8(v512_lut((const uchar *)tab, idx)); }
|
||||
|
||||
// Universal v_lut overloads for vector byte indices (aliases to v512_lut)
|
||||
inline v_uint8x64 v_lut(const uchar* tab, const v_uint8x64& idx)
|
||||
{ return v512_lut(tab, idx); }
|
||||
|
||||
inline v_int8x64 v_lut(const schar* tab, const v_uint8x64& idx)
|
||||
{ return v512_lut(tab, idx); }
|
||||
|
||||
// Byte-indexed pair LUT: 32 byte indices (lower half of idx) → 32 pairs = 64 bytes
|
||||
inline v_uint8x64 v512_lut_pairs(const uchar* tab, const v_uint8x64& idx)
|
||||
{
|
||||
#if CV_AVX_512VBMI
|
||||
const __m512i lut0 = _mm512_loadu_si512(tab);
|
||||
const __m512i lut1 = _mm512_loadu_si512(tab + 64);
|
||||
const __m512i lut2 = _mm512_loadu_si512(tab + 128);
|
||||
const __m512i lut3 = _mm512_loadu_si512(tab + 192);
|
||||
|
||||
// Expand 32 byte indices to interleaved pairs: (i0, i0+1, i1, i1+1, ...)
|
||||
__m512i idx16 = _mm512_cvtepu8_epi16(_mm512_castsi512_si256(idx.val));
|
||||
__m512i idx_dup = _mm512_or_si512(idx16, _mm512_slli_epi16(idx16, 8));
|
||||
__m512i idx_pairs = _mm512_add_epi8(idx_dup, _mm512_set1_epi16(0x0100));
|
||||
|
||||
__m512i idx6 = _mm512_and_si512(idx_pairs, _mm512_set1_epi8(0x3F));
|
||||
|
||||
__m512i r0 = _mm512_permutexvar_epi8(idx6, lut0);
|
||||
__m512i r1 = _mm512_permutexvar_epi8(idx6, lut1);
|
||||
__m512i r2 = _mm512_permutexvar_epi8(idx6, lut2);
|
||||
__m512i r3 = _mm512_permutexvar_epi8(idx6, lut3);
|
||||
|
||||
__mmask64 k6 = _mm512_test_epi8_mask(idx_pairs, _mm512_set1_epi8(0x40));
|
||||
__mmask64 k7 = _mm512_test_epi8_mask(idx_pairs, _mm512_set1_epi8((char)0x80));
|
||||
|
||||
__m512i low = _mm512_mask_blend_epi8(k6, r0, r1);
|
||||
__m512i high = _mm512_mask_blend_epi8(k6, r2, r3);
|
||||
return v_uint8x64(_mm512_mask_blend_epi8(k7, low, high));
|
||||
#else
|
||||
uchar CV_DECL_ALIGNED(64) indices[64], result[64];
|
||||
_mm512_store_si512((__m512i*)indices, idx.val);
|
||||
for (int i = 0; i < 64; i++) result[i] = tab[indices[i]];
|
||||
return v_uint8x64(_mm512_load_si512((const __m512i*)result));
|
||||
#endif
|
||||
}
|
||||
inline v_int8x64 v512_lut_pairs(const schar* tab, const v_uint8x64& idx)
|
||||
{ return v_reinterpret_as_s8(v512_lut_pairs((const uchar *)tab, idx)); }
|
||||
|
||||
// Byte-indexed quad LUT: 16 byte indices (lower 16 of idx) → 16 quads = 64 bytes
|
||||
inline v_uint8x64 v512_lut_quads(const uchar* tab, const v_uint8x64& idx)
|
||||
{
|
||||
#if CV_AVX_512VBMI
|
||||
const __m512i lut0 = _mm512_loadu_si512(tab);
|
||||
const __m512i lut1 = _mm512_loadu_si512(tab + 64);
|
||||
const __m512i lut2 = _mm512_loadu_si512(tab + 128);
|
||||
const __m512i lut3 = _mm512_loadu_si512(tab + 192);
|
||||
|
||||
// Expand 16 byte indices to quad offsets: (i0, i0+1, i0+2, i0+3, i1, ...)
|
||||
__m512i idx32 = _mm512_cvtepu8_epi32(_mm512_castsi512_si128(idx.val));
|
||||
__m512i t1 = _mm512_or_si512(idx32, _mm512_slli_epi32(idx32, 8));
|
||||
__m512i idx_bcast = _mm512_or_si512(t1, _mm512_slli_epi32(t1, 16));
|
||||
__m512i idx_quads = _mm512_add_epi8(idx_bcast, _mm512_set1_epi32(0x03020100));
|
||||
|
||||
__m512i idx6 = _mm512_and_si512(idx_quads, _mm512_set1_epi8(0x3F));
|
||||
|
||||
__m512i r0 = _mm512_permutexvar_epi8(idx6, lut0);
|
||||
__m512i r1 = _mm512_permutexvar_epi8(idx6, lut1);
|
||||
__m512i r2 = _mm512_permutexvar_epi8(idx6, lut2);
|
||||
__m512i r3 = _mm512_permutexvar_epi8(idx6, lut3);
|
||||
|
||||
__mmask64 k6 = _mm512_test_epi8_mask(idx_quads, _mm512_set1_epi8(0x40));
|
||||
__mmask64 k7 = _mm512_test_epi8_mask(idx_quads, _mm512_set1_epi8((char)0x80));
|
||||
|
||||
__m512i low = _mm512_mask_blend_epi8(k6, r0, r1);
|
||||
__m512i high = _mm512_mask_blend_epi8(k6, r2, r3);
|
||||
return v_uint8x64(_mm512_mask_blend_epi8(k7, low, high));
|
||||
#else
|
||||
uchar CV_DECL_ALIGNED(64) indices[64], result[64];
|
||||
_mm512_store_si512((__m512i*)indices, idx.val);
|
||||
for (int i = 0; i < 64; i++) result[i] = tab[indices[i]];
|
||||
return v_uint8x64(_mm512_load_si512((const __m512i*)result));
|
||||
#endif
|
||||
}
|
||||
inline v_int8x64 v512_lut_quads(const schar* tab, const v_uint8x64& idx)
|
||||
{ return v_reinterpret_as_s8(v512_lut_quads((const uchar *)tab, idx)); }
|
||||
|
||||
inline v_int16x32 v512_lut(const short* tab, const int* idx)
|
||||
{
|
||||
__m256i p0 = _mm512_cvtepi32_epi16(_mm512_i32gather_epi32(_mm512_loadu_si512((const __m512i*)idx ), (const int *)tab, 2));
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Copyright (C) 2015, Itseez Inc., all rights reserved.
|
||||
// Copyright (C) 2026, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
@@ -2714,6 +2715,16 @@ template<typename _Tp> inline v_reg<_Tp, simd128_width / sizeof(_Tp)> v_lut_quad
|
||||
return c;
|
||||
}
|
||||
|
||||
template<int n> inline v_reg<uchar, n> v_lut(const uchar* tab, const v_reg<uchar, n>& idx)
|
||||
{
|
||||
v_reg<uchar, n> c;
|
||||
for( int i = 0; i < n; i++ )
|
||||
c.s[i] = tab[idx.s[i]];
|
||||
return c;
|
||||
}
|
||||
template<int n> inline v_reg<schar, n> v_lut(const schar* tab, const v_reg<uchar, n>& idx)
|
||||
{ return v_reinterpret_as_s8(v_lut((const uchar*)tab, idx)); }
|
||||
|
||||
template<int n> inline v_reg<int, n> v_lut(const int* tab, const v_reg<int, n>& idx)
|
||||
{
|
||||
v_reg<int, n> c;
|
||||
|
||||
@@ -1673,6 +1673,21 @@ inline v_uint8x32 v256_lut(const uchar* tab, const int* idx) { return v_reinterp
|
||||
inline v_uint8x32 v256_lut_pairs(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v256_lut_pairs((const schar *)tab, idx)); }
|
||||
inline v_uint8x32 v256_lut_quads(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v256_lut_quads((const schar *)tab, idx)); }
|
||||
|
||||
// Byte-indexed LUT: 32 byte indices in a vector -> 32 looked-up bytes
|
||||
inline v_uint8x32 v256_lut(const uchar* tab, const v_uint8x32& idx)
|
||||
{
|
||||
uchar CV_DECL_ALIGNED(32) indices[32], result[32];
|
||||
__lasx_xvst(idx.val, indices, 0);
|
||||
for (int i = 0; i < 32; i++) result[i] = tab[indices[i]];
|
||||
return v_uint8x32(__lasx_xvld(result, 0));
|
||||
}
|
||||
inline v_int8x32 v256_lut(const schar* tab, const v_uint8x32& idx)
|
||||
{ return v_reinterpret_as_s8(v256_lut((const uchar*)tab, idx)); }
|
||||
|
||||
// Universal v_lut overloads for vector byte indices (aliases to v256_lut)
|
||||
inline v_uint8x32 v_lut(const uchar* tab, const v_uint8x32& idx) { return v256_lut(tab, idx); }
|
||||
inline v_int8x32 v_lut(const schar* tab, const v_uint8x32& idx) { return v256_lut(tab, idx); }
|
||||
|
||||
inline v_int16x16 v256_lut(const short* tab, const int* idx)
|
||||
{
|
||||
return v_int16x16(_v256_setr_h(tab[idx[ 0]], tab[idx[ 1]], tab[idx[ 2]], tab[idx[ 3]], tab[idx[ 4]],
|
||||
|
||||
@@ -1443,6 +1443,16 @@ inline v_uint8x16 v_lut_pairs(const uchar* tab, const int* idx)
|
||||
inline v_uint8x16 v_lut_quads(const uchar* tab, const int* idx)
|
||||
{ return v_reinterpret_as_u8(v_lut_quads((const schar*)tab, idx)); }
|
||||
|
||||
inline v_uint8x16 v_lut(const uchar* tab, const v_uint8x16& idx)
|
||||
{
|
||||
uchar CV_DECL_ALIGNED(16) indices[16], result[16];
|
||||
__lsx_vst(idx.val, indices, 0);
|
||||
for (int i = 0; i < 16; i++) result[i] = tab[indices[i]];
|
||||
return v_uint8x16(__lsx_vld(result, 0));
|
||||
}
|
||||
inline v_int8x16 v_lut(const schar* tab, const v_uint8x16& idx)
|
||||
{ return v_reinterpret_as_s8(v_lut((const uchar*)tab, idx)); }
|
||||
|
||||
inline v_int16x8 v_lut(const short* tab, const int* idx)
|
||||
{
|
||||
return v_int16x8(_v128_setr_h(tab[idx[0]], tab[idx[1]], tab[idx[2]], tab[idx[3]],
|
||||
|
||||
@@ -1566,6 +1566,15 @@ inline v_uint8x16 v_lut(const uchar* tab, const int* idx) { return v_reinterpret
|
||||
inline v_uint8x16 v_lut_pairs(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut_pairs((schar*)tab, idx)); }
|
||||
inline v_uint8x16 v_lut_quads(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut_quads((schar*)tab, idx)); }
|
||||
|
||||
inline v_uint8x16 v_lut(const uchar* tab, const v_uint8x16& idx)
|
||||
{
|
||||
uchar CV_DECL_ALIGNED(16) indices[16], result[16];
|
||||
msa_st1q_u8(indices, idx.val);
|
||||
for (int i = 0; i < 16; i++) result[i] = tab[indices[i]];
|
||||
return v_uint8x16(msa_ld1q_u8(result));
|
||||
}
|
||||
inline v_int8x16 v_lut(const schar* tab, const v_uint8x16& idx)
|
||||
{ return v_reinterpret_as_s8(v_lut((const uchar*)tab, idx)); }
|
||||
|
||||
inline v_int16x8 v_lut(const short* tab, const int* idx)
|
||||
{
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Copyright (C) 2015, Itseez Inc., all rights reserved.
|
||||
// Copyright (C) 2026, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
@@ -2370,6 +2371,48 @@ inline v_uint8x16 v_lut(const uchar* tab, const int* idx) { return v_reinterpret
|
||||
inline v_uint8x16 v_lut_pairs(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut_pairs((schar*)tab, idx)); }
|
||||
inline v_uint8x16 v_lut_quads(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut_quads((schar*)tab, idx)); }
|
||||
|
||||
inline v_uint8x16 v_lut(const uchar* tab, const v_uint8x16& idx)
|
||||
{
|
||||
#if CV_NEON_AARCH64
|
||||
uint8x16_t index = idx.val;
|
||||
uint8x16_t idx6 = vandq_u8(index, vdupq_n_u8(0x3F));
|
||||
|
||||
uint8x16x4_t t0, t1, t2, t3;
|
||||
t0.val[0] = vld1q_u8(tab); t0.val[1] = vld1q_u8(tab + 16);
|
||||
t0.val[2] = vld1q_u8(tab + 32); t0.val[3] = vld1q_u8(tab + 48);
|
||||
uint8x16_t r0 = vqtbl4q_u8(t0, idx6);
|
||||
|
||||
t1.val[0] = vld1q_u8(tab + 64); t1.val[1] = vld1q_u8(tab + 80);
|
||||
t1.val[2] = vld1q_u8(tab + 96); t1.val[3] = vld1q_u8(tab + 112);
|
||||
uint8x16_t r1 = vqtbl4q_u8(t1, idx6);
|
||||
|
||||
t2.val[0] = vld1q_u8(tab + 128); t2.val[1] = vld1q_u8(tab + 144);
|
||||
t2.val[2] = vld1q_u8(tab + 160); t2.val[3] = vld1q_u8(tab + 176);
|
||||
uint8x16_t r2 = vqtbl4q_u8(t2, idx6);
|
||||
|
||||
t3.val[0] = vld1q_u8(tab + 192); t3.val[1] = vld1q_u8(tab + 208);
|
||||
t3.val[2] = vld1q_u8(tab + 224); t3.val[3] = vld1q_u8(tab + 240);
|
||||
uint8x16_t r3 = vqtbl4q_u8(t3, idx6);
|
||||
|
||||
uint8x16_t bit6 = vtstq_u8(index, vdupq_n_u8(0x40));
|
||||
uint8x16_t low = vbslq_u8(bit6, r1, r0);
|
||||
uint8x16_t high = vbslq_u8(bit6, r3, r2);
|
||||
|
||||
uint8x16_t bit7 = vtstq_u8(index, vdupq_n_u8(0x80));
|
||||
return v_uint8x16(vbslq_u8(bit7, high, low));
|
||||
#else
|
||||
uchar CV_DECL_ALIGNED(16) indices[16], result[16];
|
||||
vst1q_u8(indices, idx.val);
|
||||
for (int i = 0; i < 16; i++) result[i] = tab[indices[i]];
|
||||
return v_uint8x16(vld1q_u8(result));
|
||||
#endif
|
||||
}
|
||||
|
||||
inline v_int8x16 v_lut(const schar* tab, const v_uint8x16& idx)
|
||||
{
|
||||
return v_reinterpret_as_s8(v_lut((const uchar*)tab, idx));
|
||||
}
|
||||
|
||||
inline v_int16x8 v_lut(const short* tab, const int* idx)
|
||||
{
|
||||
short CV_DECL_ALIGNED(32) elems[8] =
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// of this distribution and at http://opencv.org/license.html
|
||||
|
||||
// Copyright (C) 2015, PingTouGe Semiconductor Co., Ltd., all rights reserved.
|
||||
// Copyright (C) 2026, Advanced Micro Devices, Inc., all rights reserved.
|
||||
|
||||
#ifndef OPENCV_HAL_INTRIN_RISCVV_HPP
|
||||
#define OPENCV_HAL_INTRIN_RISCVV_HPP
|
||||
@@ -1625,6 +1626,16 @@ inline v_uint8x16 v_lut(const uchar* tab, const int* idx) { return v_reinterpret
|
||||
inline v_uint8x16 v_lut_pairs(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut_pairs((schar*)tab, idx)); }
|
||||
inline v_uint8x16 v_lut_quads(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut_quads((schar*)tab, idx)); }
|
||||
|
||||
inline v_uint8x16 v_lut(const uchar* tab, const v_uint8x16& idx)
|
||||
{
|
||||
uchar CV_DECL_ALIGNED(16) indices[16], result[16];
|
||||
vse8_v_u8m1(indices, idx.val, 16);
|
||||
for (int i = 0; i < 16; i++) result[i] = tab[indices[i]];
|
||||
return v_uint8x16(vle8_v_u8m1(result, 16));
|
||||
}
|
||||
inline v_int8x16 v_lut(const schar* tab, const v_uint8x16& idx)
|
||||
{ return v_reinterpret_as_s8(v_lut((const uchar*)tab, idx)); }
|
||||
|
||||
inline v_int16x8 v_lut(const short* tab, const int* idx)
|
||||
{
|
||||
#if 0
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
// The original implementation is contributed by HAN Liutong.
|
||||
// Copyright (C) 2022, Institute of Software, Chinese Academy of Sciences.
|
||||
// Copyright (C) 2026, Advanced Micro Devices, Inc., all rights reserved.
|
||||
|
||||
#ifndef OPENCV_HAL_INTRIN_RVV_SCALABLE_HPP
|
||||
#define OPENCV_HAL_INTRIN_RVV_SCALABLE_HPP
|
||||
@@ -534,6 +535,13 @@ inline void v_lut_deinterleave(const double* tab, const v_int32& vidx, v_float64
|
||||
inline v_uint8 v_lut(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut((schar*)tab, idx)); }
|
||||
inline v_uint8 v_lut_pairs(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut_pairs((schar*)tab, idx)); }
|
||||
inline v_uint8 v_lut_quads(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut_quads((schar*)tab, idx)); }
|
||||
|
||||
// Byte-indexed LUT: vector byte indices -> looked-up bytes (uses RVV indexed load)
|
||||
inline v_uint8 v_lut(const uchar* tab, const v_uint8& idx)
|
||||
{ return __riscv_vluxei8_v_u8m2(tab, idx, VTraits<v_uint8>::vlanes()); }
|
||||
inline v_int8 v_lut(const schar* tab, const v_uint8& idx)
|
||||
{ return v_reinterpret_as_s8(v_lut((const uchar*)tab, idx)); }
|
||||
|
||||
inline v_uint16 v_lut(const ushort* tab, const int* idx) { return v_reinterpret_as_u16(v_lut((short*)tab, idx)); }
|
||||
inline v_uint16 v_lut_pairs(const ushort* tab, const int* idx) { return v_reinterpret_as_u16(v_lut_pairs((short*)tab, idx)); }
|
||||
inline v_uint16 v_lut_quads(const ushort* tab, const int* idx) { return v_reinterpret_as_u16(v_lut_quads((short*)tab, idx)); }
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Copyright (C) 2015, Itseez Inc., all rights reserved.
|
||||
// Copyright (C) 2026, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
@@ -3084,6 +3085,16 @@ inline v_uint8x16 v_lut(const uchar* tab, const int* idx) { return v_reinterpret
|
||||
inline v_uint8x16 v_lut_pairs(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut_pairs((const schar *)tab, idx)); }
|
||||
inline v_uint8x16 v_lut_quads(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut_quads((const schar *)tab, idx)); }
|
||||
|
||||
inline v_uint8x16 v_lut(const uchar* tab, const v_uint8x16& idx)
|
||||
{
|
||||
uchar CV_DECL_ALIGNED(16) indices[16], result[16];
|
||||
_mm_store_si128((__m128i*)indices, idx.val);
|
||||
for (int i = 0; i < 16; i++) result[i] = tab[indices[i]];
|
||||
return v_uint8x16(_mm_load_si128((const __m128i*)result));
|
||||
}
|
||||
inline v_int8x16 v_lut(const schar* tab, const v_uint8x16& idx)
|
||||
{ return v_reinterpret_as_s8(v_lut((const uchar*)tab, idx)); }
|
||||
|
||||
inline v_int16x8 v_lut(const short* tab, const int* idx)
|
||||
{
|
||||
return v_int16x8(tab[idx[0]], tab[idx[1]], tab[idx[2]], tab[idx[3]],
|
||||
|
||||
@@ -1175,6 +1175,16 @@ inline v_uint8x16 v_lut(const uchar* tab, const int* idx) { return v_reinterpret
|
||||
inline v_uint8x16 v_lut_pairs(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut_pairs((const schar*)tab, idx)); }
|
||||
inline v_uint8x16 v_lut_quads(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut_quads((const schar*)tab, idx)); }
|
||||
|
||||
inline v_uint8x16 v_lut(const uchar* tab, const v_uint8x16& idx)
|
||||
{
|
||||
uchar CV_DECL_ALIGNED(16) indices[16], result[16];
|
||||
vsx_st(idx.val, 0, indices);
|
||||
for (int i = 0; i < 16; i++) result[i] = tab[indices[i]];
|
||||
return v_uint8x16(vsx_ld(0, result));
|
||||
}
|
||||
inline v_int8x16 v_lut(const schar* tab, const v_uint8x16& idx)
|
||||
{ return v_reinterpret_as_s8(v_lut((const uchar*)tab, idx)); }
|
||||
|
||||
inline v_int16x8 v_lut(const short* tab, const int* idx)
|
||||
{
|
||||
return v_int16x8(tab[idx[0]], tab[idx[1]], tab[idx[2]], tab[idx[3]], tab[idx[4]], tab[idx[5]], tab[idx[6]], tab[idx[7]]);
|
||||
|
||||
@@ -2584,6 +2584,16 @@ inline v_uint8x16 v_lut(const uchar* tab, const int* idx) { return v_reinterpret
|
||||
inline v_uint8x16 v_lut_pairs(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut_pairs((const schar *)tab, idx)); }
|
||||
inline v_uint8x16 v_lut_quads(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut_quads((const schar *)tab, idx)); }
|
||||
|
||||
inline v_uint8x16 v_lut(const uchar* tab, const v_uint8x16& idx)
|
||||
{
|
||||
uchar CV_DECL_ALIGNED(16) indices[16], result[16];
|
||||
wasm_v128_store(indices, idx.val);
|
||||
for (int i = 0; i < 16; i++) result[i] = tab[indices[i]];
|
||||
return v_uint8x16(wasm_v128_load(result));
|
||||
}
|
||||
inline v_int8x16 v_lut(const schar* tab, const v_uint8x16& idx)
|
||||
{ return v_reinterpret_as_s8(v_lut((const uchar*)tab, idx)); }
|
||||
|
||||
inline v_int16x8 v_lut(const short* tab, const int* idx)
|
||||
{
|
||||
return v_int16x8(tab[idx[0]], tab[idx[1]], tab[idx[2]], tab[idx[3]],
|
||||
|
||||
Reference in New Issue
Block a user