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.

Reply via email to