Skip to content

Commit 6c13526

Browse files
committed
Universal Intrinsics: aligned v_pack behavior on different platforms, fixed 64-bit register on ARM, added more saturate_cast variants
1 parent c4b158f commit 6c13526

File tree

5 files changed

+122
-81
lines changed

5 files changed

+122
-81
lines changed

modules/core/include/opencv2/core/hal/intrin_cpp.hpp

Lines changed: 51 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1762,14 +1762,14 @@ OPENCV_HAL_IMPL_C_RSHIFTR(v_int64x2, int64)
17621762

17631763
//! @brief Helper macro
17641764
//! @ingroup core_hal_intrin_impl
1765-
#define OPENCV_HAL_IMPL_C_PACK(_Tpvec, _Tpnvec, _Tpn, pack_suffix) \
1765+
#define OPENCV_HAL_IMPL_C_PACK(_Tpvec, _Tpnvec, _Tpn, pack_suffix, cast) \
17661766
inline _Tpnvec v_##pack_suffix(const _Tpvec& a, const _Tpvec& b) \
17671767
{ \
17681768
_Tpnvec c; \
17691769
for( int i = 0; i < _Tpvec::nlanes; i++ ) \
17701770
{ \
1771-
c.s[i] = saturate_cast<_Tpn>(a.s[i]); \
1772-
c.s[i+_Tpvec::nlanes] = saturate_cast<_Tpn>(b.s[i]); \
1771+
c.s[i] = cast<_Tpn>(a.s[i]); \
1772+
c.s[i+_Tpvec::nlanes] = cast<_Tpn>(b.s[i]); \
17731773
} \
17741774
return c; \
17751775
}
@@ -1783,26 +1783,28 @@ inline _Tpnvec v_##pack_suffix(const _Tpvec& a, const _Tpvec& b) \
17831783
//!
17841784
//! - pack: for 16-, 32- and 64-bit integer input types
17851785
//! - pack_u: for 16- and 32-bit signed integer input types
1786-
OPENCV_HAL_IMPL_C_PACK(v_uint16x8, v_uint8x16, uchar, pack)
1787-
OPENCV_HAL_IMPL_C_PACK(v_int16x8, v_int8x16, schar, pack)
1788-
OPENCV_HAL_IMPL_C_PACK(v_uint32x4, v_uint16x8, ushort, pack)
1789-
OPENCV_HAL_IMPL_C_PACK(v_int32x4, v_int16x8, short, pack)
1790-
OPENCV_HAL_IMPL_C_PACK(v_uint64x2, v_uint32x4, unsigned, pack)
1791-
OPENCV_HAL_IMPL_C_PACK(v_int64x2, v_int32x4, int, pack)
1792-
OPENCV_HAL_IMPL_C_PACK(v_int16x8, v_uint8x16, uchar, pack_u)
1793-
OPENCV_HAL_IMPL_C_PACK(v_int32x4, v_uint16x8, ushort, pack_u)
1786+
//!
1787+
//! @note All variants except 64-bit use saturation.
1788+
OPENCV_HAL_IMPL_C_PACK(v_uint16x8, v_uint8x16, uchar, pack, saturate_cast)
1789+
OPENCV_HAL_IMPL_C_PACK(v_int16x8, v_int8x16, schar, pack, saturate_cast)
1790+
OPENCV_HAL_IMPL_C_PACK(v_uint32x4, v_uint16x8, ushort, pack, saturate_cast)
1791+
OPENCV_HAL_IMPL_C_PACK(v_int32x4, v_int16x8, short, pack, saturate_cast)
1792+
OPENCV_HAL_IMPL_C_PACK(v_uint64x2, v_uint32x4, unsigned, pack, static_cast)
1793+
OPENCV_HAL_IMPL_C_PACK(v_int64x2, v_int32x4, int, pack, static_cast)
1794+
OPENCV_HAL_IMPL_C_PACK(v_int16x8, v_uint8x16, uchar, pack_u, saturate_cast)
1795+
OPENCV_HAL_IMPL_C_PACK(v_int32x4, v_uint16x8, ushort, pack_u, saturate_cast)
17941796
//! @}
17951797

