Bug 371013 - some code not highlighted properly
Summary: some code not highlighted properly
Status: RESOLVED WORKSFORME
Alias: None
Product: kdevelop
Classification: Applications
Component: Language Support: CPP (Clang-based) (show other bugs)
Version: 5.0.2
Platform: Other Linux
: NOR normal
Target Milestone: ---
Assignee: kdevelop-bugs-null
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-10-17 18:24 UTC by Sven Brauch
Modified: 2022-11-25 05:22 UTC (History)
2 users (show)

See Also:
Latest Commit:
Version Fixed In:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Sven Brauch 2016-10-17 18:24:13 UTC
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
Comment 1 Justin Zobel 2022-10-26 03:07:23 UTC
Thank you for reporting this bug in KDE software. As it has been a while since this issue was reported, can we please ask you to see if you can reproduce the issue with a recent software version?

If you can reproduce the issue, please change the status to "REPORTED" when replying. Thank you!
Comment 2 Bug Janitor Service 2022-11-10 05:12:31 UTC
Dear Bug Submitter,

This bug has been in NEEDSINFO status with no change for at least
15 days. Please provide the requested information as soon as
possible and set the bug status as REPORTED. Due to regular bug
tracker maintenance, if the bug is still in NEEDSINFO status with
no change in 30 days the bug will be closed as RESOLVED > WORKSFORME
due to lack of needed information.

For more information about our bug triaging procedures please read the
wiki located here:
https://community.kde.org/Guidelines_and_HOWTOs/Bug_triaging

If you have already provided the requested information, please
mark the bug as REPORTED so that the KDE team knows that the bug is
ready to be confirmed.

Thank you for helping us make KDE software even better for everyone!
Comment 3 Bug Janitor Service 2022-11-25 05:22:44 UTC
This bug has been in NEEDSINFO status with no change for at least
30 days. The bug is now closed as RESOLVED > WORKSFORME
due to lack of needed information.

For more information about our bug triaging procedures please read the
wiki located here:
https://community.kde.org/Guidelines_and_HOWTOs/Bug_triaging

Thank you for helping us make KDE software even better for everyone!