https://bugs.kde.org/show_bug.cgi?id=371013
Bug ID: 371013 Summary: some code not highlighted properly Product: kdevelop Version: 5.0.2 Platform: Other OS: Linux Status: UNCONFIRMED Severity: normal Priority: NOR Component: Language Support: CPP (Clang-based) Assignee: kdevelop-bugs-n...@kde.org Reporter: m...@svenbrauch.de CC: kf...@kde.org, m...@milianw.de Some of the below code is not being highlighted at all by kdev-clang: #ifndef FIXPOINT_HPP #define FIXPOINT_HPP #include <algorithm> #include <stdint.h> #include <type_traits> #include <assert.h> template <int Size> struct SIntegerBySize {}; template <> struct SIntegerBySize<1> { using stype = int8_t; using utype = uint8_t; }; template <> struct SIntegerBySize<2> { using stype = int16_t; using utype = uint16_t; }; template <> struct SIntegerBySize<4> { using stype = int32_t; using utype = uint32_t; }; template <> struct SIntegerBySize<8> { using stype = int64_t; using utype = uint64_t; }; #if defined(__SIZEOF_INT128__) template <> struct SIntegerBySize<16>{ using stype = __int128; using utype = unsigned __int128; }; template <> struct SIntegerBySize<32>{ using stype = __int128; using utype = unsigned __int128; }; #else template <> struct SIntegerBySize<16>{ using stype = int64_t; using utype = uint64_t; }; #endif template <typename T> struct SDoubleWidth { using type = typename std::conditional<std::is_signed<T>::value, typename SIntegerBySize<sizeof(T)*2>::stype, typename SIntegerBySize<sizeof(T)*2>::utype >::type; }; template <typename T1, typename T2> struct SBiggerType { using type = typename std::conditional<(sizeof(T1)>sizeof(T2)) , T1, T2>::type; }; template<int X, int Y> struct static_min{ static constexpr int value = X < Y ? X : Y; }; template<int X, int Y> struct static_max{ static constexpr int value = X >= Y ? X : Y; }; template<int X, int min, int max> struct static_clamp{ static constexpr int value = static_max<static_min<X, max>::value, min>::value; }; template<int X> struct staitc_abs{ static constexpr int value = X < 0 ? -X : X; }; template<int X, typename T> struct static_shift{ static constexpr int value = static_clamp<X, 0, sizeof(T)*8-1>::value; }; template<int FP, typename T> struct Fixpoint; template <int lhs_FP, typename lhs_T, int rhs_FP, typename rhs_T> struct ArbitraryMUL; template <int lhs_FP, typename lhs_T, int rhs_FP, typename rhs_T> struct ArbitraryDIV; template<typename ResultType, typename T> ResultType ShrinkType(const T& t) { if (sizeof(T) > sizeof(ResultType)) { constexpr int DestTypeSize = static_min<sizeof(ResultType)*8, sizeof(T)*8-1>::value; //constexpr int DiscardedBits = (sizeof(T) - sizeof(ResultType))*8; const bool __attribute__((unused)) OverflowCheck = (t >> DestTypeSize) == 0; assert(OverflowCheck); if (std::is_signed<ResultType>::value && std::is_signed<T>::value) { const bool InputIsNegative = t < 0; const bool CastedVersionIsNegative = ResultType(t) < 0; const bool __attribute__((unused)) SignHasChangedDueToOverflow = InputIsNegative == CastedVersionIsNegative; assert(SignHasChangedDueToOverflow); } } return ResultType(t); } enum FixpointOperationAggregate{foaArbitraryADD, foaArbitraryMUL, foaArbitraryDIV}; template <int lhs_FP, typename lhs_T, int rhs_FP, typename rhs_T> struct ArbitraryADD { ArbitraryADD(const lhs_T& _lhs, const rhs_T& _rhs): lhs(_lhs), rhs(_rhs) {} using type = ArbitraryADD<lhs_FP, lhs_T, rhs_FP, rhs_T>; static constexpr int lhs_prec = lhs_FP; static constexpr FixpointOperationAggregate Operation = foaArbitraryADD; using lhs_type = lhs_T; template<int ret_FP, typename ret_T> constexpr operator Fixpoint<ret_FP, ret_T>() const { if (ret_FP <= static_min<lhs_FP, rhs_FP>::value) // return precision is the lowest { //Convert everything down to ret_FP, then add to allow overflow constexpr int minprec = static_min<lhs_FP, rhs_FP>::value; const lhs_T lhs_shifted = lhs >> staitc_abs<lhs_FP-minprec>::value; const rhs_T rhs_shifted = rhs >> staitc_abs<rhs_FP-minprec>::value; return Fixpoint<ret_FP, ret_T>::ConstructRaw( (lhs_shifted + rhs_shifted) >> staitc_abs<minprec-ret_FP>::value); } else if (ret_FP > static_max<lhs_FP, rhs_FP>::value) // return precision is the highest { //use the highest precision of lhs and rhs available, constexpr int max_lhs_rhs = static_max<lhs_FP, rhs_FP>::value; const lhs_T lhs_shifted = lhs_FP < max_lhs_rhs ? lhs << staitc_abs<lhs_FP-max_lhs_rhs>::value : lhs; const rhs_T rhs_shifted = rhs_FP < max_lhs_rhs ? rhs << static_clamp<staitc_abs<rhs_FP-max_lhs_rhs>::value, 0, sizeof(rhs_T)*8-1>::value : rhs; return Fixpoint<ret_FP, ret_T>::ConstructRaw((lhs_shifted + rhs_shifted) << staitc_abs<ret_FP-max_lhs_rhs>::value); } else if ( (rhs_FP >= ret_FP) && (ret_FP >= lhs_FP) ) { const rhs_T rhs_shifted = rhs >> staitc_abs<rhs_FP-ret_FP>::value; const lhs_T lhs_shifted = lhs << staitc_abs<lhs_FP-ret_FP>::value; return Fixpoint<ret_FP, ret_T>::ConstructRaw(lhs_shifted + rhs_shifted); } else //if ( (lhs_FP >= ret_FP) && (ret_FP >= rhs_FP) ) { const rhs_T rhs_shifted = rhs << staitc_abs<rhs_FP-ret_FP>::value; const lhs_T lhs_shifted = lhs >> staitc_abs<lhs_FP-ret_FP>::value; return Fixpoint<ret_FP, ret_T>::ConstructRaw(lhs_shifted + rhs_shifted); } } // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ template<int ret_FP, typename ret_T> inline constexpr ArbitraryADD<lhs_FP, lhs_T, ret_FP, ret_T> operator + (const Fixpoint<ret_FP, ret_T>& _rhs) const { /* TODO: Discuss operand grouping to avoid LHS-Rule. * Consider Fixpoint<12>a + Fixpoint<10>b + Fixpoint<10>c; * This is currently treated as (Fixpoint<12>a + Fixpoint<10>b) + Fixpoint<10>c; evaluating Fixpoint<12>(a+b) + Fixpoint<10>c; due to LHS-Rule. * Alternatively since its a lazy evaluation we can reorder the operands so that matching precision types are evaluated first in left to right order, then * not-matching operands are treated with LHS-rule. * Pro: less shifting * Con: less predictable overflow behavior. */ return ArbitraryADD<lhs_FP, lhs_T, ret_FP, ret_T>(Fixpoint<lhs_FP, lhs_T>(*this).Data, _rhs.Data); } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type > inline constexpr ArbitraryADD<lhs_FP, lhs_T, std::is_integral<Arithmetic>::value ? 0: lhs_FP, lhs_T> operator + (const Arithmetic& _rhs) const { return ArbitraryADD<lhs_FP, lhs_T, std::is_integral<Arithmetic>::value ? 0: lhs_FP, lhs_T>(Fixpoint<lhs_FP, lhs_T>(*this).Data, Fixpoint<std::is_integral<Arithmetic>::value ? 0: lhs_FP, lhs_T>(_rhs).Data); } template<typename add_T> inline constexpr ArbitraryADD<lhs_FP, lhs_T, add_T::lhs_prec, typename add_T::lhs_type> operator + (const add_T& _rhs) const { return ArbitraryADD<lhs_FP, lhs_T, add_T::lhs_prec, typename add_T::lhs_type>( Fixpoint<lhs_FP, lhs_T>(*this).Data, Fixpoint<add_T::lhs_prec, typename add_T::lhs_type>(_rhs).Data); } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type > friend inline constexpr ArbitraryADD<lhs_FP, lhs_T, std::is_integral<Arithmetic>::value ? 0 : lhs_FP, lhs_T> operator + (Arithmetic lhs, const type& rhs) { return ArbitraryADD<lhs_FP, lhs_T, std::is_integral<Arithmetic>::value ? 0 : lhs_FP, lhs_T>(Fixpoint<lhs_FP, lhs_T>(rhs).InternalRepresentation(), Fixpoint<std::is_integral<Arithmetic>::value ? 0 : lhs_FP, lhs_T>(lhs).InternalRepresentation()); } //Multiply-Add optimization template<int mullhs_FP, typename mullhs_T, int mulrhs_FP, typename mulrhs_T> inline constexpr ArbitraryADD<lhs_FP, lhs_T, mullhs_FP+mulrhs_FP, typename ArbitraryMUL<mullhs_FP, mullhs_T, mulrhs_FP, mulrhs_T>::DoubleSizeType> operator + (const ArbitraryMUL<mullhs_FP, mullhs_T, mulrhs_FP, mulrhs_T>& mul) const { const lhs_T rhs_shifted = ShrinkType<lhs_T>(lhs_FP > rhs_FP ? rhs << staitc_abs<lhs_FP-rhs_FP>::value : rhs >> staitc_abs<rhs_FP-lhs_FP>::value); return ArbitraryADD<lhs_FP, lhs_T, mullhs_FP+mulrhs_FP, typename ArbitraryMUL<mullhs_FP, mullhs_T, mulrhs_FP, mulrhs_T>::DoubleSizeType>(lhs+rhs_shifted, mul.Result()); } // ---------------------------------------------------------------------------------------------------------------------------------------------------------------- template<int ret_FP, typename ret_T> inline constexpr ArbitraryADD<lhs_FP, lhs_T, ret_FP, ret_T> operator - (const Fixpoint<ret_FP, ret_T>& _rhs) const { return ArbitraryADD<lhs_FP, lhs_T, ret_FP, ret_T>(Fixpoint<lhs_FP, lhs_T>(*this).Data, -_rhs.Data); } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type> inline constexpr ArbitraryADD<lhs_FP, lhs_T, std::is_integral<Arithmetic>::value ? 0: lhs_FP, lhs_T> operator - (const Arithmetic& _rhs) const { return ArbitraryADD<lhs_FP, lhs_T, std::is_integral<Arithmetic>::value ? 0: lhs_FP, lhs_T>(Fixpoint<lhs_FP, lhs_T>(*this).Data, Fixpoint<std::is_integral<Arithmetic>::value ? 0: lhs_FP, lhs_T>(-_rhs).Data); } template<typename add_T> inline constexpr ArbitraryADD<lhs_FP, lhs_T, add_T::lhs_prec, typename add_T::lhs_type> operator - (const add_T& _rhs) const { return ArbitraryADD<lhs_FP, lhs_T, add_T::lhs_prec, typename add_T::lhs_type>( Fixpoint<lhs_FP, lhs_T>(*this).Data, -Fixpoint<add_T::lhs_prec, typename add_T::lhs_type>(_rhs).Data); } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type > friend inline constexpr ArbitraryADD<lhs_FP, lhs_T, std::is_integral<Arithmetic>::value ? 0 : lhs_FP, lhs_T> operator - (Arithmetic lhs, const type& rhs) { return ArbitraryADD<lhs_FP, lhs_T, std::is_integral<Arithmetic>::value ? 0 : lhs_FP, lhs_T>(-Fixpoint<lhs_FP, lhs_T>(rhs).InternalRepresentation(), Fixpoint<std::is_integral<Arithmetic>::value ? 0 : lhs_FP, lhs_T>(lhs).InternalRepresentation()); } //Multiply-Add optimization template<int mullhs_FP, typename mullhs_T, int mulrhs_FP, typename mulrhs_T> inline constexpr ArbitraryADD<lhs_FP, lhs_T, mullhs_FP+mulrhs_FP, typename ArbitraryMUL<mullhs_FP, mullhs_T, mulrhs_FP, mulrhs_T>::DoubleSizeType> operator - (const ArbitraryMUL<mullhs_FP, mullhs_T, mulrhs_FP, mulrhs_T>& mul) const { const lhs_T rhs_shifted = lhs_FP > rhs_FP ? rhs << staitc_abs<lhs_FP-rhs_FP>::value : rhs >> staitc_abs<rhs_FP-lhs_FP>::value; return ArbitraryADD<lhs_FP, lhs_T, mullhs_FP+mulrhs_FP, typename ArbitraryMUL<mullhs_FP, mullhs_T, mulrhs_FP, mulrhs_T>::DoubleSizeType>(lhs+rhs_shifted, -mul.Result()); } // ************************************************************************************************************ template<int ret_FP, typename ret_T> inline constexpr ArbitraryMUL<lhs_FP, lhs_T, ret_FP, ret_T> operator * (const Fixpoint<ret_FP, ret_T>& _rhs) const { return ArbitraryMUL<lhs_FP, lhs_T, ret_FP, ret_T>(Fixpoint<lhs_FP, lhs_T>(*this).Data, _rhs.Data); } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type > inline constexpr ArbitraryMUL<lhs_FP, lhs_T, std::is_integral<Arithmetic>::value ? 0: lhs_FP, lhs_T> operator * (const Arithmetic& _rhs) const { return ArbitraryMUL<lhs_FP, lhs_T, std::is_integral<Arithmetic>::value ? 0: lhs_FP, lhs_T>(Fixpoint<lhs_FP, lhs_T>(*this).Data, Fixpoint<std::is_integral<Arithmetic>::value ? 0: lhs_FP, lhs_T>(_rhs).Data); } template<typename mul_T> inline constexpr ArbitraryMUL<lhs_FP, lhs_T, mul_T::lhs_prec, typename mul_T::lhs_type> operator * (const mul_T& _rhs) const { return ArbitraryMUL<lhs_FP, lhs_T, mul_T::lhs_prec, typename mul_T::lhs_type>( Fixpoint<lhs_FP, lhs_T>(*this).Data, Fixpoint<mul_T::lhs_prec, typename mul_T::lhs_type>(_rhs).Data); } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type > friend inline constexpr ArbitraryMUL<lhs_FP, lhs_T, std::is_integral<Arithmetic>::value ? 0 : lhs_FP, lhs_T> operator * (Arithmetic lhs, const type& rhs) { return ArbitraryMUL<lhs_FP, lhs_T, std::is_integral<Arithmetic>::value ? 0 : lhs_FP, lhs_T>(Fixpoint<lhs_FP, lhs_T>(rhs).InternalRepresentation(), Fixpoint<std::is_integral<Arithmetic>::value ? 0 : lhs_FP, lhs_T>(lhs).InternalRepresentation()); } // //////////////////////////////////////////////////////////////////////////////////////////////////////////// template<int ret_FP, typename ret_T> inline constexpr ArbitraryDIV<lhs_FP, lhs_T, ret_FP, ret_T> operator / (const Fixpoint<ret_FP, ret_T>& _rhs) const { return ArbitraryMUL<lhs_FP, lhs_T, ret_FP, ret_T>(Fixpoint<lhs_FP, lhs_T>(*this).Data, _rhs.Data); } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type> inline constexpr ArbitraryDIV<lhs_FP, lhs_T, std::is_integral<Arithmetic>::value ? 0: lhs_FP, lhs_T> operator / (const Arithmetic& _rhs) const { return ArbitraryDIV<lhs_FP, lhs_T, std::is_integral<Arithmetic>::value ? 0: lhs_FP, lhs_T>(Fixpoint<lhs_FP, lhs_T>(*this).Data, Fixpoint<std::is_integral<Arithmetic>::value ? 0: lhs_FP, lhs_T>(_rhs).Data); } template<typename div_T> inline constexpr ArbitraryDIV<lhs_FP, lhs_T, div_T::lhs_prec, typename div_T::lhs_type> operator / (const div_T& _rhs) const { return ArbitraryDIV<lhs_FP, lhs_T, div_T::lhs_prec, typename div_T::lhs_type>( Fixpoint<lhs_FP, lhs_T>(*this).Data, Fixpoint<div_T::lhs_prec, typename div_T::lhs_type>(_rhs).Data); } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type > friend inline constexpr ArbitraryDIV<lhs_FP, lhs_T, std::is_integral<Arithmetic>::value ? 0 : lhs_FP, lhs_T> operator / (Arithmetic lhs, const type& rhs) { return ArbitraryDIV<lhs_FP, lhs_T, std::is_integral<Arithmetic>::value ? 0 : lhs_FP, lhs_T>(Fixpoint<lhs_FP, lhs_T>(rhs).InternalRepresentation(), Fixpoint<std::is_integral<Arithmetic>::value ? 0 : lhs_FP, lhs_T>(lhs).InternalRepresentation()); } private: const lhs_T lhs; const rhs_T rhs; }; //***************************************************************************************************************************************************** //***************************************************************************************************************************************************** //***************************************************************************************************************************************************** template <int lhs_FP, typename lhs_T, int rhs_FP, typename rhs_T> struct ArbitraryMUL { static constexpr int lhs_prec = lhs_FP; static constexpr FixpointOperationAggregate Operation = foaArbitraryMUL; using lhs_type = lhs_T; using DoubleSizeType = typename SDoubleWidth<typename SBiggerType<lhs_T, rhs_T>::type>::type; using type = ArbitraryMUL<lhs_FP, lhs_T, rhs_FP, rhs_T>; template<int, typename, int, typename> friend struct ArbitraryMUL; template<int, typename, int, typename> friend struct ArbitraryDIV; inline ArbitraryMUL(const lhs_T& _lhs, const rhs_T& _rhs) : lhs(_lhs), rhs(_rhs) {} inline constexpr DoubleSizeType Result() const { return DoubleSizeType(lhs)*DoubleSizeType(rhs); } template<int ret_FP, typename ret_T> inline constexpr operator Fixpoint<ret_FP, ret_T>() const { constexpr int ResultShift = (lhs_FP + rhs_FP) - ret_FP; if (ResultShift >= 0) return Fixpoint<ret_FP, ret_T>::ConstructRaw(Result() >> staitc_abs<ResultShift>::value); else return Fixpoint<ret_FP, ret_T>::ConstructRaw(Result() << staitc_abs<ResultShift>::value); } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ template<int add_FP, typename add_T> inline constexpr ArbitraryADD<lhs_FP + rhs_FP, DoubleSizeType, add_FP, add_T> operator + (const Fixpoint<add_FP, add_T>& add) const { return ArbitraryADD<lhs_FP + rhs_FP, DoubleSizeType, add_FP, add_T>(Result(), add.Data); } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type > inline constexpr ArbitraryADD<lhs_FP + rhs_FP, DoubleSizeType, std::is_integral<Arithmetic>::value ? 0 : lhs_FP, lhs_T> operator + (const Arithmetic& _rhs) const { return ArbitraryADD<lhs_FP + rhs_FP, DoubleSizeType, std::is_integral<Arithmetic>::value ? 0 : lhs_FP, lhs_T>(Result(), Fixpoint<std::is_integral<Arithmetic>::value ? 0 : lhs_FP, lhs_T>(_rhs).Data); } template<typename add_T> inline constexpr ArbitraryADD<lhs_FP + rhs_FP, DoubleSizeType, add_T::lhs_prec, typename add_T::lhs_type> operator + (const add_T& _rhs) const { return ArbitraryADD<lhs_FP + rhs_FP, DoubleSizeType, add_T::lhs_prec, typename add_T::lhs_type>( Result(), Fixpoint<add_T::lhs_prec, typename add_T::lhs_type>(_rhs).Data); } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type > friend inline constexpr ArbitraryADD<lhs_FP, lhs_T, std::is_integral<Arithmetic>::value ? 0 : lhs_FP, lhs_T> operator + (Arithmetic lhs, const type& rhs) { return ArbitraryADD<lhs_FP, lhs_T, std::is_integral<Arithmetic>::value ? 0 : lhs_FP, lhs_T>(Fixpoint<lhs_FP, lhs_T>(rhs).InternalRepresentation(), Fixpoint<std::is_integral<Arithmetic>::value ? 0 : lhs_FP, lhs_T>(lhs).InternalRepresentation()); } // Multiply-Add optimization template <int madlhs_FP, typename madlhs_T, int madrhs_FP, typename madrhs_T> inline constexpr ArbitraryADD<lhs_FP + rhs_FP, DoubleSizeType, madlhs_FP+madrhs_FP, typename ArbitraryMUL<madlhs_FP, madlhs_T, madrhs_FP, madrhs_T>::DoubleSizeType> operator + (const ArbitraryMUL<madlhs_FP, madlhs_T, madrhs_FP, madrhs_T>& _rhs) const { return ArbitraryADD<lhs_FP + rhs_FP, DoubleSizeType, madlhs_FP+madrhs_FP, typename ArbitraryMUL<madlhs_FP, madlhs_T, madrhs_FP, madrhs_T>::DoubleSizeType>(Result(), _rhs.Result()); } //--------------------------------------------------------------------------------------------------------------------------------------------------------------- template<int add_FP, typename add_T> inline constexpr ArbitraryADD<lhs_FP + rhs_FP, DoubleSizeType, add_FP, add_T> operator - (const Fixpoint<add_FP, add_T>& _rhs) const { return ArbitraryADD<lhs_FP + rhs_FP, DoubleSizeType, add_FP, add_T>(Result(), -_rhs.Data); } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type > inline constexpr ArbitraryADD<lhs_FP + rhs_FP, DoubleSizeType, std::is_integral<Arithmetic>::value ? 0 : lhs_FP, lhs_T> operator - (const Arithmetic & _rhs) const { return ArbitraryADD<lhs_FP + rhs_FP, DoubleSizeType, std::is_integral<Arithmetic>::value ? 0 : lhs_FP, lhs_T>(Result(), -Fixpoint<std::is_integral<Arithmetic>::value ? 0 : lhs_FP, lhs_T>(_rhs).Data); } template<typename add_T> inline constexpr ArbitraryADD<lhs_FP + rhs_FP, DoubleSizeType, add_T::lhs_prec, typename add_T::lhs_type> operator - (const add_T& _rhs) const { return ArbitraryADD<lhs_FP + rhs_FP, DoubleSizeType, add_T::lhs_prec, typename add_T::lhs_type>( Result(), -Fixpoint<add_T::lhs_prec, typename add_T::lhs_type>(_rhs).Data); } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type > friend inline constexpr ArbitraryADD<lhs_FP, lhs_T, std::is_integral<Arithmetic>::value ? 0 : lhs_FP, lhs_T> operator - (Arithmetic lhs, const type& rhs) { return ArbitraryADD<lhs_FP, lhs_T, std::is_integral<Arithmetic>::value ? 0 : lhs_FP, lhs_T>(-Fixpoint<lhs_FP, lhs_T>(rhs).InternalRepresentation(), Fixpoint<std::is_integral<Arithmetic>::value ? 0 : lhs_FP, lhs_T>(lhs).InternalRepresentation()); } // Multiply-Add optimization template <int madlhs_FP, typename madlhs_T, int madrhs_FP, typename madrhs_T> inline constexpr ArbitraryADD<lhs_FP + rhs_FP, DoubleSizeType, madlhs_FP+madrhs_FP, typename ArbitraryMUL<madlhs_FP, madlhs_T, madrhs_FP, madrhs_T>::DoubleSizeType> operator - (const ArbitraryMUL<madlhs_FP, madlhs_T, madrhs_FP, madrhs_T>& add) const { return ArbitraryADD<lhs_FP + rhs_FP, DoubleSizeType, madlhs_FP+madrhs_FP, typename ArbitraryMUL<madlhs_FP, madlhs_T, madrhs_FP, madrhs_T>::DoubleSizeType>(Result(), -add.Result()); } // *************************************************************************************************************************************************************** template<int ret_FP, typename ret_T> inline constexpr ArbitraryMUL<lhs_FP, lhs_T, ret_FP, ret_T> operator * (const Fixpoint<ret_FP, ret_T>& _rhs) const { return ArbitraryMUL<lhs_FP, lhs_T, ret_FP, ret_T>(Fixpoint<lhs_FP, lhs_T>(*this).Data, _rhs.Data); } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type> inline constexpr ArbitraryMUL<lhs_FP, lhs_T, std::is_integral<Arithmetic>::value ? 0: lhs_FP, lhs_T> operator * (const Arithmetic& _rhs) const { return ArbitraryMUL<lhs_FP, lhs_T, std::is_integral<Arithmetic>::value ? 0: lhs_FP, lhs_T>(Fixpoint<lhs_FP, lhs_T>(*this).Data, Fixpoint<std::is_integral<Arithmetic>::value ? 0: lhs_FP, lhs_T>(_rhs).Data); } template<typename mul_T> inline constexpr ArbitraryMUL<lhs_FP, lhs_T, mul_T::lhs_prec, typename mul_T::lhs_type> operator * (const mul_T& _rhs) const { return ArbitraryMUL<lhs_FP, lhs_T, mul_T::lhs_prec, typename mul_T::lhs_type>(Fixpoint<lhs_FP, lhs_T>(*this).Data, Fixpoint<mul_T::lhs_prec, typename mul_T::lhs_type>(_rhs).Data); } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type > friend inline constexpr ArbitraryMUL<lhs_FP, lhs_T, std::is_integral<Arithmetic>::value ? 0 : lhs_FP, lhs_T> operator * (const Arithmetic& lhs, const type& rhs) { return ArbitraryMUL<lhs_FP, lhs_T, std::is_integral<Arithmetic>::value ? 0 : lhs_FP, lhs_T>(Fixpoint<lhs_FP, lhs_T>(rhs).InternalRepresentation(), Fixpoint<std::is_integral<Arithmetic>::value ? 0 : lhs_FP, lhs_T>(lhs).InternalRepresentation()); } // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// template<int ret_FP, typename ret_T> inline constexpr ArbitraryDIV<lhs_FP+rhs_FP, DoubleSizeType, ret_FP, ret_T> operator / (const Fixpoint<ret_FP, ret_T>& _rhs) const { return ArbitraryDIV<lhs_FP+rhs_FP, DoubleSizeType, ret_FP, ret_T>(Result(), _rhs.Data); } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type> inline constexpr ArbitraryDIV<lhs_FP+rhs_FP, DoubleSizeType, std::is_integral<Arithmetic>::value ? 0: lhs_FP, lhs_T> operator / (const Arithmetic& _rhs) const { return ArbitraryDIV<lhs_FP+rhs_FP, DoubleSizeType, std::is_integral<Arithmetic>::value ? 0: lhs_FP, lhs_T>(Result(), Fixpoint<std::is_integral<Arithmetic>::value ? 0: lhs_FP, lhs_T>(_rhs).Data); } template<typename div_T> inline constexpr ArbitraryDIV<lhs_FP+rhs_FP, DoubleSizeType, div_T::lhs_prec, typename div_T::lhs_type> operator / (const div_T& _rhs) const { return ArbitraryDIV<lhs_FP+rhs_FP, DoubleSizeType, div_T::lhs_prec, typename div_T::lhs_type>(Result(), Fixpoint<div_T::lhs_prec, typename div_T::lhs_type>(_rhs).Data); } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type > friend inline constexpr ArbitraryDIV<lhs_FP, lhs_T, lhs_FP, lhs_T> operator / (const Arithmetic& lhs, const type& rhs) { //TODO check not involving DoubleSizedType. its an annomaly i cant resolve right now return ArbitraryDIV<lhs_FP, lhs_T, lhs_FP, lhs_T>(Fixpoint<lhs_FP, lhs_T>(lhs).InternalRepresentation(), Fixpoint<lhs_FP, lhs_T>(rhs).InternalRepresentation() ); } private: const lhs_T lhs; const rhs_T rhs; }; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// template <int lhs_FP, typename lhs_T, int rhs_FP, typename rhs_T> struct ArbitraryDIV { static constexpr int lhs_prec = lhs_FP; static constexpr FixpointOperationAggregate Operation = foaArbitraryDIV; using lhs_type = lhs_T; using DoubleSizeType = typename SDoubleWidth<lhs_T>::type; using type = ArbitraryDIV<lhs_FP, lhs_T, rhs_FP, rhs_T>; template<int, typename, int, typename> friend struct ArbitraryDIV; template<int, typename, int, typename> friend struct ArbitraryMUL; template<int, typename, int, typename> friend struct ArbitraryADD; template<int, typename> friend struct Fixpoint; inline ArbitraryDIV(const lhs_T& _lhs, const rhs_T& _rhs) : lhs(_lhs), rhs(_rhs) {} template<int ret_FP, typename ret_T> inline constexpr operator Fixpoint<ret_FP, ret_T>() const { constexpr int result_prec = lhs_FP - rhs_FP; (volatile void)result_prec; if (sizeof(lhs_T) < sizeof(rhs_T)) { if (result_prec < ret_FP) { if (lhs_FP > rhs_FP) { const DoubleSizeType lhs_shift = DoubleSizeType(lhs) << static_clamp<ret_FP - result_prec, 0, sizeof(DoubleSizeType)*8-1>::value; return Fixpoint<ret_FP, ret_T>::ConstructRaw(lhs_shift / rhs); } else { using dst = typename SDoubleWidth<typename SBiggerType<lhs_T, ret_T>::type>::type; constexpr int possiblePrec = ((int)sizeof(rhs_T)-(int)sizeof(lhs_T))*8; constexpr int rhs_correct = ret_FP - result_prec - possiblePrec; const rhs_T rhs_shift = rhs_correct > 0 ? rhs >> static_shift<rhs_correct, rhs_T>::value : rhs << static_shift<-rhs_correct,rhs_T>::value; constexpr unsigned int ActualLeftShift = static_min<(sizeof(dst)-sizeof(lhs))*8, possiblePrec>::value; constexpr unsigned int NeededRightShift = possiblePrec-ActualLeftShift; const dst lhs_shift = dst(lhs) << staitc_abs<ActualLeftShift>::value; return Fixpoint<ret_FP, ret_T>::ConstructRaw( lhs_shift / (rhs_shift >> staitc_abs<NeededRightShift>::value) ); } } else { /*if (lhs_FP >= rhs_FP) */return Fixpoint<ret_FP, ret_T>::ConstructRaw( (lhs / rhs) >> static_shift<result_prec-ret_FP, lhs_T>::value); //else return Fixpoint<ret_FP, ret_T>::ConstructRaw( 0 ); // impossible } } else { if (result_prec < ret_FP) { // constexpr bool ExpandToDoubleSize = int(sizeof(lhs) - sizeof(rhs)) < int(sizeof(ret_T)); if (ExpandToDoubleSize) { const DoubleSizeType lhs_shift = DoubleSizeType(lhs) << static_shift<ret_FP-result_prec, DoubleSizeType>::value; return Fixpoint<ret_FP, ret_T>::ConstructRaw(lhs_shift / rhs); } else { /* Result type is smaller(or equal) than a / b naturally gives. * Example: short = long long / int. * This means, the lhs-shift may overflow here. * This problem only goes unnoticed in conditions like: int = long long / int */ return Fixpoint<ret_FP, ret_T>::ConstructRaw((lhs<<static_shift<ret_FP-result_prec, lhs_T>::value) / rhs); } } else return Fixpoint<ret_FP, ret_T>::ConstructRaw( (lhs / rhs) >> static_shift<result_prec-ret_FP, DoubleSizeType>::value ); } } // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ template<int sub_FP, typename sub_T> inline constexpr ArbitraryADD<lhs_FP, lhs_T, sub_FP, sub_T> operator + (const Fixpoint<sub_FP, sub_T>& _rhs) const { return ArbitraryADD<lhs_FP, lhs_T, sub_FP, sub_T>( Fixpoint<lhs_FP, lhs_T>(*this).Data, _rhs.Data); } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type > inline constexpr ArbitraryADD<lhs_FP, lhs_T, std::is_integral<Arithmetic>::value ? 0 : lhs_FP, lhs_T> operator + (const Arithmetic& _rhs) { return ArbitraryADD<lhs_FP, lhs_T, std::is_integral<Arithmetic>::value ? 0 : lhs_FP, lhs_T>(Fixpoint<lhs_FP, lhs_T>(*this).Data, Fixpoint<std::is_integral<Arithmetic>::value ? 0 : lhs_FP, lhs_T>(_rhs).Data); } template<typename add_T> inline constexpr ArbitraryADD<lhs_FP, lhs_T, add_T::lhs_prec, typename add_T::lhs_type> operator + (const add_T& _rhs) const { return ArbitraryADD<lhs_FP, lhs_T, add_T::lhs_prec, typename add_T::lhs_type>( Fixpoint<lhs_FP, lhs_T>(*this).Data, +Fixpoint<add_T::lhs_prec, typename add_T::lhs_type>(_rhs).Data); } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type > friend inline constexpr ArbitraryADD<lhs_FP, lhs_T, lhs_FP, lhs_T> operator + (Arithmetic _lhs, const type& _rhs) { return ArbitraryADD<lhs_FP, lhs_T, lhs_FP, lhs_T>(Fixpoint<lhs_FP, lhs_T>(_lhs).InternalRepresentation(), Fixpoint<lhs_FP, lhs_T>(_rhs).InternalRepresentation()); } // ------------------------------------------------------------------------------------------------------------ template<int sub_FP, typename sub_T> inline constexpr ArbitraryADD<lhs_FP, lhs_T, sub_FP, sub_T> operator - (const Fixpoint<sub_FP, sub_T>& _rhs) const { return ArbitraryADD<lhs_FP, lhs_T, sub_FP, sub_T>( Fixpoint<lhs_FP, lhs_T>(*this).Data, -_rhs.Data); } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type > inline constexpr ArbitraryADD<lhs_FP, lhs_T, std::is_integral<Arithmetic>::value ? 0 : lhs_FP, lhs_T> operator - (const Arithmetic& _rhs) { return ArbitraryADD<lhs_FP, lhs_T, std::is_integral<Arithmetic>::value ? 0 : lhs_FP, lhs_T>(Fixpoint<lhs_FP, lhs_T>(*this).Data, -Fixpoint<std::is_integral<Arithmetic>::value ? 0 : lhs_FP, lhs_T>(_rhs).Data); } template<typename sub_T> inline constexpr ArbitraryADD<lhs_FP, lhs_T, sub_T::lhs_prec, typename sub_T::lhs_type> operator - (const sub_T& _rhs) const { return ArbitraryADD<lhs_FP, lhs_T, sub_T::lhs_prec, typename sub_T::lhs_type>( Fixpoint<lhs_FP, lhs_T>(*this).Data, -Fixpoint<sub_T::lhs_prec, typename sub_T::lhs_type>(_rhs).Data); } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type > friend inline constexpr ArbitraryADD<std::is_integral<Arithmetic>::value ? 0 : lhs_FP, lhs_T, lhs_FP, lhs_T> operator - (Arithmetic lhs, const type& rhs) { return ArbitraryADD<std::is_integral<Arithmetic>::value ? 0 : lhs_FP, lhs_T, lhs_FP, lhs_T>(Fixpoint<std::is_integral<Arithmetic>::value ? 0 : lhs_FP, lhs_T>(lhs).InternalRepresentation(), -Fixpoint<lhs_FP, lhs_T>(rhs).InternalRepresentation()); } // ************************************************************************************************************ template<int mul_FP, typename mul_T> inline constexpr ArbitraryDIV<lhs_FP+mul_FP, DoubleSizeType, rhs_FP, rhs_T> operator * (const Fixpoint<mul_FP, mul_T>& _rhs) const { static_assert(sizeof(lhs_T) < sizeof(typename SDoubleWidth<lhs_T>::type), "This construct sadly is undefined due to operand optimization. (a/b)*c * d becomes (a*c)/b * d to avoid shifting of a during division. Please consider (a/b)*(c*d) or Fixpoint<LeftSidePrecision>(a/b*c)*d"); return ArbitraryDIV<lhs_FP+mul_FP, DoubleSizeType, rhs_FP, rhs_T>(ArbitraryMUL<lhs_FP, lhs_T, mul_FP, mul_T>(lhs, _rhs.Data).Result(), rhs); } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type > inline constexpr ArbitraryDIV<lhs_FP + (std::is_integral<Arithmetic>::value ? 0 : lhs_FP), DoubleSizeType, rhs_FP, rhs_T> operator * (const Arithmetic& mul) { return ArbitraryDIV<lhs_FP + (std::is_integral<Arithmetic>::value ? 0 : lhs_FP), DoubleSizeType, rhs_FP, rhs_T>( ArbitraryMUL<lhs_FP, lhs_T, std::is_integral<Arithmetic>::value ? 0 : lhs_FP, lhs_T>(lhs, Fixpoint<std::is_integral<Arithmetic>::value ? 0 : lhs_FP, lhs_T>(mul).InternalRepresentation()).Result(), rhs); } template<typename mul_T> inline constexpr ArbitraryDIV<lhs_FP+mul_T::lhs_prec, DoubleSizeType, rhs_FP, rhs_T> operator * (const mul_T& _rhs) const { static_assert(sizeof(lhs_T) < sizeof(typename SDoubleWidth<lhs_T>::type), "This construct sadly is undefined due to operand optimization. (a/b)*c * d becomes (a*c)/b * d to avoid shifting of a during division. Please consider (a/b)*(c*d) or Fixpoint<LeftSidePrecision>(a/b*c)*d"); return (*this) * Fixpoint< mul_T::lhs_prec, typename mul_T::lhs_type>(_rhs); } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type > friend inline constexpr ArbitraryDIV<lhs_FP + (std::is_integral<Arithmetic>::value ? 0 : lhs_FP), DoubleSizeType, rhs_FP, rhs_T> operator * (Arithmetic lhs, const type& rhs) { return ArbitraryDIV<lhs_FP + (std::is_integral<Arithmetic>::value ? 0 : lhs_FP), DoubleSizeType, rhs_FP, rhs_T>( ArbitraryMUL<lhs_FP, lhs_T, std::is_integral<Arithmetic>::value ? 0 : lhs_FP, lhs_T>(rhs.lhs, Fixpoint<std::is_integral<Arithmetic>::value ? 0 : lhs_FP, lhs_T>(lhs).InternalRepresentation()).Result(), rhs.rhs); } // //////////////////////////////////////////////////////////////////////////////////////////////////////////// template<int div_FP, typename div_T> inline constexpr ArbitraryDIV<lhs_FP, lhs_T, div_FP+rhs_FP, typename ArbitraryMUL<rhs_FP, rhs_T, div_FP, div_T>::DoubleSizeType> operator / (const Fixpoint<div_FP, div_T>& _rhs) const { static_assert(sizeof(rhs_T) < sizeof(typename SDoubleWidth<rhs_T>::type), "Sadly this construct is undefined due to operand optimization. Constructs like (a/b)/c/d become a/(b*c) / d. Please consider a/(b*c*d) directly or Fixpoint<LeftSidePrecision>(a/b/c) / d"); return ArbitraryDIV<lhs_FP, lhs_T, div_FP+rhs_FP, typename ArbitraryMUL<rhs_FP, rhs_T, div_FP, div_T>::DoubleSizeType>(lhs, ArbitraryMUL<rhs_FP, rhs_T, div_FP, div_T>(rhs, _rhs.Data).Result()); } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type > friend inline constexpr ArbitraryDIV<rhs_FP + (std::is_integral<Arithmetic>::value ? 0 : rhs_FP), DoubleSizeType, lhs_FP, lhs_T> operator / (Arithmetic _lhs, const type& _rhs) { return ArbitraryDIV<rhs_FP + (std::is_integral<Arithmetic>::value ? 0 : rhs_FP), DoubleSizeType, lhs_FP, lhs_T>( ArbitraryMUL<rhs_FP, rhs_T, std::is_integral<Arithmetic>::value ? 0 : rhs_FP, rhs_T>(_rhs.rhs, Fixpoint<std::is_integral<Arithmetic>::value ? 0 : rhs_FP, rhs_T>(_lhs).InternalRepresentation()).Result(), _rhs.lhs); } template<typename div_T, typename = typename std::enable_if<div_T::Operation != foaArbitraryDIV>::type> inline constexpr ArbitraryDIV<lhs_FP, lhs_T, rhs_FP+div_T::lhs_prec, DoubleSizeType> operator / (const div_T& _rhs) const { static_assert(sizeof(rhs_T) < sizeof(typename SDoubleWidth<rhs_T>::type), "Sadly this construct is undefined due to operand optimization. Constructs like (a/b)/c/d become a/(b*c) / d. Please consider a/(b*c*d) directly or Fixpoint<LeftSidePrecision>(a/b/c) / d"); return (*this) / Fixpoint< div_T::lhs_prec, typename div_T::lhs_type>(_rhs); } template<int div_lhs_FP, typename div_lhs_T, int div_rhs_FP, typename div_rhs_T> inline constexpr ArbitraryDIV<lhs_FP+div_rhs_FP, typename ArbitraryMUL<lhs_FP, lhs_T, div_rhs_FP, div_rhs_T>::DoubleSizeType, rhs_FP+div_lhs_FP, typename ArbitraryMUL<rhs_FP, rhs_T, div_lhs_FP, div_lhs_T>::DoubleSizeType> operator / (const ArbitraryDIV<div_lhs_FP, div_lhs_T, div_rhs_FP, div_rhs_T>& _rhs) const { constexpr int newlhs_size = sizeof(typename ArbitraryMUL<lhs_FP, lhs_T, div_rhs_FP, div_rhs_T>::DoubleSizeType); constexpr int newrhs_size = sizeof(typename ArbitraryMUL<rhs_FP, rhs_T, div_lhs_FP, div_lhs_T>::DoubleSizeType); static_assert( !(newlhs_size < (sizeof(lhs_T)+sizeof(div_rhs_T))) || (newrhs_size < (sizeof(rhs_T)+sizeof(div_lhs_T))), "Sadly this construct is undefined due to operand optimization. (a/b) / (c/d) becomes (a*d)/(b*c). If either a*d or b*c does not fit into a type you see this error. This can happen if (a/b) is already an optimized expression like (a/b/x) which became a/(b*x)"); return ArbitraryDIV<lhs_FP+div_rhs_FP, typename ArbitraryMUL<lhs_FP, lhs_T, div_rhs_FP, div_rhs_T>::DoubleSizeType, rhs_FP+div_lhs_FP, typename ArbitraryMUL<rhs_FP, rhs_T, div_lhs_FP, div_lhs_T>::DoubleSizeType>(ArbitraryMUL<lhs_FP, lhs_T, div_rhs_FP, div_rhs_T>(lhs, _rhs.rhs).Result(), ArbitraryMUL<rhs_FP, rhs_T, div_lhs_FP, div_lhs_T>(rhs, _rhs.lhs).Result() ); } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type > inline constexpr ArbitraryDIV<lhs_FP, lhs_T, rhs_FP + (std::is_integral<Arithmetic>::value ? 0 : rhs_FP), typename ArbitraryMUL<rhs_FP, rhs_T, std::is_integral<Arithmetic>::value ? 0 : rhs_FP, rhs_T>::DoubleSizeType> operator / (const Arithmetic& div) { static_assert(sizeof(rhs_T) < sizeof(typename ArbitraryMUL<rhs_FP, rhs_T, std::is_integral<Arithmetic>::value ? 0 : rhs_FP, rhs_T>::DoubleSizeType), "Sadly this construct is undefined due to operand optimization. Constructs like (a/b)/c/d become a/(b*c) / d. Please consider a/(b*c*d) directly or Fixpoint<Precision(, Type)>(a/b/c) / d"); return ArbitraryDIV<lhs_FP, lhs_T, rhs_FP + (std::is_integral<Arithmetic>::value ? 0 : rhs_FP), typename ArbitraryMUL<rhs_FP, rhs_T, std::is_integral<Arithmetic>::value ? 0 : rhs_FP, rhs_T>::DoubleSizeType>(lhs, ArbitraryMUL<rhs_FP, rhs_T, std::is_integral<Arithmetic>::value ? 0 : rhs_FP, rhs_T>(rhs, Fixpoint<std::is_integral<Arithmetic>::value ? 0 : rhs_FP, rhs_T>(div).InternalRepresentation()).Result()); } private: const lhs_T lhs; const rhs_T rhs; }; template<int FP, typename T = int> struct Fixpoint { static_assert(FP >= 0, "Negative precision requested - should this mybe allowed ?? It makes sense."); static_assert(sizeof(T)*8 > FP, "Storage type does not have sufficient number bits for your requested precision"); static_assert( std::is_signed<T>::value ? (sizeof(T)*8-1) != FP : true, "Requested precision makes value 1.0 overwrite the sign bit of the underlying type. Try an unsigned type for reduce precision"); static constexpr T One = T(1u)<<T(FP); static constexpr T Precission = FP; using StorageType = T; using type = Fixpoint<FP, T>; using DoubleSizeType = typename SDoubleWidth<T>::type; template<int, typename> friend struct Fixpoint; template<int, typename, int, typename> friend struct ArbitraryADD; template<int, typename, int, typename> friend struct ArbitraryMUL; template<int, typename, int, typename> friend struct ArbitraryDIV; Fixpoint(): Data(0) {}; inline Fixpoint(const type& t): Data(t.Data) { } template<typename InitType, typename = typename std::enable_if<std::is_arithmetic<InitType>::value>::type > inline Fixpoint(const InitType& t): Data(T(t*One)) {}; template<int rhs_FP, typename rhs_T> inline constexpr Fixpoint(const Fixpoint<rhs_FP, rhs_T>& rhs) { if (FP > rhs_FP) Data = rhs.Data << staitc_abs<rhs_FP-FP>::value; else Data = rhs.Data >> staitc_abs<rhs_FP-FP>::value; } // ================================================================================================================================================= template<int rhs_FP, typename rhs_T> inline constexpr type& operator=(const Fixpoint<rhs_FP, rhs_T>& rhs) { if (FP > rhs_FP) Data = rhs.Data << staitc_abs<rhs_FP-FP>::value; else Data = rhs.Data >> staitc_abs<rhs_FP-FP>::value; return *this; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ template<int rhs_FP, typename rhs_T> inline constexpr ArbitraryADD<FP, T, rhs_FP, rhs_T> operator + (const Fixpoint<rhs_FP, rhs_T>& rhs) const { return ArbitraryADD<FP, T, rhs_FP, rhs_T>(Data, rhs.Data); } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type > inline constexpr ArbitraryADD<FP, T, std::is_integral<Arithmetic>::value ? 0: FP, T> operator + (const Arithmetic & rhs) const { return ArbitraryADD<FP, T, std::is_integral<Arithmetic>::value ? 0: FP, T>(Data, Fixpoint<std::is_integral<Arithmetic>::value ? 0: FP, T>(rhs).Data); } template<typename add_T> inline constexpr ArbitraryADD<FP, T, add_T::lhs_prec, typename add_T::lhs_type> operator + (const add_T& rhs) const { return ArbitraryADD<FP, T, add_T::lhs_prec, typename add_T::lhs_type>(Data, Fixpoint<add_T::lhs_prec, typename add_T::lhs_type>(rhs).Data); } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type > friend inline constexpr ArbitraryADD<FP, T, std::is_integral<Arithmetic>::value ? 0 : FP, T> operator +(Arithmetic lhs, const type& rhs) { return ArbitraryADD<FP, T, std::is_integral<Arithmetic>::value ? 0 : FP, T>(rhs.InternalRepresentation(), Fixpoint<std::is_integral<Arithmetic>::value ? 0 : FP, T>(lhs).InternalRepresentation()); } // ------------------------------------------------------------------------------------------------------------------------------------------------ template<int rhs_FP, typename rhs_T> inline constexpr ArbitraryADD<FP, T, rhs_FP, rhs_T> operator - (const Fixpoint<rhs_FP, rhs_T>& rhs) const { return ArbitraryADD<FP, T, rhs_FP, rhs_T>(Data, -rhs.Data); } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type > inline constexpr ArbitraryADD<FP, T, std::is_integral<Arithmetic>::value ? 0: FP, T> operator - (const Arithmetic & rhs) const { return ArbitraryADD<FP, T, std::is_integral<Arithmetic>::value ? 0: FP, T>(Data, -Fixpoint<std::is_integral<Arithmetic>::value ? 0: FP, T>(rhs).Data); } template<typename add_T> inline constexpr ArbitraryADD<FP, T, add_T::lhs_prec, typename add_T::lhs_type> operator - (const add_T& rhs) const { return ArbitraryADD<FP, T, add_T::lhs_prec, typename add_T::lhs_type>(Data, -Fixpoint<add_T::lhs_prec, typename add_T::lhs_type>(rhs).Data); } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type > friend inline constexpr ArbitraryADD<FP, T, std::is_integral<Arithmetic>::value ? 0 : FP, T> operator -(Arithmetic lhs, const type& rhs) { return ArbitraryADD<FP, T, std::is_integral<Arithmetic>::value ? 0 : FP, T>(-rhs.InternalRepresentation(), Fixpoint<std::is_integral<Arithmetic>::value ? 0 : FP, T>(lhs).InternalRepresentation()); } //*************************************************************************************************************************************************** template<int rhs_FP, typename rhs_T> inline constexpr ArbitraryMUL<FP, T, rhs_FP, rhs_T> operator * (const Fixpoint<rhs_FP, rhs_T> & rhs) const { return ArbitraryMUL<FP, T, rhs_FP, rhs_T>(Data, rhs.Data); } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type > inline constexpr ArbitraryMUL<FP, T, std::is_integral<Arithmetic>::value ? 0: FP, T> operator * (const Arithmetic & rhs) const { return ArbitraryMUL<FP, T, std::is_integral<Arithmetic>::value ? 0: FP, T>(Data, Fixpoint<std::is_integral<Arithmetic>::value ? 0: FP, T>(rhs).Data); } template<typename mul_T> inline constexpr ArbitraryMUL<FP, T, mul_T::lhs_prec, typename mul_T::lhs_type> operator * (const mul_T& rhs) const { return ArbitraryMUL<FP, T, mul_T::lhs_prec, typename mul_T::lhs_type>(Data, Fixpoint<mul_T::lhs_prec, typename mul_T::lhs_type>(rhs).Data); } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type > friend inline constexpr ArbitraryMUL<FP, T, std::is_integral<Arithmetic>::value ? 0 : FP, T> operator *(Arithmetic lhs, const type& rhs) { return ArbitraryMUL<FP, T, std::is_integral<Arithmetic>::value ? 0 : FP, T>(rhs.InternalRepresentation(), Fixpoint<std::is_integral<Arithmetic>::value ? 0 : FP, T>(lhs).InternalRepresentation()); } // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// template<int rhs_FP, typename rhs_T> inline constexpr ArbitraryDIV<FP, T, rhs_FP, rhs_T> operator / (const Fixpoint<rhs_FP, rhs_T> & rhs) const { return ArbitraryDIV<FP, T, rhs_FP, rhs_T>(Data, rhs.Data); } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type > inline constexpr ArbitraryDIV<FP, T, std::is_integral<Arithmetic>::value ? 0: FP, T> operator / (const Arithmetic & rhs) const { return ArbitraryDIV<FP, T, std::is_integral<Arithmetic>::value ? 0: FP, T>(Data, Fixpoint<std::is_integral<Arithmetic>::value ? 0: FP, T>(rhs).Data); } template<typename div_T> inline constexpr ArbitraryDIV<FP, T, div_T::lhs_prec, typename div_T::lhs_type> operator / (const div_T& rhs) const { static_assert( sizeof(typename div_T::lhs_type) < sizeof(DoubleSizeType), "Sadly this construct is undefined due to operand optimization. a/(b/c/d) becomes a/[(b*d)/c]. Try a/Fixpoint<LeftSidePrecision>(b/c/d)"); return ArbitraryDIV<FP, T, div_T::lhs_prec, typename div_T::lhs_type>(Data, Fixpoint<div_T::lhs_prec, typename div_T::lhs_type>(rhs).Data); } template<int divrhs_FP, typename divrhs_T, int divlhs_FP, typename divlhs_T, typename = typename std::enable_if<static_max<sizeof(divlhs_T), sizeof(divrhs_T)>::value < sizeof(DoubleSizeType)>::type > inline constexpr ArbitraryDIV<FP+divrhs_FP, DoubleSizeType, divlhs_FP, divlhs_T> operator / (const ArbitraryDIV<divlhs_FP, divlhs_T, divrhs_FP, divrhs_T> & div) const { return ArbitraryDIV<FP+divrhs_FP, DoubleSizeType, divlhs_FP, divlhs_T> //divrhs_T prüfen ( ArbitraryMUL<FP, T, divlhs_FP, divlhs_T>(Data, div.rhs).Result(), div.lhs); } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type > friend inline constexpr ArbitraryDIV<std::is_integral<Arithmetic>::value ? 0 : FP, T, FP, T> operator / (Arithmetic lhs, const type& rhs) { return ArbitraryDIV<std::is_integral<Arithmetic>::value ? 0 : FP, T, FP, T>(Fixpoint<std::is_integral<Arithmetic>::value ? 0 : FP, T>(lhs).InternalRepresentation(), rhs.InternalRepresentation()); } template<typename rhs_T> Fixpoint& operator += (const rhs_T& rhs) { *this = *this + rhs; return *this; } template<typename rhs_T> Fixpoint& operator -= (const rhs_T& rhs) { *this = *this - rhs; return *this; } template<typename rhs_T> Fixpoint& operator *= (const rhs_T& rhs) { *this = *this * rhs; return *this; } template<typename rhs_T> Fixpoint& operator /= (const rhs_T& rhs) { *this = *this / rhs; return *this; } constexpr inline Fixpoint operator >> (const int& rhs) const { return Fixpoint::ConstructRaw(Data >> rhs); } constexpr inline Fixpoint operator << (const int& rhs) const { return Fixpoint::ConstructRaw(Data << rhs); } Fixpoint& operator >>= (const int& rhs) { Data >>= rhs; return *this; } Fixpoint& operator <<= (const int& rhs) { Data <<= rhs; return *this; } template<int rhs_FP, typename rhs_T> inline constexpr bool operator == (const Fixpoint<rhs_FP, rhs_T> & rhs) const { Fixpoint tmp = rhs; return Data == tmp.Data; } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type> inline constexpr bool operator == (const Arithmetic& rhs) const { Fixpoint tmp = rhs; return Data == tmp.Data; } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type > friend inline constexpr bool operator == (Arithmetic lhs, const type& rhs) { return rhs == lhs; } template<int rhs_FP, typename rhs_T> inline constexpr bool operator != (const Fixpoint<rhs_FP, rhs_T> & rhs) const { Fixpoint tmp = rhs; return Data != tmp.Data; } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type> inline constexpr bool operator != (const Arithmetic& rhs) const { Fixpoint tmp = rhs; return Data != tmp.Data; } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type > friend inline constexpr bool operator != (Arithmetic lhs, const type& rhs) { return rhs != lhs; } template<int rhs_FP, typename rhs_T> inline constexpr bool operator < (const Fixpoint<rhs_FP, rhs_T> & rhs) const { Fixpoint tmp = rhs; return Data < tmp.Data; } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type> inline constexpr bool operator < (const Arithmetic& rhs) const { Fixpoint tmp = rhs; return Data < tmp.Data; } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type > friend inline constexpr bool operator < (Arithmetic lhs, const type& rhs) { return rhs > lhs; } template<int rhs_FP, typename rhs_T> inline constexpr bool operator > (const Fixpoint<rhs_FP, rhs_T> & rhs) const { Fixpoint tmp = rhs; return Data > tmp.Data; } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type> inline constexpr bool operator > (const Arithmetic& rhs) const { Fixpoint tmp = rhs; return Data > tmp.Data; } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type > friend inline constexpr bool operator > (Arithmetic lhs, const type& rhs) { return rhs < lhs; } template<int rhs_FP, typename rhs_T> inline constexpr bool operator <= (const Fixpoint<rhs_FP, rhs_T> & rhs) const { Fixpoint tmp = rhs; return Data <= tmp.Data; } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type> inline constexpr bool operator <= (const Arithmetic& rhs) const { Fixpoint tmp = rhs; return Data <= tmp.Data; } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type > friend inline constexpr bool operator <= (Arithmetic lhs, const type& rhs) { return rhs >= lhs; } template<int rhs_FP, typename rhs_T> inline constexpr bool operator >= (const Fixpoint<rhs_FP, rhs_T> & rhs) const { Fixpoint tmp = rhs; return Data >= tmp.Data; } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type> inline constexpr bool operator >= (const Arithmetic& rhs) const { Fixpoint tmp = rhs; return Data >= tmp.Data; } template<typename Arithmetic, typename = typename std::enable_if<std::is_arithmetic<Arithmetic>::value>::type > friend inline constexpr bool operator >= (Arithmetic lhs, const type& rhs) { return rhs <= lhs; } constexpr T InternalRepresentation() const { return Data; } inline constexpr float AsFloat() { return float(Data)/float(One); } inline constexpr double AsDouble() { return double(Data)/double(One); } inline constexpr T IntegerPart() { return Data >> FP; } inline constexpr Fixpoint FractionalPart() { return ConstructRaw(Data & ((T(1)<<FP)-1)); } private: T Data; template<typename Input_t> static inline Fixpoint<FP, T> ConstructRaw(const Input_t& Data) { Fixpoint<FP, T> retval; retval.Data = ShrinkType<T>(Data); return retval; } }; #endif -- You are receiving this mail because: You are watching all bug changes.