17961798
//! @brief Helper macro
17971799
//! @ingroup core_hal_intrin_impl
1798-
#define OPENCV_HAL_IMPL_C_RSHR_PACK(_Tpvec, _Tp, _Tpnvec, _Tpn, pack_suffix) \
1800+
#define OPENCV_HAL_IMPL_C_RSHR_PACK(_Tpvec, _Tp, _Tpnvec, _Tpn, pack_suffix, cast) \
17991801
template<int n> inline _Tpnvec v_rshr_##pack_suffix(const _Tpvec& a, const _Tpvec& b) \
18001802
{ \
18011803
_Tpnvec c; \
18021804
for( int i = 0; i < _Tpvec::nlanes; i++ ) \
18031805
{ \
1804-
c.s[i] = saturate_cast<_Tpn>((a.s[i] + ((_Tp)1 << (n - 1))) >> n); \
1805-
c.s[i+_Tpvec::nlanes] = saturate_cast<_Tpn>((b.s[i] + ((_Tp)1 << (n - 1))) >> n); \
1806+
c.s[i] = cast<_Tpn>((a.s[i] + ((_Tp)1 << (n - 1))) >> n); \
1807+
c.s[i+_Tpvec::nlanes] = cast<_Tpn>((b.s[i] + ((_Tp)1 << (n - 1))) >> n); \
18061808
} \
18071809
return c; \
18081810
}
@@ -1816,51 +1818,55 @@ template<int n> inline _Tpnvec v_rshr_##pack_suffix(const _Tpvec& a, const _Tpve
18161818
//!
18171819
//! - pack: for 16-, 32- and 64-bit integer input types
18181820
//! - pack_u: for 16- and 32-bit signed integer input types
1819-
OPENCV_HAL_IMPL_C_RSHR_PACK(v_uint16x8, ushort, v_uint8x16, uchar, pack)
1820-
OPENCV_HAL_IMPL_C_RSHR_PACK(v_int16x8, short, v_int8x16, schar, pack)
1821-
OPENCV_HAL_IMPL_C_RSHR_PACK(v_uint32x4, unsigned, v_uint16x8, ushort, pack)
1822-
OPENCV_HAL_IMPL_C_RSHR_PACK(v_int32x4, int, v_int16x8, short, pack)
1823-
OPENCV_HAL_IMPL_C_RSHR_PACK(v_uint64x2, uint64, v_uint32x4, unsigned, pack)
1824-
OPENCV_HAL_IMPL_C_RSHR_PACK(v_int64x2, int64, v_int32x4, int, pack)
1825-
OPENCV_HAL_IMPL_C_RSHR_PACK(v_int16x8, short, v_uint8x16, uchar, pack_u)
1826-
OPENCV_HAL_IMPL_C_RSHR_PACK(v_int32x4, int, v_uint16x8, ushort, pack_u)
1821+
//!
1822+
//! @note All variants except 64-bit use saturation.
1823+
OPENCV_HAL_IMPL_C_RSHR_PACK(v_uint16x8, ushort, v_uint8x16, uchar, pack, saturate_cast)
1824+
OPENCV_HAL_IMPL_C_RSHR_PACK(v_int16x8, short, v_int8x16, schar, pack, saturate_cast)
1825+
OPENCV_HAL_IMPL_C_RSHR_PACK(v_uint32x4, unsigned, v_uint16x8, ushort, pack, saturate_cast)
1826+
OPENCV_HAL_IMPL_C_RSHR_PACK(v_int32x4, int, v_int16x8, short, pack, saturate_cast)
1827+
OPENCV_HAL_IMPL_C_RSHR_PACK(v_uint64x2, uint64, v_uint32x4, unsigned, pack, static_cast)
1828+
OPENCV_HAL_IMPL_C_RSHR_PACK(v_int64x2, int64, v_int32x4, int, pack, static_cast)
1829+
OPENCV_HAL_IMPL_C_RSHR_PACK(v_int16x8, short, v_uint8x16, uchar, pack_u, saturate_cast)
1830+
OPENCV_HAL_IMPL_C_RSHR_PACK(v_int32x4, int, v_uint16x8, ushort, pack_u, saturate_cast)
18271831
//! @}
18281832

