From 8cc3094f7be961100e62e56a982369c9862d8cdb Mon Sep 17 00:00:00 2001 From: Pharap <2933055+Pharap@users.noreply.github.com> Date: Mon, 4 Jun 2018 19:48:36 +0100 Subject: [PATCH] Test commit of 0 integer fixed points --- src/FixedPoints/FixedPoints.h | 3 + src/FixedPoints/SFixed0.h | 128 ++++++++++++++ src/FixedPoints/SFixed0FreeFunctions.h | 209 +++++++++++++++++++++++ src/FixedPoints/SFixed0MemberFunctions.h | 191 +++++++++++++++++++++ src/FixedPoints/UFixed0.h | 128 ++++++++++++++ src/FixedPoints/UFixed0FreeFunctions.h | 209 +++++++++++++++++++++++ src/FixedPoints/UFixed0MemberFunctions.h | 175 +++++++++++++++++++ src/FixedPoints/Utils.h | 26 ++- 8 files changed, 1068 insertions(+), 1 deletion(-) create mode 100644 src/FixedPoints/SFixed0.h create mode 100644 src/FixedPoints/SFixed0FreeFunctions.h create mode 100644 src/FixedPoints/SFixed0MemberFunctions.h create mode 100644 src/FixedPoints/UFixed0.h create mode 100644 src/FixedPoints/UFixed0FreeFunctions.h create mode 100644 src/FixedPoints/UFixed0MemberFunctions.h diff --git a/src/FixedPoints/FixedPoints.h b/src/FixedPoints/FixedPoints.h index 8325e36..6cffad7 100644 --- a/src/FixedPoints/FixedPoints.h +++ b/src/FixedPoints/FixedPoints.h @@ -17,4 +17,7 @@ #include "UFixed.h" #include "SFixed.h" +#include "UFixed0.h" +#include "SFixed0.h" + #include "Utils.h" \ No newline at end of file diff --git a/src/FixedPoints/SFixed0.h b/src/FixedPoints/SFixed0.h new file mode 100644 index 0000000..46dc02a --- /dev/null +++ b/src/FixedPoints/SFixed0.h @@ -0,0 +1,128 @@ +// Copyright 2017-2018 Pharap +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "Details.h" + +FIXED_POINTS_BEGIN_NAMESPACE + +// +// Declaration +// + +// Predeclaration +template< unsigned Integer, unsigned Fraction > class SFixed; + +template< unsigned Fraction > +class SFixed<0, Fraction> +{ +public: + constexpr const static uintmax_t IntegerSize = 1; + constexpr const static uintmax_t FractionSize = Fraction; + constexpr const static uintmax_t LogicalSize = IntegerSize + FractionSize; + constexpr const static uintmax_t Scale = UINTMAX_C(1) << FractionSize; + +public: + static_assert(LogicalSize <= FIXED_POINTS_DETAILS::BitSize::Value, "Platform does not have a native type large enough for SFixed."); + +public: + using IntegerType = FIXED_POINTS_DETAILS::LeastInt; + using FractionType = FIXED_POINTS_DETAILS::LeastUInt; + using InternalType = FIXED_POINTS_DETAILS::LeastInt; + + constexpr const static uintmax_t InternalSize = FIXED_POINTS_DETAILS::BitSize::Value; + + using ShiftType = FIXED_POINTS_DETAILS::LeastUInt; + using MaskType = FIXED_POINTS_DETAILS::LeastUInt; + +public: + constexpr const static ShiftType IntegerShift = FractionSize; + constexpr const static ShiftType FractionShift = 0; + + constexpr const static MaskType IntegerMask = FIXED_POINTS_DETAILS::IdentityMask::Value; + constexpr const static MaskType FractionMask = FIXED_POINTS_DETAILS::IdentityMask::Value; + + constexpr const static MaskType IdentityMask = (IntegerMask << IntegerShift) | (FractionMask << FractionShift); + + constexpr const static MaskType MidpointMask = FIXED_POINTS_DETAILS::MsbMask::Value; + constexpr const static MaskType LesserMidpointMask = MidpointMask - 1; + +protected: + class RawType + { + private: + const InternalType value; + + public: + constexpr inline explicit RawType(const InternalType & value) : value(value) {} + constexpr inline explicit operator InternalType(void) const { return this->value; } + }; + +protected: + InternalType value; + +protected: + constexpr SFixed(const RawType & value); + +public: + constexpr SFixed(void); + constexpr SFixed(const IntegerType & integer, const FractionType & fraction); + constexpr SFixed(const char & value) = delete; + constexpr SFixed(const unsigned char & value) = delete; + constexpr SFixed(const signed char & value) = delete; + constexpr SFixed(const unsigned short int & value) = delete; + constexpr SFixed(const signed short int & value) = delete; + constexpr SFixed(const unsigned int & value) = delete; + constexpr SFixed(const signed int & value) = delete; + constexpr SFixed(const unsigned long int & value) = delete; + constexpr SFixed(const signed long int & value) = delete; + constexpr SFixed(const unsigned long long int & value) = delete; + constexpr SFixed(const signed long long int & value) = delete; + constexpr SFixed(const double & value); + constexpr SFixed(const float & value); + constexpr SFixed(const long double & value); + + constexpr InternalType getInternal(void) const; + constexpr IntegerType getInteger(void) const; + constexpr FractionType getFraction(void) const; + + constexpr explicit operator IntegerType(void) const; + constexpr explicit operator float(void) const; + constexpr explicit operator double(void) const; + constexpr explicit operator long double(void) const; + + template< unsigned IntegerOut, unsigned FractionOut > + constexpr explicit operator SFixed(void) const; + + constexpr static SFixed fromInternal(const InternalType & value); + + constexpr SFixed operator -(void) const; + SFixed & operator +=(const SFixed & other); + SFixed & operator -=(const SFixed & other); + SFixed & operator *=(const SFixed & other); + SFixed & operator /=(const SFixed & other); + +public: + constexpr const static SFixed Epsilon = SFixed::fromInternal(1); + constexpr const static SFixed MinValue = SFixed::fromInternal(FIXED_POINTS_DETAILS::MsbMask::Value); + constexpr const static SFixed MaxValue = SFixed::fromInternal(~FIXED_POINTS_DETAILS::MsbMask::Value); + + // Pi, E, Phi and Tau will never be representable by 0 integer fixed points +}; + +FIXED_POINTS_END_NAMESPACE + +#include "SFixed0MemberFunctions.h" +#include "SFixed0FreeFunctions.h" \ No newline at end of file diff --git a/src/FixedPoints/SFixed0FreeFunctions.h b/src/FixedPoints/SFixed0FreeFunctions.h new file mode 100644 index 0000000..c54aaa5 --- /dev/null +++ b/src/FixedPoints/SFixed0FreeFunctions.h @@ -0,0 +1,209 @@ +// Copyright 2017-2018 Pharap +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +FIXED_POINTS_BEGIN_NAMESPACE + +// +// Literal-type Operators +// Generated by macro to make maintenance easier +// + +#define LOGIC_OPERATOR( type, op )\ + template< unsigned Fraction >\ + constexpr bool operator op (const SFixed<0, Fraction> & left, const type & right)\ + {\ + return (left op SFixed<0, Fraction>(right));\ + }\ + \ + template< unsigned Fraction >\ + constexpr bool operator op (const type & left, const SFixed<0, Fraction> & right)\ + {\ + return (SFixed<0, Fraction>(left) op right);\ + } + +#define DELETED_LOGIC_OPERATOR_EQ( type )\ + template< unsigned Fraction >\ + constexpr bool operator == (const SFixed<0, Fraction> & left, const type & right)\ + {\ + return false;\ + }\ + \ + template< unsigned Fraction >\ + constexpr bool operator == (const type & left, const SFixed<0, Fraction> & right)\ + {\ + return false;\ + } + +#define DELETED_LOGIC_OPERATOR_NE( type )\ + template< unsigned Fraction >\ + constexpr bool operator != (const SFixed<0, Fraction> & left, const type & right)\ + {\ + return true;\ + }\ + \ + template< unsigned Fraction >\ + constexpr bool operator != (const type & left, const SFixed<0, Fraction> & right)\ + {\ + return true;\ + } + +#define DELETED_LOGIC_OPERATOR_LT( type )\ + template< unsigned Fraction >\ + constexpr bool operator < (const SFixed<0, Fraction> & left, const type & right)\ + {\ + return true;\ + }\ + \ + template< unsigned Fraction >\ + constexpr bool operator < (const type & left, const SFixed<0, Fraction> & right)\ + {\ + return false;\ + } + +#define DELETED_LOGIC_OPERATOR_LTE( type )\ + template< unsigned Fraction >\ + constexpr bool operator <= (const SFixed<0, Fraction> & left, const type & right)\ + {\ + return true;\ + }\ + \ + template< unsigned Fraction >\ + constexpr bool operator <= (const type & left, const SFixed<0, Fraction> & right)\ + {\ + return false;\ + } + +#define DELETED_LOGIC_OPERATOR_GT( type )\ + template< unsigned Fraction >\ + constexpr bool operator > (const SFixed<0, Fraction> & left, const type & right)\ + {\ + return false;\ + }\ + \ + template< unsigned Fraction >\ + constexpr bool operator > (const type & left, const SFixed<0, Fraction> & right)\ + {\ + return true;\ + } + +#define DELETED_LOGIC_OPERATOR_GTE( type )\ + template< unsigned Fraction >\ + constexpr bool operator >= (const SFixed<0, Fraction> & left, const type & right)\ + {\ + return false;\ + }\ + \ + template< unsigned Fraction >\ + constexpr bool operator >= (const type & left, const SFixed<0, Fraction> & right)\ + {\ + return true;\ + } + +#define ARITHMETIC_OPERATOR( type, op )\ + template< unsigned Fraction >\ + constexpr SFixed<0, Fraction> operator op (const SFixed<0, Fraction> & left, const type & right)\ + {\ + return (left op SFixed<0, Fraction>(right));\ + }\ + \ + template< unsigned Fraction >\ + constexpr SFixed<0, Fraction> operator op (const type & left, const SFixed<0, Fraction> & right)\ + {\ + return (SFixed<0, Fraction>(left) op right);\ + } + +#define DELETED_ARITHMETIC_OPERATOR( type, op )\ + template< unsigned Fraction >\ + constexpr SFixed<0, Fraction> operator op (const SFixed<0, Fraction> & left, const type & right)\ + {\ + return 0;\ + }\ + \ + template< unsigned Fraction >\ + constexpr SFixed<0, Fraction> operator op (const type & left, const SFixed<0, Fraction> & right)\ + {\ + return 0;\ + } + +#define LOGIC_OPERATORS( type ) \ + LOGIC_OPERATOR( type, == )\ + LOGIC_OPERATOR( type, != )\ + LOGIC_OPERATOR( type, < )\ + LOGIC_OPERATOR( type, <= )\ + LOGIC_OPERATOR( type, > )\ + LOGIC_OPERATOR( type, >= ) + +#define ARITHMETIC_OPERATORS( type ) \ + ARITHMETIC_OPERATOR( type, + )\ + ARITHMETIC_OPERATOR( type, - )\ + ARITHMETIC_OPERATOR( type, * )\ + ARITHMETIC_OPERATOR( type, / ) + +#define DELETED_LOGIC_OPERATORS( type ) \ + DELETED_LOGIC_OPERATOR_EQ( type )\ + DELETED_LOGIC_OPERATOR_NE( type )\ + DELETED_LOGIC_OPERATOR_LT( type )\ + DELETED_LOGIC_OPERATOR_LTE( type )\ + DELETED_LOGIC_OPERATOR_GT( type )\ + DELETED_LOGIC_OPERATOR_GTE( type ) + +#define DELETED_ARITHMETIC_OPERATORS( type ) \ + DELETED_ARITHMETIC_OPERATOR( type, + )\ + DELETED_ARITHMETIC_OPERATOR( type, - )\ + DELETED_ARITHMETIC_OPERATOR( type, * )\ + DELETED_ARITHMETIC_OPERATOR( type, / ) + +#define OPERATORS( type ) \ + LOGIC_OPERATORS( type )\ + ARITHMETIC_OPERATORS( type ) + +#define DELETED_OPERATORS( type ) \ + DELETED_LOGIC_OPERATORS( type )\ + DELETED_ARITHMETIC_OPERATORS( type ) + +OPERATORS( float ) +OPERATORS( double ) +OPERATORS( long double ) + +DELETED_OPERATORS( char ) +DELETED_OPERATORS( unsigned char ) +DELETED_OPERATORS( signed char ) +DELETED_OPERATORS( unsigned short int ) +DELETED_OPERATORS( signed short int ) +DELETED_OPERATORS( unsigned int ) +DELETED_OPERATORS( signed int ) +DELETED_OPERATORS( unsigned long int ) +DELETED_OPERATORS( signed long int ) +DELETED_OPERATORS( unsigned long long int ) +DELETED_OPERATORS( signed long long int ) + +// Prevent Macro-bleed: + +#undef DELETED_OPERATORS +#undef OPERATORS +#undef DELETED_ARITHMETIC_OPERATORS +#undef DELETED_LOGIC_OPERATORS +#undef ARITHMETIC_OPERATORS +#undef LOGIC_OPERATORS +#undef DELETED_ARITHMETIC_OPERATOR +#undef ARITHMETIC_OPERATOR + +#undef DELETED_LOGIC_OPERATOR_EQ +#undef DELETED_LOGIC_OPERATOR_NE +#undef DELETED_LOGIC_OPERATOR_LT +#undef DELETED_LOGIC_OPERATOR_LTE +#undef DELETED_LOGIC_OPERATOR_GT +#undef DELETED_LOGIC_OPERATOR_GTE + +FIXED_POINTS_END_NAMESPACE \ No newline at end of file diff --git a/src/FixedPoints/SFixed0MemberFunctions.h b/src/FixedPoints/SFixed0MemberFunctions.h new file mode 100644 index 0000000..52372c4 --- /dev/null +++ b/src/FixedPoints/SFixed0MemberFunctions.h @@ -0,0 +1,191 @@ +// Copyright 2017-2018 Pharap +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +FIXED_POINTS_BEGIN_NAMESPACE + +// +// Constructors +// + +template< unsigned Fraction > +constexpr SFixed<0, Fraction>::SFixed(const RawType & value) + : value(static_cast(value)) +{ +} + +template< unsigned Fraction > +constexpr SFixed<0, Fraction>::SFixed(void) + : value(0) +{ +} + +// Here the comma operator is used to circumvent an unused parameter warning +template< unsigned Fraction > +constexpr SFixed<0, Fraction>::SFixed(const IntegerType & integer, const FractionType & fraction) + : value((integer, fraction)) +{ +} + +template< unsigned Fraction > +constexpr SFixed<0, Fraction>::SFixed(const double & value) + : value(static_cast(value * static_cast(Scale))) +{ +} + +template< unsigned Fraction > +constexpr SFixed<0, Fraction>::SFixed(const float & value) + : value(static_cast(value * static_cast(Scale))) +{ +} + +template< unsigned Fraction > +constexpr SFixed<0, Fraction>::SFixed(const long double & value) + : value(static_cast(value * static_cast(Scale))) +{ +} + +// +// Getters +// + +template< unsigned Fraction > +constexpr typename SFixed<0, Fraction>::InternalType SFixed<0, Fraction>::getInternal(void) const +{ + return this->value; +} + +template< unsigned Fraction > +constexpr typename SFixed<0, Fraction>::IntegerType SFixed<0, Fraction>::getInteger(void) const +{ + static_assert(false, "UNDEFINED BEHAVIOUR"); + //return (static_cast(this->value >> IntegerShift) & IntegerMask) | ((this->value < 0) ? ~IntegerMask : 0); +} + +template< unsigned Fraction > +constexpr typename SFixed<0, Fraction>::FractionType SFixed<0, Fraction>::getFraction(void) const +{ + return static_cast(this->value >> FractionShift) & FractionMask; +} + +// +// Cast Operators +// + +template< unsigned Fraction > +constexpr SFixed<0, Fraction>::operator IntegerType(void) const +{ + return this->getInteger(); +} + +template< unsigned Fraction > +constexpr SFixed<0, Fraction>::operator float(void) const +{ + return (1.0F / Scale) * + static_cast + ((this->value & IdentityMask) | + ((this->value < 0) ? ~IdentityMask : 0)); +} + +template< unsigned Fraction > +constexpr SFixed<0, Fraction>::operator double(void) const +{ + return (1.0 / Scale) * + static_cast + ((this->value & IdentityMask) | + ((this->value < 0) ? ~IdentityMask : 0)); +} + +template< unsigned Fraction > +constexpr SFixed<0, Fraction>::operator long double(void) const +{ + return (1.0L / Scale) * + static_cast + ((this->value & IdentityMask) | + ((this->value < 0) ? ~IdentityMask : 0)); +} + +template< unsigned Fraction > +template< unsigned IntegerOut, unsigned FractionOut > +constexpr SFixed<0, Fraction>::operator SFixed(void) const +{ + using OutputType = SFixed; + using OutputInternalType = typename OutputType::InternalType; + using OutputShiftType = typename OutputType::ShiftType; + + using InputType = SFixed<0, Fraction>; + using InputShiftType = typename InputType::ShiftType; + + return + (FractionOut > FractionSize) ? + OutputType::fromInternal(static_cast(static_cast(this->value) << ((FractionOut > FractionSize) ? (FractionOut - FractionSize) : 0))) : + (FractionSize > FractionOut) ? + OutputType::fromInternal(static_cast(static_cast(this->value) >> ((FractionSize > FractionOut) ? (FractionSize - FractionOut) : 0))) : + OutputType::fromInternal(this->value); +} + +// +// Static Functions +// + +template< unsigned Fraction > +constexpr SFixed<0, Fraction> SFixed<0, Fraction>::fromInternal(const typename SFixed<0, Fraction>::InternalType & value) +{ + return SFixed<0, Fraction>(RawType(value)); +} + +template< unsigned Fraction > +constexpr SFixed<0, Fraction> SFixed<0, Fraction>::operator -(void) const +{ + return SFixed<0, Fraction>::fromInternal(-this->value); +} + +// +// Compound Assignment Operators +// + +template< unsigned Fraction > +SFixed<0, Fraction> & SFixed<0, Fraction>::operator +=(const SFixed<0, Fraction> & other) +{ + this->value += other.value; + return *this; +} + +template< unsigned Fraction > +SFixed<0, Fraction> & SFixed<0, Fraction>::operator -=(const SFixed<0, Fraction> & other) +{ + this->value -= other.value; + return *this; +} + +template< unsigned Fraction > +SFixed<0, Fraction> & SFixed<0, Fraction>::operator *=(const SFixed<0, Fraction> & other) +{ + using InternalType = typename SFixed<0, Fraction>::InternalType; + using PrecisionType = typename SFixed::InternalType; + const PrecisionType temp = (static_cast(this->value) * static_cast(other.value)) >> Fraction; + this->value = static_cast(temp); + return *this; +} + +template< unsigned Fraction > +SFixed<0, Fraction> & SFixed<0, Fraction>::operator /=(const SFixed<0, Fraction> & other) +{ + using InternalType = typename SFixed<0, Fraction>::InternalType; + using PrecisionType = typename SFixed::InternalType; + const PrecisionType temp = (static_cast(this->value) << Fraction) / static_cast(other.value); + this->value = static_cast(temp); + return *this; +} + +FIXED_POINTS_END_NAMESPACE \ No newline at end of file diff --git a/src/FixedPoints/UFixed0.h b/src/FixedPoints/UFixed0.h new file mode 100644 index 0000000..c33fc8e --- /dev/null +++ b/src/FixedPoints/UFixed0.h @@ -0,0 +1,128 @@ +// Copyright 2017-2018 Pharap +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "Details.h" + +FIXED_POINTS_BEGIN_NAMESPACE + +// +// Declaration +// + +// Predeclaration +template< unsigned Integer, unsigned Fraction > class UFixed; + +template< unsigned Fraction > +class UFixed<0, Fraction> +{ +public: + constexpr const static uintmax_t IntegerSize = 0; + constexpr const static uintmax_t FractionSize = Fraction; + constexpr const static uintmax_t LogicalSize = IntegerSize + FractionSize; + constexpr const static uintmax_t Scale = UINTMAX_C(1) << FractionSize; + +public: + static_assert(LogicalSize <= FIXED_POINTS_DETAILS::BitSize::Value, "Platform does not have a native type large enough for UFixed."); + +public: + using IntegerType = FIXED_POINTS_DETAILS::LeastUInt; + using FractionType = FIXED_POINTS_DETAILS::LeastUInt; + using InternalType = FIXED_POINTS_DETAILS::LeastUInt; + + constexpr const static uintmax_t InternalSize = FIXED_POINTS_DETAILS::BitSize::Value; + + using ShiftType = FIXED_POINTS_DETAILS::LeastUInt; + using MaskType = FIXED_POINTS_DETAILS::LeastUInt; + +public: + constexpr const static ShiftType IntegerShift = FractionSize; + constexpr const static ShiftType FractionShift = 0; + + constexpr const static MaskType IntegerMask = FIXED_POINTS_DETAILS::IdentityMask::Value; + constexpr const static MaskType FractionMask = FIXED_POINTS_DETAILS::IdentityMask::Value; + + constexpr const static MaskType IdentityMask = (IntegerMask << IntegerShift) | (FractionMask << FractionShift); + + constexpr const static MaskType MidpointMask = FIXED_POINTS_DETAILS::MsbMask::Value; + constexpr const static MaskType LesserMidpointMask = MidpointMask - 1; + +protected: + class RawType + { + private: + const InternalType value; + + public: + constexpr inline explicit RawType(const InternalType & value) : value(value) {} + constexpr inline explicit operator InternalType(void) const { return this->value; } + }; + +protected: + InternalType value; + +protected: + constexpr UFixed(const RawType & value); + +public: + constexpr UFixed(void); + constexpr UFixed(const IntegerType & integer, const FractionType & fraction); + constexpr UFixed(const char & value) = delete; + constexpr UFixed(const unsigned char & value) = delete; + constexpr UFixed(const signed char & value) = delete; + constexpr UFixed(const unsigned short int & value) = delete; + constexpr UFixed(const signed short int & value) = delete; + constexpr UFixed(const unsigned int & value) = delete; + constexpr UFixed(const signed int & value) = delete; + constexpr UFixed(const unsigned long int & value) = delete; + constexpr UFixed(const signed long int & value) = delete; + constexpr UFixed(const unsigned long long int & value) = delete; + constexpr UFixed(const signed long long int & value) = delete; + constexpr UFixed(const double & value); + constexpr UFixed(const float & value); + constexpr UFixed(const long double & value); + +public: + constexpr InternalType getInternal(void) const; + constexpr IntegerType getInteger(void) const; + constexpr FractionType getFraction(void) const; + + constexpr explicit operator IntegerType(void) const; + constexpr explicit operator float(void) const; + constexpr explicit operator double(void) const; + constexpr explicit operator long double(void) const; + + template< unsigned IntegerOut, unsigned FractionOut > + constexpr explicit operator UFixed(void) const; + + constexpr static UFixed fromInternal(const InternalType & value); + + UFixed & operator +=(const UFixed & other); + UFixed & operator -=(const UFixed & other); + UFixed & operator *=(const UFixed & other); + UFixed & operator /=(const UFixed & other); + +public: + constexpr const static UFixed Epsilon = UFixed::fromInternal(1); + constexpr const static UFixed MinValue = UFixed::fromInternal(0); + constexpr const static UFixed MaxValue = UFixed::fromInternal(~0); + + // Pi, E, Phi and Tau will never be representable by 0 integer fixed points +}; + +FIXED_POINTS_END_NAMESPACE + +#include "UFixed0MemberFunctions.h" +#include "UFixed0FreeFunctions.h" \ No newline at end of file diff --git a/src/FixedPoints/UFixed0FreeFunctions.h b/src/FixedPoints/UFixed0FreeFunctions.h new file mode 100644 index 0000000..88d8f8c --- /dev/null +++ b/src/FixedPoints/UFixed0FreeFunctions.h @@ -0,0 +1,209 @@ +// Copyright 2017-2018 Pharap +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +FIXED_POINTS_BEGIN_NAMESPACE + +// +// Literal-type Operators +// Generated by macro to make maintenance easier +// + +#define LOGIC_OPERATOR( type, op )\ + template< unsigned Fraction >\ + constexpr bool operator op (const UFixed<0, Fraction> & left, const type & right)\ + {\ + return (left op UFixed<0, Fraction>(right));\ + }\ + \ + template< unsigned Fraction >\ + constexpr bool operator op (const type & left, const UFixed<0, Fraction> & right)\ + {\ + return (UFixed<0, Fraction>(left) op right);\ + } + +#define DELETED_LOGIC_OPERATOR_EQ( type )\ + template< unsigned Fraction >\ + constexpr bool operator == (const UFixed<0, Fraction> & left, const type & right)\ + {\ + return false;\ + }\ + \ + template< unsigned Fraction >\ + constexpr bool operator == (const type & left, const UFixed<0, Fraction> & right)\ + {\ + return false;\ + } + +#define DELETED_LOGIC_OPERATOR_NE( type )\ + template< unsigned Fraction >\ + constexpr bool operator != (const UFixed<0, Fraction> & left, const type & right)\ + {\ + return true;\ + }\ + \ + template< unsigned Fraction >\ + constexpr bool operator != (const type & left, const UFixed<0, Fraction> & right)\ + {\ + return true;\ + } + +#define DELETED_LOGIC_OPERATOR_LT( type )\ + template< unsigned Fraction >\ + constexpr bool operator < (const UFixed<0, Fraction> & left, const type & right)\ + {\ + return true;\ + }\ + \ + template< unsigned Fraction >\ + constexpr bool operator < (const type & left, const UFixed<0, Fraction> & right)\ + {\ + return false;\ + } + +#define DELETED_LOGIC_OPERATOR_LTE( type )\ + template< unsigned Fraction >\ + constexpr bool operator <= (const UFixed<0, Fraction> & left, const type & right)\ + {\ + return true;\ + }\ + \ + template< unsigned Fraction >\ + constexpr bool operator <= (const type & left, const UFixed<0, Fraction> & right)\ + {\ + return false;\ + } + +#define DELETED_LOGIC_OPERATOR_GT( type )\ + template< unsigned Fraction >\ + constexpr bool operator > (const UFixed<0, Fraction> & left, const type & right)\ + {\ + return false;\ + }\ + \ + template< unsigned Fraction >\ + constexpr bool operator > (const type & left, const UFixed<0, Fraction> & right)\ + {\ + return true;\ + } + +#define DELETED_LOGIC_OPERATOR_GTE( type )\ + template< unsigned Fraction >\ + constexpr bool operator >= (const UFixed<0, Fraction> & left, const type & right)\ + {\ + return false;\ + }\ + \ + template< unsigned Fraction >\ + constexpr bool operator >= (const type & left, const UFixed<0, Fraction> & right)\ + {\ + return true;\ + } + +#define ARITHMETIC_OPERATOR( type, op )\ + template< unsigned Fraction >\ + constexpr UFixed<0, Fraction> operator op (const UFixed<0, Fraction> & left, const type & right)\ + {\ + return (left op UFixed<0, Fraction>(right));\ + }\ + \ + template< unsigned Fraction >\ + constexpr UFixed<0, Fraction> operator op (const type & left, const UFixed<0, Fraction> & right)\ + {\ + return (UFixed<0, Fraction>(left) op right);\ + } + +#define DELETED_ARITHMETIC_OPERATOR( type, op )\ + template< unsigned Fraction >\ + constexpr UFixed<0, Fraction> operator op (const UFixed<0, Fraction> & left, const type & right)\ + {\ + return 0;\ + }\ + \ + template< unsigned Fraction >\ + constexpr UFixed<0, Fraction> operator op (const type & left, const UFixed<0, Fraction> & right)\ + {\ + return 0;\ + } + +#define LOGIC_OPERATORS( type ) \ + LOGIC_OPERATOR( type, == )\ + LOGIC_OPERATOR( type, != )\ + LOGIC_OPERATOR( type, < )\ + LOGIC_OPERATOR( type, <= )\ + LOGIC_OPERATOR( type, > )\ + LOGIC_OPERATOR( type, >= ) + +#define ARITHMETIC_OPERATORS( type ) \ + ARITHMETIC_OPERATOR( type, + )\ + ARITHMETIC_OPERATOR( type, - )\ + ARITHMETIC_OPERATOR( type, * )\ + ARITHMETIC_OPERATOR( type, / ) + +#define DELETED_LOGIC_OPERATORS( type ) \ + DELETED_LOGIC_OPERATOR_EQ( type )\ + DELETED_LOGIC_OPERATOR_NE( type )\ + DELETED_LOGIC_OPERATOR_LT( type )\ + DELETED_LOGIC_OPERATOR_LTE( type )\ + DELETED_LOGIC_OPERATOR_GT( type )\ + DELETED_LOGIC_OPERATOR_GTE( type ) + +#define DELETED_ARITHMETIC_OPERATORS( type ) \ + DELETED_ARITHMETIC_OPERATOR( type, + )\ + DELETED_ARITHMETIC_OPERATOR( type, - )\ + DELETED_ARITHMETIC_OPERATOR( type, * )\ + DELETED_ARITHMETIC_OPERATOR( type, / ) + +#define OPERATORS( type ) \ + LOGIC_OPERATORS( type )\ + ARITHMETIC_OPERATORS( type ) + +#define DELETED_OPERATORS( type ) \ + DELETED_LOGIC_OPERATORS( type )\ + DELETED_ARITHMETIC_OPERATORS( type ) + +OPERATORS( float ) +OPERATORS( double ) +OPERATORS( long double ) + +DELETED_OPERATORS( char ) +DELETED_OPERATORS( unsigned char ) +DELETED_OPERATORS( signed char ) +DELETED_OPERATORS( unsigned short int ) +DELETED_OPERATORS( signed short int ) +DELETED_OPERATORS( unsigned int ) +DELETED_OPERATORS( signed int ) +DELETED_OPERATORS( unsigned long int ) +DELETED_OPERATORS( signed long int ) +DELETED_OPERATORS( unsigned long long int ) +DELETED_OPERATORS( signed long long int ) + +// Prevent Macro-bleed: + +#undef DELETED_OPERATORS +#undef OPERATORS +#undef DELETED_ARITHMETIC_OPERATORS +#undef DELETED_LOGIC_OPERATORS +#undef ARITHMETIC_OPERATORS +#undef LOGIC_OPERATORS +#undef DELETED_ARITHMETIC_OPERATOR +#undef ARITHMETIC_OPERATOR + +#undef DELETED_LOGIC_OPERATOR_EQ +#undef DELETED_LOGIC_OPERATOR_NE +#undef DELETED_LOGIC_OPERATOR_LT +#undef DELETED_LOGIC_OPERATOR_LTE +#undef DELETED_LOGIC_OPERATOR_GT +#undef DELETED_LOGIC_OPERATOR_GTE + +FIXED_POINTS_END_NAMESPACE \ No newline at end of file diff --git a/src/FixedPoints/UFixed0MemberFunctions.h b/src/FixedPoints/UFixed0MemberFunctions.h new file mode 100644 index 0000000..b0c0bac --- /dev/null +++ b/src/FixedPoints/UFixed0MemberFunctions.h @@ -0,0 +1,175 @@ +// Copyright 2017-2018 Pharap +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +FIXED_POINTS_BEGIN_NAMESPACE + +// +// Constructors +// + +template< unsigned Fraction > +constexpr UFixed<0, Fraction>::UFixed(const RawType & value) + : value(static_cast(value)) +{ +} + +template< unsigned Fraction > +constexpr UFixed<0, Fraction>::UFixed(void) + : value(0) +{ +} + +// Here the comma operator is used to circumvent an unused parameter warning +template< unsigned Fraction > +constexpr UFixed<0, Fraction>::UFixed(const IntegerType & integer, const FractionType & fraction) + : value((integer, fraction)) +{ +} + +template< unsigned Fraction > +constexpr UFixed<0, Fraction>::UFixed(const double & value) + : value(static_cast(value * static_cast(Scale))) +{ +} + +template< unsigned Fraction > +constexpr UFixed<0, Fraction>::UFixed(const float & value) + : value(static_cast(value * static_cast(Scale))) +{ +} + +template< unsigned Fraction > +constexpr UFixed<0, Fraction>::UFixed(const long double & value) + : value(static_cast(value * static_cast(Scale))) +{ +} + +// +// Getters +// + +template< unsigned Fraction > +constexpr typename UFixed<0, Fraction>::InternalType UFixed<0, Fraction>::getInternal(void) const +{ + return this->value; +} + +template< unsigned Fraction > +constexpr typename UFixed<0, Fraction>::IntegerType UFixed<0, Fraction>::getInteger(void) const +{ + return 0; +} + +template< unsigned Fraction > +constexpr typename UFixed<0, Fraction>::FractionType UFixed<0, Fraction>::getFraction(void) const +{ + return static_cast(this->value) & FractionMask; +} + +// +// Cast Operators +// + +template< unsigned Fraction > +constexpr UFixed<0, Fraction>::operator IntegerType(void) const +{ + return this->getInteger(); +} + +template< unsigned Fraction > +constexpr UFixed<0, Fraction>::operator float(void) const +{ + return ((this->value & IdentityMask) * (1.0F / Scale)); +} + +template< unsigned Fraction > +constexpr UFixed<0, Fraction>::operator double(void) const +{ + return ((this->value & IdentityMask) * (1.0 / Scale)); +} + +template< unsigned Fraction > +constexpr UFixed<0, Fraction>::operator long double(void) const +{ + return ((this->value & IdentityMask) * (1.0L / Scale)); +} + +template< unsigned Fraction > +template< unsigned IntegerOut, unsigned FractionOut > +constexpr UFixed<0, Fraction>::operator UFixed(void) const +{ + using OutputType = UFixed; + using OutputInternalType = typename OutputType::InternalType; + using OutputShiftType = typename OutputType::ShiftType; + + using InputType = UFixed<0, Fraction>; + using InputShiftType = typename InputType::ShiftType; + + return + (FractionOut > FractionSize) ? + OutputType::fromInternal(static_cast(static_cast(this->value) << ((FractionOut > FractionSize) ? (FractionOut - FractionSize) : 0))) : + (FractionSize > FractionOut) ? + OutputType::fromInternal(static_cast(static_cast(this->value) >> ((FractionSize > FractionOut) ? (FractionSize - FractionOut) : 0))) : + OutputType::fromInternal(this->value); +} + +// +// Static Functions +// + +template< unsigned Fraction > +constexpr UFixed<0, Fraction> UFixed<0, Fraction>::fromInternal(const typename UFixed<0, Fraction>::InternalType & value) +{ + return UFixed<0, Fraction>(RawType(value)); +} + +// +// Compound Assignment Operators +// + +template< unsigned Fraction > +UFixed<0, Fraction> & UFixed<0, Fraction>::operator +=(const UFixed<0, Fraction> & other) +{ + this->value += other.value; + return *this; +} + +template< unsigned Fraction > +UFixed<0, Fraction> & UFixed<0, Fraction>::operator -=(const UFixed<0, Fraction> & other) +{ + this->value -= other.value; + return *this; +} + +template< unsigned Fraction > +UFixed<0, Fraction> & UFixed<0, Fraction>::operator *=(const UFixed<0, Fraction> & other) +{ + using InternalType = typename UFixed<0, Fraction>::InternalType; + using PrecisionType = typename UFixed<0, Fraction * 2>::InternalType; + const PrecisionType temp = (static_cast(this->value) * static_cast(other.value)) >> FractionSize; + this->value = static_cast(temp); + return *this; +} + +template< unsigned Fraction > +UFixed<0, Fraction> & UFixed<0, Fraction>::operator /=(const UFixed<0, Fraction> & other) +{ + using InternalType = typename UFixed<0, Fraction>::InternalType; + using PrecisionType = typename UFixed<0, Fraction * 2>::InternalType; + const PrecisionType temp = (static_cast(this->value) << FractionSize) / static_cast(other.value); + this->value = static_cast(temp); + return *this; +} + +FIXED_POINTS_END_NAMESPACE \ No newline at end of file diff --git a/src/FixedPoints/Utils.h b/src/FixedPoints/Utils.h index 0d1cf6b..a6de960 100644 --- a/src/FixedPoints/Utils.h +++ b/src/FixedPoints/Utils.h @@ -103,6 +103,12 @@ constexpr UFixed floorFixed(const UFixed & return OutputType::fromInternal(static_cast(value.getInternal() & ~OutputType::FractionMask)); } +template< unsigned Fraction > +constexpr UFixed<0, Fraction> floorFixed(const UFixed<0, Fraction> & value) +{ + return UFixed<0, Fraction>(0, 0); +} + template< unsigned Integer, unsigned Fraction > constexpr SFixed floorFixed(const SFixed & value) { @@ -117,6 +123,12 @@ constexpr UFixed ceilFixed(const UFixed & return UFixed((value.getFraction() == 0) ? value.getInteger() : (value.getInteger() + 1), 0); } +template< unsigned Fraction > +constexpr UFixed<0, Fraction> ceilFixed(const UFixed<0, Fraction> & value) +{ + return UFixed<0, Fraction>(0, 0); +} + template< unsigned Integer, unsigned Fraction > constexpr SFixed ceilFixed(const SFixed & value) { @@ -130,12 +142,18 @@ constexpr UFixed roundFixed(const UFixed & return (value.getFraction() >= OutputType(0.5).getFraction()) ? ceilFixed(value) : floorFixed(value); } +template< unsigned Fraction > +constexpr UFixed<0, Fraction> roundFixed(const UFixed<0, Fraction> & value) +{ + return UFixed<0, Fraction>(0, 0); +} + template< unsigned Integer, unsigned Fraction > constexpr SFixed roundFixed(const SFixed & value) { using OutputType = SFixed; return - signbitFixed(value) ? + signbitFixed(value) ((value.getFraction() <= OutputType(0.5).getFraction()) ? floorFixed(value) : ceilFixed(value)) : ((value.getFraction() >= OutputType(0.5).getFraction()) ? ceilFixed(value) : floorFixed(value)); } @@ -146,6 +164,12 @@ constexpr UFixed truncFixed(const UFixed & return UFixed(value.getInteger(), 0); } +template< unsigned Fraction > +constexpr UFixed<0, Fraction> truncFixed(const UFixed<0, Fraction> & value) +{ + return UFixed<0, Fraction>(0, 0); +} + template< unsigned Integer, unsigned Fraction > constexpr SFixed truncFixed(const SFixed & value) {