Path: blob/master/modules/imgproc/src/fixedpoint.inl.hpp
16354 views
// This file is part of OpenCV project.1// It is subject to the license terms in the LICENSE file found in the top-level directory2// of this distribution and at http://opencv.org/license.html.3//4// Copyright (C) 2017, Intel Corporation, all rights reserved.5// Third party copyrights are property of their respective owners.678#ifndef _CV_FIXEDPOINT_HPP_9#define _CV_FIXEDPOINT_HPP_1011#include "opencv2/core/softfloat.hpp"1213#ifndef CV_ALWAYS_INLINE14#if defined(__GNUC__) && (__GNUC__ > 3 ||(__GNUC__ == 3 && __GNUC_MINOR__ >= 1))15#define CV_ALWAYS_INLINE inline __attribute__((always_inline))16#elif defined(_MSC_VER)17#define CV_ALWAYS_INLINE __forceinline18#else19#define CV_ALWAYS_INLINE inline20#endif21#endif2223namespace24{2526class fixedpoint6427{28private:29static const int fixedShift = 32;3031int64_t val;32fixedpoint64(int64_t _val) : val(_val) {}33static CV_ALWAYS_INLINE uint64_t fixedround(const uint64_t& _val) { return (_val + ((1LL << fixedShift) >> 1)); }34public:35typedef fixedpoint64 WT;36CV_ALWAYS_INLINE fixedpoint64() { val = 0; }37CV_ALWAYS_INLINE fixedpoint64(const int8_t& _val) { val = ((int64_t)_val) << fixedShift; }38CV_ALWAYS_INLINE fixedpoint64(const uint8_t& _val) { val = ((int64_t)_val) << fixedShift; }39CV_ALWAYS_INLINE fixedpoint64(const int16_t& _val) { val = ((int64_t)_val) << fixedShift; }40CV_ALWAYS_INLINE fixedpoint64(const uint16_t& _val) { val = ((int64_t)_val) << fixedShift; }41CV_ALWAYS_INLINE fixedpoint64(const int32_t& _val) { val = ((int64_t)_val) << fixedShift; }42CV_ALWAYS_INLINE fixedpoint64(const cv::softdouble& _val) { val = cvRound64(_val * cv::softdouble((int64_t)(1LL << fixedShift))); }43CV_ALWAYS_INLINE fixedpoint64& operator = (const int8_t& _val) { val = ((int64_t)_val) << fixedShift; return *this; }44CV_ALWAYS_INLINE fixedpoint64& operator = (const uint8_t& _val) { val = ((int64_t)_val) << fixedShift; return *this; }45CV_ALWAYS_INLINE fixedpoint64& operator = (const int16_t& _val) { val = ((int64_t)_val) << fixedShift; return *this; }46CV_ALWAYS_INLINE fixedpoint64& operator = (const uint16_t& _val) { val = ((int64_t)_val) << fixedShift; return *this; }47CV_ALWAYS_INLINE fixedpoint64& operator = (const int32_t& _val) { val = ((int64_t)_val) << fixedShift; return *this; }48CV_ALWAYS_INLINE fixedpoint64& operator = (const cv::softdouble& _val) { val = cvRound64(_val * cv::softdouble((int64_t)(1LL << fixedShift))); return *this; }49CV_ALWAYS_INLINE fixedpoint64& operator = (const fixedpoint64& _val) { val = _val.val; return *this; }50CV_ALWAYS_INLINE fixedpoint64 operator * (const int8_t& val2) const { return operator *(fixedpoint64(val2)); }51CV_ALWAYS_INLINE fixedpoint64 operator * (const uint8_t& val2) const { return operator *(fixedpoint64(val2)); }52CV_ALWAYS_INLINE fixedpoint64 operator * (const int16_t& val2) const { return operator *(fixedpoint64(val2)); }53CV_ALWAYS_INLINE fixedpoint64 operator * (const uint16_t& val2) const { return operator *(fixedpoint64(val2)); }54CV_ALWAYS_INLINE fixedpoint64 operator * (const int32_t& val2) const { return operator *(fixedpoint64(val2)); }55CV_ALWAYS_INLINE fixedpoint64 operator * (const fixedpoint64& val2) const56{57bool sign_val = val < 0;58bool sign_mul = val2.val < 0;59uint64_t uval = sign_val ? (uint64_t)(-val) : (uint64_t)val;60uint64_t umul = sign_mul ? (uint64_t)(-val2.val) : (uint64_t)val2.val;61bool ressign = sign_val ^ sign_mul;6263uint64_t sh0 = fixedround((uval & 0xFFFFFFFF) * (umul & 0xFFFFFFFF));64uint64_t sh1_0 = (uval >> 32) * (umul & 0xFFFFFFFF);65uint64_t sh1_1 = (uval & 0xFFFFFFFF) * (umul >> 32);66uint64_t sh2 = (uval >> 32) * (umul >> 32);67uint64_t val0_l = (sh1_0 & 0xFFFFFFFF) + (sh1_1 & 0xFFFFFFFF) + (sh0 >> 32);68uint64_t val0_h = (sh2 & 0xFFFFFFFF) + (sh1_0 >> 32) + (sh1_1 >> 32) + (val0_l >> 32);69val0_l &= 0xFFFFFFFF;7071if (sh2 > CV_BIG_INT(0x7FFFFFFF) || val0_h > CV_BIG_INT(0x7FFFFFFF))72return (int64_t)(ressign ? CV_BIG_UINT(0x8000000000000000) : CV_BIG_INT(0x7FFFFFFFFFFFFFFF));7374if (ressign)75{76return -(int64_t)(val0_h << 32 | val0_l);77}78return (int64_t)(val0_h << 32 | val0_l);79}80CV_ALWAYS_INLINE fixedpoint64 operator + (const fixedpoint64& val2) const81{82int64_t res = val + val2.val;83return (int64_t)(((val ^ res) & (val2.val ^ res)) < 0 ? ~(res & CV_BIG_UINT(0x8000000000000000)) : res);84}85CV_ALWAYS_INLINE fixedpoint64 operator - (const fixedpoint64& val2) const86{87int64_t res = val - val2.val;88return (int64_t)(((val ^ val2.val) & (val ^ res)) < 0 ? ~(res & CV_BIG_UINT(0x8000000000000000)) : res);89}90CV_ALWAYS_INLINE fixedpoint64 operator >> (int n) const { return fixedpoint64(val >> n); }91CV_ALWAYS_INLINE fixedpoint64 operator << (int n) const { return fixedpoint64(val << n); }92CV_ALWAYS_INLINE bool operator == (const fixedpoint64& val2) const { return val == val2.val; }93template <typename ET>94CV_ALWAYS_INLINE ET saturate_cast() const { return cv::saturate_cast<ET>((int64_t)fixedround((uint64_t)val) >> fixedShift); }95CV_ALWAYS_INLINE operator double() const { return (double)val / (1LL << fixedShift); }96CV_ALWAYS_INLINE operator float() const { return (float)val / (1LL << fixedShift); }97CV_ALWAYS_INLINE operator uint8_t() const { return saturate_cast<uint8_t>(); }98CV_ALWAYS_INLINE operator int8_t() const { return saturate_cast<int8_t>(); }99CV_ALWAYS_INLINE operator uint16_t() const { return saturate_cast<uint16_t>(); }100CV_ALWAYS_INLINE operator int16_t() const { return saturate_cast<int16_t>(); }101CV_ALWAYS_INLINE operator int32_t() const { return saturate_cast<int32_t>(); }102CV_ALWAYS_INLINE bool isZero() { return val == 0; }103static CV_ALWAYS_INLINE fixedpoint64 zero() { return fixedpoint64(); }104static CV_ALWAYS_INLINE fixedpoint64 one() { return fixedpoint64((int64_t)(1LL << fixedShift)); }105friend class fixedpoint32;106};107108class ufixedpoint64109{110private:111static const int fixedShift = 32;112113uint64_t val;114ufixedpoint64(uint64_t _val) : val(_val) {}115static CV_ALWAYS_INLINE uint64_t fixedround(const uint64_t& _val) { return (_val + ((1LL << fixedShift) >> 1)); }116public:117typedef ufixedpoint64 WT;118CV_ALWAYS_INLINE ufixedpoint64() { val = 0; }119CV_ALWAYS_INLINE ufixedpoint64(const uint8_t& _val) { val = ((uint64_t)_val) << fixedShift; }120CV_ALWAYS_INLINE ufixedpoint64(const uint16_t& _val) { val = ((uint64_t)_val) << fixedShift; }121CV_ALWAYS_INLINE ufixedpoint64(const uint32_t& _val) { val = ((uint64_t)_val) << fixedShift; }122CV_ALWAYS_INLINE ufixedpoint64(const cv::softdouble& _val) { val = _val.getSign() ? 0 : (uint64_t)cvRound64(_val * cv::softdouble((int64_t)(1LL << fixedShift))); }123CV_ALWAYS_INLINE ufixedpoint64& operator = (const uint8_t& _val) { val = ((uint64_t)_val) << fixedShift; return *this; }124CV_ALWAYS_INLINE ufixedpoint64& operator = (const uint16_t& _val) { val = ((uint64_t)_val) << fixedShift; return *this; }125CV_ALWAYS_INLINE ufixedpoint64& operator = (const uint32_t& _val) { val = ((uint64_t)_val) << fixedShift; return *this; }126CV_ALWAYS_INLINE ufixedpoint64& operator = (const cv::softdouble& _val) { val = _val.getSign() ? 0 : (uint64_t)cvRound64(_val * cv::softdouble((int64_t)(1LL << fixedShift))); return *this; }127CV_ALWAYS_INLINE ufixedpoint64& operator = (const ufixedpoint64& _val) { val = _val.val; return *this; }128CV_ALWAYS_INLINE ufixedpoint64 operator * (const uint8_t& val2) const { return operator *(ufixedpoint64(val2)); }129CV_ALWAYS_INLINE ufixedpoint64 operator * (const uint16_t& val2) const { return operator *(ufixedpoint64(val2)); }130CV_ALWAYS_INLINE ufixedpoint64 operator * (const uint32_t& val2) const { return operator *(ufixedpoint64(val2)); }131CV_ALWAYS_INLINE ufixedpoint64 operator * (const ufixedpoint64& val2) const132{133uint64_t sh0 = fixedround((val & 0xFFFFFFFF) * (val2.val & 0xFFFFFFFF));134uint64_t sh1_0 = (val >> 32) * (val2.val & 0xFFFFFFFF);135uint64_t sh1_1 = (val & 0xFFFFFFFF) * (val2.val >> 32);136uint64_t sh2 = (val >> 32) * (val2.val >> 32);137uint64_t val0_l = (sh1_0 & 0xFFFFFFFF) + (sh1_1 & 0xFFFFFFFF) + (sh0 >> 32);138uint64_t val0_h = (sh2 & 0xFFFFFFFF) + (sh1_0 >> 32) + (sh1_1 >> 32) + (val0_l >> 32);139val0_l &= 0xFFFFFFFF;140141if (sh2 > CV_BIG_INT(0xFFFFFFFF) || val0_h > CV_BIG_INT(0xFFFFFFFF))142return (uint64_t)CV_BIG_UINT(0xFFFFFFFFFFFFFFFF);143144return (val0_h << 32 | val0_l);145}146CV_ALWAYS_INLINE ufixedpoint64 operator + (const ufixedpoint64& val2) const147{148uint64_t res = val + val2.val;149return (uint64_t)((val > res) ? CV_BIG_UINT(0xFFFFFFFFFFFFFFFF) : res);150}151CV_ALWAYS_INLINE ufixedpoint64 operator - (const ufixedpoint64& val2) const152{153return val > val2.val ? (val - val2.val) : 0;154}155CV_ALWAYS_INLINE ufixedpoint64 operator >> (int n) const { return ufixedpoint64(val >> n); }156CV_ALWAYS_INLINE ufixedpoint64 operator << (int n) const { return ufixedpoint64(val << n); }157CV_ALWAYS_INLINE bool operator == (const ufixedpoint64& val2) const { return val == val2.val; }158template <typename ET>159CV_ALWAYS_INLINE ET saturate_cast() const { return cv::saturate_cast<ET>(fixedround(val) >> fixedShift); }160CV_ALWAYS_INLINE operator double() const { return (double)val / (1LL << fixedShift); }161CV_ALWAYS_INLINE operator float() const { return (float)val / (1LL << fixedShift); }162CV_ALWAYS_INLINE operator uint8_t() const { return saturate_cast<uint8_t>(); }163CV_ALWAYS_INLINE operator int8_t() const { return saturate_cast<int8_t>(); }164CV_ALWAYS_INLINE operator uint16_t() const { return saturate_cast<uint16_t>(); }165CV_ALWAYS_INLINE operator int16_t() const { return saturate_cast<int16_t>(); }166CV_ALWAYS_INLINE operator int32_t() const { return saturate_cast<int32_t>(); }167CV_ALWAYS_INLINE bool isZero() { return val == 0; }168static CV_ALWAYS_INLINE ufixedpoint64 zero() { return ufixedpoint64(); }169static CV_ALWAYS_INLINE ufixedpoint64 one() { return ufixedpoint64((uint64_t)(1ULL << fixedShift)); }170friend class ufixedpoint32;171};172173class fixedpoint32174{175private:176static const int fixedShift = 16;177178int32_t val;179fixedpoint32(int32_t _val) : val(_val) {}180static CV_ALWAYS_INLINE uint32_t fixedround(const uint32_t& _val) { return (_val + ((1 << fixedShift) >> 1)); }181public:182typedef fixedpoint64 WT;183CV_ALWAYS_INLINE fixedpoint32() { val = 0; }184CV_ALWAYS_INLINE fixedpoint32(const int8_t& _val) { val = ((int32_t)_val) << fixedShift; }185CV_ALWAYS_INLINE fixedpoint32(const uint8_t& _val) { val = ((int32_t)_val) << fixedShift; }186CV_ALWAYS_INLINE fixedpoint32(const int16_t& _val) { val = ((int32_t)_val) << fixedShift; }187CV_ALWAYS_INLINE fixedpoint32(const cv::softdouble& _val) { val = (int32_t)cvRound(_val * cv::softdouble((1 << fixedShift))); }188CV_ALWAYS_INLINE fixedpoint32& operator = (const int8_t& _val) { val = ((int32_t)_val) << fixedShift; return *this; }189CV_ALWAYS_INLINE fixedpoint32& operator = (const uint8_t& _val) { val = ((int32_t)_val) << fixedShift; return *this; }190CV_ALWAYS_INLINE fixedpoint32& operator = (const int16_t& _val) { val = ((int32_t)_val) << fixedShift; return *this; }191CV_ALWAYS_INLINE fixedpoint32& operator = (const cv::softdouble& _val) { val = (int32_t)cvRound(_val * cv::softdouble((1 << fixedShift))); return *this; }192CV_ALWAYS_INLINE fixedpoint32& operator = (const fixedpoint32& _val) { val = _val.val; return *this; }193CV_ALWAYS_INLINE fixedpoint32 operator * (const int8_t& val2) const { return cv::saturate_cast<int32_t>((int64_t)val * val2); }194CV_ALWAYS_INLINE fixedpoint32 operator * (const uint8_t& val2) const { return cv::saturate_cast<int32_t>((int64_t)val * val2); }195CV_ALWAYS_INLINE fixedpoint32 operator * (const int16_t& val2) const { return cv::saturate_cast<int32_t>((int64_t)val * val2); }196CV_ALWAYS_INLINE fixedpoint64 operator * (const fixedpoint32& val2) const { return (int64_t)val * (int64_t)(val2.val); }197CV_ALWAYS_INLINE fixedpoint32 operator + (const fixedpoint32& val2) const198{199int32_t res = val + val2.val;200return (int64_t)((val ^ res) & (val2.val ^ res)) >> 31 ? ~(res & ~0x7FFFFFFF) : res;201}202CV_ALWAYS_INLINE fixedpoint32 operator - (const fixedpoint32& val2) const203{204int32_t res = val - val2.val;205return (int64_t)((val ^ val2.val) & (val ^ res)) >> 31 ? ~(res & ~0x7FFFFFFF) : res;206}207CV_ALWAYS_INLINE fixedpoint32 operator >> (int n) const { return fixedpoint32(val >> n); }208CV_ALWAYS_INLINE fixedpoint32 operator << (int n) const { return fixedpoint32(val << n); }209CV_ALWAYS_INLINE bool operator == (const fixedpoint32& val2) const { return val == val2.val; }210template <typename ET>211CV_ALWAYS_INLINE ET saturate_cast() const { return cv::saturate_cast<ET>((int32_t)fixedround((uint32_t)val) >> fixedShift); }212CV_ALWAYS_INLINE operator fixedpoint64() const { return (int64_t)val << (fixedpoint64::fixedShift - fixedShift); }213CV_ALWAYS_INLINE operator double() const { return (double)val / (1 << fixedShift); }214CV_ALWAYS_INLINE operator float() const { return (float)val / (1 << fixedShift); }215CV_ALWAYS_INLINE operator uint8_t() const { return saturate_cast<uint8_t>(); }216CV_ALWAYS_INLINE operator int8_t() const { return saturate_cast<int8_t>(); }217CV_ALWAYS_INLINE operator uint16_t() const { return saturate_cast<uint16_t>(); }218CV_ALWAYS_INLINE operator int16_t() const { return saturate_cast<int16_t>(); }219CV_ALWAYS_INLINE operator int32_t() const { return saturate_cast<int32_t>(); }220CV_ALWAYS_INLINE bool isZero() { return val == 0; }221static CV_ALWAYS_INLINE fixedpoint32 zero() { return fixedpoint32(); }222static CV_ALWAYS_INLINE fixedpoint32 one() { return fixedpoint32((1 << fixedShift)); }223friend class fixedpoint16;224};225226class ufixedpoint32227{228private:229static const int fixedShift = 16;230231uint32_t val;232ufixedpoint32(uint32_t _val) : val(_val) {}233static CV_ALWAYS_INLINE uint32_t fixedround(const uint32_t& _val) { return (_val + ((1 << fixedShift) >> 1)); }234public:235typedef ufixedpoint64 WT;236CV_ALWAYS_INLINE ufixedpoint32() { val = 0; }237CV_ALWAYS_INLINE ufixedpoint32(const uint8_t& _val) { val = ((uint32_t)_val) << fixedShift; }238CV_ALWAYS_INLINE ufixedpoint32(const uint16_t& _val) { val = ((uint32_t)_val) << fixedShift; }239CV_ALWAYS_INLINE ufixedpoint32(const cv::softdouble& _val) { val = _val.getSign() ? 0 : (uint32_t)cvRound(_val * cv::softdouble((1 << fixedShift))); }240CV_ALWAYS_INLINE ufixedpoint32& operator = (const uint8_t& _val) { val = ((uint32_t)_val) << fixedShift; return *this; }241CV_ALWAYS_INLINE ufixedpoint32& operator = (const uint16_t& _val) { val = ((uint32_t)_val) << fixedShift; return *this; }242CV_ALWAYS_INLINE ufixedpoint32& operator = (const cv::softdouble& _val) { val = _val.getSign() ? 0 : (uint32_t)cvRound(_val * cv::softdouble((1 << fixedShift))); return *this; }243CV_ALWAYS_INLINE ufixedpoint32& operator = (const ufixedpoint32& _val) { val = _val.val; return *this; }244CV_ALWAYS_INLINE ufixedpoint32 operator * (const uint8_t& val2) const { return cv::saturate_cast<uint32_t>((uint64_t)val * val2); }245CV_ALWAYS_INLINE ufixedpoint32 operator * (const uint16_t& val2) const { return cv::saturate_cast<uint32_t>((uint64_t)val * val2); }246CV_ALWAYS_INLINE ufixedpoint64 operator * (const ufixedpoint32& val2) const { return (uint64_t)val * (uint64_t)(val2.val); }247CV_ALWAYS_INLINE ufixedpoint32 operator + (const ufixedpoint32& val2) const248{249uint32_t res = val + val2.val;250return (val > res) ? 0xFFFFFFFF : res;251}252CV_ALWAYS_INLINE ufixedpoint32 operator - (const ufixedpoint32& val2) const253{254return val > val2.val ? (val - val2.val) : 0;255}256CV_ALWAYS_INLINE ufixedpoint32 operator >> (int n) const { return ufixedpoint32(val >> n); }257CV_ALWAYS_INLINE ufixedpoint32 operator << (int n) const { return ufixedpoint32(val << n); }258CV_ALWAYS_INLINE bool operator == (const ufixedpoint32& val2) const { return val == val2.val; }259template <typename ET>260CV_ALWAYS_INLINE ET saturate_cast() const { return cv::saturate_cast<ET>(fixedround(val) >> fixedShift); }261CV_ALWAYS_INLINE operator ufixedpoint64() const { return (uint64_t)val << (ufixedpoint64::fixedShift - fixedShift); }262CV_ALWAYS_INLINE operator double() const { return (double)val / (1 << fixedShift); }263CV_ALWAYS_INLINE operator float() const { return (float)val / (1 << fixedShift); }264CV_ALWAYS_INLINE operator uint8_t() const { return saturate_cast<uint8_t>(); }265CV_ALWAYS_INLINE operator int8_t() const { return saturate_cast<int8_t>(); }266CV_ALWAYS_INLINE operator uint16_t() const { return saturate_cast<uint16_t>(); }267CV_ALWAYS_INLINE operator int16_t() const { return saturate_cast<int16_t>(); }268CV_ALWAYS_INLINE operator int32_t() const { return saturate_cast<int32_t>(); }269CV_ALWAYS_INLINE bool isZero() { return val == 0; }270static CV_ALWAYS_INLINE ufixedpoint32 zero() { return ufixedpoint32(); }271static CV_ALWAYS_INLINE ufixedpoint32 one() { return ufixedpoint32((1U << fixedShift)); }272friend class ufixedpoint16;273};274275class fixedpoint16276{277private:278static const int fixedShift = 8;279280int16_t val;281fixedpoint16(int16_t _val) : val(_val) {}282static CV_ALWAYS_INLINE uint16_t fixedround(const uint16_t& _val) { return (_val + ((1 << fixedShift) >> 1)); }283public:284typedef fixedpoint32 WT;285CV_ALWAYS_INLINE fixedpoint16() { val = 0; }286CV_ALWAYS_INLINE fixedpoint16(const int8_t& _val) { val = ((int16_t)_val) << fixedShift; }287CV_ALWAYS_INLINE fixedpoint16(const cv::softdouble& _val) { val = (int16_t)cvRound(_val * cv::softdouble((1 << fixedShift))); }288CV_ALWAYS_INLINE fixedpoint16& operator = (const int8_t& _val) { val = ((int16_t)_val) << fixedShift; return *this; }289CV_ALWAYS_INLINE fixedpoint16& operator = (const cv::softdouble& _val) { val = (int16_t)cvRound(_val * cv::softdouble((1 << fixedShift))); return *this; }290CV_ALWAYS_INLINE fixedpoint16& operator = (const fixedpoint16& _val) { val = _val.val; return *this; }291CV_ALWAYS_INLINE fixedpoint16 operator * (const int8_t& val2) const { return cv::saturate_cast<int16_t>((int32_t)val * val2); }292CV_ALWAYS_INLINE fixedpoint32 operator * (const fixedpoint16& val2) const { return (int32_t)val * (int32_t)(val2.val); }293CV_ALWAYS_INLINE fixedpoint16 operator + (const fixedpoint16& val2) const294{295int16_t res = val + val2.val;296return ((val ^ res) & (val2.val ^ res)) >> 15 ? (int16_t)(~(res & ~0x7FFF)) : res;297}298CV_ALWAYS_INLINE fixedpoint16 operator - (const fixedpoint16& val2) const299{300int16_t res = val - val2.val;301return ((val ^ val2.val) & (val ^ res)) >> 15 ? (int16_t)(~(res & ~(int16_t)0x7FFF)) : res;302}303CV_ALWAYS_INLINE fixedpoint16 operator >> (int n) const { return fixedpoint16((int16_t)(val >> n)); }304CV_ALWAYS_INLINE fixedpoint16 operator << (int n) const { return fixedpoint16((int16_t)(val << n)); }305CV_ALWAYS_INLINE bool operator == (const fixedpoint16& val2) const { return val == val2.val; }306template <typename ET>307CV_ALWAYS_INLINE ET saturate_cast() const { return cv::saturate_cast<ET>((int16_t)fixedround((uint16_t)val) >> fixedShift); }308CV_ALWAYS_INLINE operator fixedpoint32() const { return (int32_t)val << (fixedpoint32::fixedShift - fixedShift); }309CV_ALWAYS_INLINE operator double() const { return (double)val / (1 << fixedShift); }310CV_ALWAYS_INLINE operator float() const { return (float)val / (1 << fixedShift); }311CV_ALWAYS_INLINE operator uint8_t() const { return saturate_cast<uint8_t>(); }312CV_ALWAYS_INLINE operator int8_t() const { return saturate_cast<int8_t>(); }313CV_ALWAYS_INLINE operator uint16_t() const { return saturate_cast<uint16_t>(); }314CV_ALWAYS_INLINE operator int16_t() const { return saturate_cast<int16_t>(); }315CV_ALWAYS_INLINE operator int32_t() const { return saturate_cast<int32_t>(); }316CV_ALWAYS_INLINE bool isZero() { return val == 0; }317static CV_ALWAYS_INLINE fixedpoint16 zero() { return fixedpoint16(); }318static CV_ALWAYS_INLINE fixedpoint16 one() { return fixedpoint16((int16_t)(1 << fixedShift)); }319};320321class ufixedpoint16322{323private:324static const int fixedShift = 8;325326uint16_t val;327ufixedpoint16(uint16_t _val) : val(_val) {}328static CV_ALWAYS_INLINE uint16_t fixedround(const uint16_t& _val) { return (_val + ((1 << fixedShift) >> 1)); }329public:330typedef ufixedpoint32 WT;331CV_ALWAYS_INLINE ufixedpoint16() { val = 0; }332CV_ALWAYS_INLINE ufixedpoint16(const uint8_t& _val) { val = ((uint16_t)_val) << fixedShift; }333CV_ALWAYS_INLINE ufixedpoint16(const cv::softdouble& _val) { val = _val.getSign() ? 0 : (uint16_t)cvRound(_val * cv::softdouble((int32_t)(1 << fixedShift))); }334CV_ALWAYS_INLINE ufixedpoint16& operator = (const uint8_t& _val) { val = ((uint16_t)_val) << fixedShift; return *this; }335CV_ALWAYS_INLINE ufixedpoint16& operator = (const cv::softdouble& _val) { val = _val.getSign() ? 0 : (uint16_t)cvRound(_val * cv::softdouble((int32_t)(1 << fixedShift))); return *this; }336CV_ALWAYS_INLINE ufixedpoint16& operator = (const ufixedpoint16& _val) { val = _val.val; return *this; }337CV_ALWAYS_INLINE ufixedpoint16 operator * (const uint8_t& val2) const { return cv::saturate_cast<uint16_t>((uint32_t)val * val2); }338CV_ALWAYS_INLINE ufixedpoint32 operator * (const ufixedpoint16& val2) const { return ((uint32_t)val * (uint32_t)(val2.val)); }339CV_ALWAYS_INLINE ufixedpoint16 operator + (const ufixedpoint16& val2) const340{341uint16_t res = val + val2.val;342return (val > res) ? (uint16_t)0xFFFF : res;343}344CV_ALWAYS_INLINE ufixedpoint16 operator - (const ufixedpoint16& val2) const345{346return val > val2.val ? (uint16_t)(val - val2.val) : (uint16_t)0;347}348CV_ALWAYS_INLINE ufixedpoint16 operator >> (int n) const { return ufixedpoint16((uint16_t)(val >> n)); }349CV_ALWAYS_INLINE ufixedpoint16 operator << (int n) const { return ufixedpoint16((uint16_t)(val << n)); }350CV_ALWAYS_INLINE bool operator == (const ufixedpoint16& val2) const { return val == val2.val; }351template <typename ET>352CV_ALWAYS_INLINE ET saturate_cast() const { return cv::saturate_cast<ET>(fixedround(val) >> fixedShift); }353CV_ALWAYS_INLINE operator ufixedpoint32() const { return (uint32_t)val << (ufixedpoint32::fixedShift - fixedShift); }354CV_ALWAYS_INLINE operator double() const { return (double)val / (1 << fixedShift); }355CV_ALWAYS_INLINE operator float() const { return (float)val / (1 << fixedShift); }356CV_ALWAYS_INLINE operator uint8_t() const { return saturate_cast<uint8_t>(); }357CV_ALWAYS_INLINE operator int8_t() const { return saturate_cast<int8_t>(); }358CV_ALWAYS_INLINE operator uint16_t() const { return saturate_cast<uint16_t>(); }359CV_ALWAYS_INLINE operator int16_t() const { return saturate_cast<int16_t>(); }360CV_ALWAYS_INLINE operator int32_t() const { return saturate_cast<int32_t>(); }361CV_ALWAYS_INLINE bool isZero() { return val == 0; }362static CV_ALWAYS_INLINE ufixedpoint16 zero() { return ufixedpoint16(); }363static CV_ALWAYS_INLINE ufixedpoint16 one() { return ufixedpoint16((uint16_t)(1 << fixedShift)); }364};365366}367368#endif369370371