18291833
//! @brief Helper macro
18301834
//! @ingroup core_hal_intrin_impl
1831-
#define OPENCV_HAL_IMPL_C_PACK_STORE(_Tpvec, _Tp, _Tpnvec, _Tpn, pack_suffix) \
1835+
#define OPENCV_HAL_IMPL_C_PACK_STORE(_Tpvec, _Tp, _Tpnvec, _Tpn, pack_suffix, cast) \
18321836
inline void v_##pack_suffix##_store(_Tpn* ptr, const _Tpvec& a) \
18331837
{ \
18341838
for( int i = 0; i < _Tpvec::nlanes; i++ ) \
1835-
ptr[i] = saturate_cast<_Tpn>(a.s[i]); \
1839+
ptr[i] = cast<_Tpn>(a.s[i]); \
18361840
}
18371841

18381842
//! @name Pack and store
18391843
//! @{
18401844
//! @brief Store values from the input vector into memory with pack
18411845
//!
1842-
//! Values will be stored into memory with saturating conversion to narrower type.
1846+
//! Values will be stored into memory with conversion to narrower type.
18431847
//! Variant with _u_ suffix converts to corresponding unsigned type.
18441848
//!
18451849
//! - pack: for 16-, 32- and 64-bit integer input types
18461850
//! - pack_u: for 16- and 32-bit signed integer input types
1847-
OPENCV_HAL_IMPL_C_PACK_STORE(v_uint16x8, ushort, v_uint8x16, uchar, pack)
1848-
OPENCV_HAL_IMPL_C_PACK_STORE(v_int16x8, short, v_int8x16, schar, pack)
1849-
OPENCV_HAL_IMPL_C_PACK_STORE(v_uint32x4, unsigned, v_uint16x8, ushort, pack)
1850-
OPENCV_HAL_IMPL_C_PACK_STORE(v_int32x4, int, v_int16x8, short, pack)
1851-
OPENCV_HAL_IMPL_C_PACK_STORE(v_uint64x2, uint64, v_uint32x4, unsigned, pack)
1852-
OPENCV_HAL_IMPL_C_PACK_STORE(v_int64x2, int64, v_int32x4, int, pack)
1853-
OPENCV_HAL_IMPL_C_PACK_STORE(v_int16x8, short, v_uint8x16, uchar, pack_u)
1854-
OPENCV_HAL_IMPL_C_PACK_STORE(v_int32x4, int, v_uint16x8, ushort, pack_u)
1851+
//!
1852+
//! @note All variants except 64-bit use saturation.
1853+
OPENCV_HAL_IMPL_C_PACK_STORE(v_uint16x8, ushort, v_uint8x16, uchar, pack, saturate_cast)
1854+
OPENCV_HAL_IMPL_C_PACK_STORE(v_int16x8, short, v_int8x16, schar, pack, saturate_cast)
1855+
OPENCV_HAL_IMPL_C_PACK_STORE(v_uint32x4, unsigned, v_uint16x8, ushort, pack, saturate_cast)
1856+
OPENCV_HAL_IMPL_C_PACK_STORE(v_int32x4, int, v_int16x8, short, pack, saturate_cast)
1857+
OPENCV_HAL_IMPL_C_PACK_STORE(v_uint64x2, uint64, v_uint32x4, unsigned, pack, static_cast)
1858+
OPENCV_HAL_IMPL_C_PACK_STORE(v_int64x2, int64, v_int32x4, int, pack, static_cast)
1859+
OPENCV_HAL_IMPL_C_PACK_STORE(v_int16x8, short, v_uint8x16, uchar, pack_u, saturate_cast)
1860+
OPENCV_HAL_IMPL_C_PACK_STORE(v_int32x4, int, v_uint16x8, ushort, pack_u, saturate_cast)
18551861
//! @}
18561862

18571863
//! @brief Helper macro
18581864
//! @ingroup core_hal_intrin_impl
1859-
#define OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(_Tpvec, _Tp, _Tpnvec, _Tpn, pack_suffix) \
1865+
#define OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(_Tpvec, _Tp, _Tpnvec, _Tpn, pack_suffix, cast) \
18601866
template<int n> inline void v_rshr_##pack_suffix##_store(_Tpn* ptr, const _Tpvec& a) \
18611867
{ \
18621868
for( int i = 0; i < _Tpvec::nlanes; i++ ) \
1863-
ptr[i] = saturate_cast<_Tpn>((a.s[i] + ((_Tp)1 << (n - 1))) >> n); \
1869+
ptr[i] = cast<_Tpn>((a.s[i] + ((_Tp)1 << (n - 1))) >> n); \
18641870
}
18651871

18661872
//! @name Pack and store with rounding shift
@@ -1872,14 +1878,16 @@ template<int n> inline void v_rshr_##pack_suffix##_store(_Tpn* ptr, const _Tpvec
18721878
//!
18731879
//! - pack: for 16-, 32- and 64-bit integer input types
18741880
//! - pack_u: for 16- and 32-bit signed integer input types
1875-
OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(v_uint16x8, ushort, v_uint8x16, uchar, pack)
1876-
OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(v_int16x8, short, v_int8x16, schar, pack)
1877-
OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(v_uint32x4, unsigned, v_uint16x8, ushort, pack)
1878-
OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(v_int32x4, int, v_int16x8, short, pack)
1879-
OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(v_uint64x2, uint64, v_uint32x4, unsigned, pack)
1880-
OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(v_int64x2, int64, v_int32x4, int, pack)
1881-
OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(v_int16x8, short, v_uint8x16, uchar, pack_u)
1882-
OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(v_int32x4, int, v_uint16x8, ushort, pack_u)
1881+
//!
1882+
//! @note All variants except 64-bit use saturation.
1883+
OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(v_uint16x8, ushort, v_uint8x16, uchar, pack, saturate_cast)
1884+
OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(v_int16x8, short, v_int8x16, schar, pack, saturate_cast)
1885+
OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(v_uint32x4, unsigned, v_uint16x8, ushort, pack, saturate_cast)
1886+
OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(v_int32x4, int, v_int16x8, short, pack, saturate_cast)
1887+
OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(v_uint64x2, uint64, v_uint32x4, unsigned, pack, static_cast)
1888+
OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(v_int64x2, int64, v_int32x4, int, pack, static_cast)
1889+
OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(v_int16x8, short, v_uint8x16, uchar, pack_u, saturate_cast)
1890+
OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(v_int32x4, int, v_uint16x8, ushort, pack_u, saturate_cast)
18831891
//! @}
18841892

18851893
/** @brief Matrix multiplication

modules/core/include/opencv2/core/hal/intrin_neon.hpp

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ struct v_uint64x2
226226

227227
v_uint64x2() {}
228228
explicit v_uint64x2(uint64x2_t v) : val(v) {}
229-
v_uint64x2(unsigned v0, unsigned v1)
229+
v_uint64x2(uint64 v0, uint64 v1)
230230
{
231231
uint64 v[] = {v0, v1};
232232
val = vld1q_u64(v);
@@ -245,7 +245,7 @@ struct v_int64x2
245245

246246
v_int64x2() {}
247247
explicit v_int64x2(int64x2_t v) : val(v) {}
248-
v_int64x2(int v0, int v1)
248+
v_int64x2(int64 v0, int64 v1)
249249
{
250250
int64 v[] = {v0, v1};
251251
val = vld1q_s64(v);
@@ -360,40 +360,40 @@ OPENCV_HAL_IMPL_NEON_INIT_64(float32x4, f32)
360360
OPENCV_HAL_IMPL_NEON_INIT_64(float64x2, f64)
361361
#endif
362362

363-
#define OPENCV_HAL_IMPL_NEON_PACK(_Tpvec, _Tp, hreg, suffix, _Tpwvec, wsuffix, pack, op) \
363+
#define OPENCV_HAL_IMPL_NEON_PACK(_Tpvec, _Tp, hreg, suffix, _Tpwvec, pack, mov, rshr) \
364364
inline _Tpvec v_##pack(const _Tpwvec& a, const _Tpwvec& b) \
365365
{ \
366-
hreg a1 = vqmov##op##_##wsuffix(a.val), b1 = vqmov##op##_##wsuffix(b.val); \
366+
hreg a1 = mov(a.val), b1 = mov(b.val); \
367367
return _Tpvec(vcombine_##suffix(a1, b1)); \
368368
} \
369369
inline void v_##pack##_store(_Tp* ptr, const _Tpwvec& a) \
370370
{ \
371-
hreg a1 = vqmov##op##_##wsuffix(a.val); \
371+
hreg a1 = mov(a.val); \
372372
vst1_##suffix(ptr, a1); \
373373
} \
374374
template<int n> inline \
375375
_Tpvec v_rshr_##pack(const _Tpwvec& a, const _Tpwvec& b) \
376376
{ \
377-
hreg a1 = vqrshr##op##_n_##wsuffix(a.val, n); \
378-
hreg b1 = vqrshr##op##_n_##wsuffix(b.val, n); \
377+
hreg a1 = rshr(a.val, n); \
378+
hreg b1 = rshr(b.val, n); \
379379
return _Tpvec(vcombine_##suffix(a1, b1)); \
380380
} \
381381
template<int n> inline \
382382
void v_rshr_##pack##_store(_Tp* ptr, const _Tpwvec& a) \
383383
{ \
384-
hreg a1 = vqrshr##op##_n_##wsuffix(a.val, n); \
384+
hreg a1 = rshr(a.val, n); \
385385
vst1_##suffix(ptr, a1); \
386386
}
387387

388-
OPENCV_HAL_IMPL_NEON_PACK(v_uint8x16, uchar, uint8x8_t, u8, v_uint16x8, u16, pack, n)
389-
OPENCV_HAL_IMPL_NEON_PACK(v_int8x16, schar, int8x8_t, s8, v_int16x8, s16, pack, n)
390-
OPENCV_HAL_IMPL_NEON_PACK(v_uint16x8, ushort, uint16x4_t, u16, v_uint32x4, u32, pack, n)
391-
OPENCV_HAL_IMPL_NEON_PACK(v_int16x8, short, int16x4_t, s16, v_int32x4, s32, pack, n)
392-
OPENCV_HAL_IMPL_NEON_PACK(v_uint32x4, unsigned, uint32x2_t, u32, v_uint64x2, u64, pack, n)
393-
OPENCV_HAL_IMPL_NEON_PACK(v_int32x4, int, int32x2_t, s32, v_int64x2, s64, pack, n)
388+
OPENCV_HAL_IMPL_NEON_PACK(v_uint8x16, uchar, uint8x8_t, u8, v_uint16x8, pack, vqmovn_u16, vqrshrn_n_u16)
389+
OPENCV_HAL_IMPL_NEON_PACK(v_int8x16, schar, int8x8_t, s8, v_int16x8, pack, vqmovn_s16, vqrshrn_n_s16)
390+
OPENCV_HAL_IMPL_NEON_PACK(v_uint16x8, ushort, uint16x4_t, u16, v_uint32x4, pack, vqmovn_u32, vqrshrn_n_u32)
391+
OPENCV_HAL_IMPL_NEON_PACK(v_int16x8, short, int16x4_t, s16, v_int32x4, pack, vqmovn_s32, vqrshrn_n_s32)
392+
OPENCV_HAL_IMPL_NEON_PACK(v_uint32x4, unsigned, uint32x2_t, u32, v_uint64x2, pack, vmovn_u64, vrshrn_n_u64)
393+
OPENCV_HAL_IMPL_NEON_PACK(v_int32x4, int, int32x2_t, s32, v_int64x2, pack, vmovn_s64, vrshrn_n_s64)
394394

395-
OPENCV_HAL_IMPL_NEON_PACK(v_uint8x16, uchar, uint8x8_t, u8, v_int16x8, s16, pack_u, un)
396-
OPENCV_HAL_IMPL_NEON_PACK(v_uint16x8, ushort, uint16x4_t, u16, v_int32x4, s32, pack_u, un)
395+
OPENCV_HAL_IMPL_NEON_PACK(v_uint8x16, uchar, uint8x8_t, u8, v_int16x8, pack_u, vqmovun_s16, vqrshrun_n_s16)
396+
OPENCV_HAL_IMPL_NEON_PACK(v_uint16x8, ushort, uint16x4_t, u16, v_int32x4, pack_u, vqmovun_s32, vqrshrun_n_s32)
397397

398398
inline v_float32x4 v_matmul(const v_float32x4& v, const v_float32x4& m0,
399399
const v_float32x4& m1, const v_float32x4& m2,

modules/core/include/opencv2/core/hal/intrin_vsx.hpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -394,16 +394,17 @@ OPENCV_HAL_IMPL_VSX_PACK(v_int16x8, short, v_int32x4, unsigned int, int,
394394
vec_sra, vec_packs, vec_add, pack)
395395

396396
OPENCV_HAL_IMPL_VSX_PACK(v_uint32x4, uint, v_uint64x2, unsigned long long, unsigned long long,
397-
vec_sr, vec_packs, vec_add, pack)
397+
vec_sr, vec_pack, vec_add, pack)
398398
OPENCV_HAL_IMPL_VSX_PACK(v_int32x4, int, v_int64x2, unsigned long long, long long,
399-
vec_sra, vec_packs, vec_add, pack)
399+
vec_sra, vec_pack, vec_add, pack)
400400

401401
OPENCV_HAL_IMPL_VSX_PACK(v_uint8x16, uchar, v_int16x8, unsigned short, short,
402402
vec_sra, vec_packsu, vec_adds, pack_u)
403403
OPENCV_HAL_IMPL_VSX_PACK(v_uint16x8, ushort, v_int32x4, unsigned int, int,
404404
vec_sra, vec_packsu, vec_add, pack_u)
405-
OPENCV_HAL_IMPL_VSX_PACK(v_uint32x4, uint, v_int64x2, unsigned long long, long long,
406-
vec_sra, vec_packsu, vec_add, pack_u)
405+
// Following variant is not implemented on other platforms:
406+
//OPENCV_HAL_IMPL_VSX_PACK(v_uint32x4, uint, v_int64x2, unsigned long long, long long,
407+
// vec_sra, vec_packsu, vec_add, pack_u)
407408

408409
/* Recombine */
409410
template <typename _Tpvec>

modules/core/include/opencv2/core/saturate.hpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,12 +136,27 @@ template<> inline short saturate_cast<short>(double v) { int iv = cvRound(
136136
template<> inline short saturate_cast<short>(int64 v) { return (short)((uint64)((int64)v - SHRT_MIN) <= (uint64)USHRT_MAX ? v : v > 0 ? SHRT_MAX : SHRT_MIN); }
137137
template<> inline short saturate_cast<short>(uint64 v) { return (short)std::min(v, (uint64)SHRT_MAX); }
138138

139+
template<> inline int saturate_cast<int>(unsigned v) { return (int)std::min(v, (unsigned)INT_MAX); }
140+
template<> inline int saturate_cast<int>(int64 v) { return (int)((uint64)(v - INT_MIN) <= (uint64)UINT_MAX ? v : v > 0 ? INT_MAX : INT_MIN); }
141+
template<> inline int saturate_cast<int>(uint64 v) { return (int)std::min(v, (uint64)INT_MAX); }
139142
template<> inline int saturate_cast<int>(float v) { return cvRound(v); }
140143
template<> inline int saturate_cast<int>(double v) { return cvRound(v); }
141144

145+
template<> inline unsigned saturate_cast<unsigned>(schar v) { return (unsigned)std::max(v, (schar)0); }
146+
template<> inline unsigned saturate_cast<unsigned>(short v) { return (unsigned)std::max(v, (short)0); }
147+
template<> inline unsigned saturate_cast<unsigned>(int v) { return (unsigned)std::max(v, (int)0); }
148+
template<> inline unsigned saturate_cast<unsigned>(int64 v) { return (unsigned)((uint64)v <= (uint64)UINT_MAX ? v : v > 0 ? UINT_MAX : 0); }
149+
template<> inline unsigned saturate_cast<unsigned>(uint64 v) { return (unsigned)std::min(v, (uint64)UINT_MAX); }
142150
// we intentionally do not clip negative numbers, to make -1 become 0xffffffff etc.
143-
template<> inline unsigned saturate_cast<unsigned>(float v) { return cvRound(v); }
144-
template<> inline unsigned saturate_cast<unsigned>(double v) { return cvRound(v); }
151+
template<> inline unsigned saturate_cast<unsigned>(float v) { return static_cast<unsigned>(cvRound(v)); }
152+
template<> inline unsigned saturate_cast<unsigned>(double v) { return static_cast<unsigned>(cvRound(v)); }
153+
154+
template<> inline uint64 saturate_cast<uint64>(schar v) { return (uint64)std::max(v, (schar)0); }
155+
template<> inline uint64 saturate_cast<uint64>(short v) { return (uint64)std::max(v, (short)0); }
156+
template<> inline uint64 saturate_cast<uint64>(int v) { return (uint64)std::max(v, (int)0); }
157+
template<> inline uint64 saturate_cast<uint64>(int64 v) { return (uint64)std::max(v, (int64)0); }
158+
159+
template<> inline int64 saturate_cast<int64>(uint64 v) { return (int64)std::min(v, (uint64)LLONG_MAX); }
145160

146161
//! @}
147162

0 commit comments

Comments
 (0)