|
|
|
// Copyright 2017 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
|
|
|
|
|
|
|
|
//
|
|
|
|
// multiply
|
|
|
|
//
|
|
|
|
|
|
|
|
template< unsigned Integer, unsigned Fraction >
|
|
|
|
constexpr UFixed<Integer * 2, Fraction * 2> multiply(const UFixed<Integer, Fraction> & left, const UFixed<Integer, Fraction> & right)
|
|
|
|
{
|
|
|
|
using ResultType = UFixed<Integer * 2, Fraction * 2>;
|
|
|
|
using InternalType = typename ResultType::InternalType;
|
|
|
|
return ResultType::fromInternal(static_cast<InternalType>(static_cast<InternalType>(left.getInternal()) * static_cast<InternalType>(right.getInternal())));
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Basic Logic Operations
|
|
|
|
//
|
|
|
|
|
|
|
|
template< unsigned Integer, unsigned Fraction >
|
|
|
|
constexpr bool operator ==(const UFixed<Integer, Fraction> & left, const UFixed<Integer, Fraction> & right)
|
|
|
|
{
|
|
|
|
return (left.getInternal() == right.getInternal());
|
|
|
|
}
|
|
|
|
|
|
|
|
template< unsigned Integer, unsigned Fraction >
|
|
|
|
constexpr bool operator !=(const UFixed<Integer, Fraction> & left, const UFixed<Integer, Fraction> & right)
|
|
|
|
{
|
|
|
|
return (left.getInternal() != right.getInternal());
|
|
|
|
}
|
|
|
|
|
|
|
|
template< unsigned Integer, unsigned Fraction >
|
|
|
|
constexpr bool operator <(const UFixed<Integer, Fraction> & left, const UFixed<Integer, Fraction> & right)
|
|
|
|
{
|
|
|
|
return (left.getInternal() < right.getInternal());
|
|
|
|
}
|
|
|
|
|
|
|
|
template< unsigned Integer, unsigned Fraction >
|
|
|
|
constexpr bool operator >(const UFixed<Integer, Fraction> & left, const UFixed<Integer, Fraction> & right)
|
|
|
|
{
|
|
|
|
return (left.getInternal() > right.getInternal());
|
|
|
|
}
|
|
|
|
|
|
|
|
template< unsigned Integer, unsigned Fraction >
|
|
|
|
constexpr bool operator <=(const UFixed<Integer, Fraction> & left, const UFixed<Integer, Fraction> & right)
|
|
|
|
{
|
|
|
|
return (left.getInternal() <= right.getInternal());
|
|
|
|
}
|
|
|
|
|
|
|
|
template< unsigned Integer, unsigned Fraction >
|
|
|
|
constexpr bool operator >=(const UFixed<Integer, Fraction> & left, const UFixed<Integer, Fraction> & right)
|
|
|
|
{
|
|
|
|
return (left.getInternal() >= right.getInternal());
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Inter-size Logic Operations
|
|
|
|
//
|
|
|
|
|
|
|
|
template< unsigned IntegerLeft, unsigned FractionLeft, unsigned IntegerRight, unsigned FractionRight >
|
|
|
|
constexpr bool operator ==(const UFixed<IntegerLeft, FractionLeft> & left, const UFixed<IntegerRight, FractionRight> & right)
|
|
|
|
{
|
|
|
|
using LeftType = UFixed<IntegerLeft, FractionLeft>;
|
|
|
|
using RightType = UFixed<IntegerRight, FractionRight>;
|
|
|
|
|
|
|
|
static_assert(LeftType::InternalSize != RightType::InternalSize, "operator == has ambiguous result");
|
|
|
|
|
|
|
|
using CompareType = FIXED_POINTS_DETAILS::LargerType<LeftType, RightType>;
|
|
|
|
|
|
|
|
return (static_cast<CompareType>(left) == static_cast<CompareType>(right));
|
|
|
|
}
|
|
|
|
|
|
|
|
template< unsigned IntegerLeft, unsigned FractionLeft, unsigned IntegerRight, unsigned FractionRight >
|
|
|
|
constexpr bool operator !=(const UFixed<IntegerLeft, FractionLeft> & left, const UFixed<IntegerRight, FractionRight> & right)
|
|
|
|
{
|
|
|
|
using LeftType = UFixed<IntegerLeft, FractionLeft>;
|
|
|
|
using RightType = UFixed<IntegerRight, FractionRight>;
|
|
|
|
|
|
|
|
static_assert(LeftType::InternalSize != RightType::InternalSize, "operator != has ambiguous result");
|
|
|
|
|
|
|
|
using CompareType = FIXED_POINTS_DETAILS::LargerType<LeftType, RightType>;
|
|
|
|
|
|
|
|
return (static_cast<CompareType>(left) != static_cast<CompareType>(right));
|
|
|
|
}
|
|
|
|
|
|
|
|
template< unsigned IntegerLeft, unsigned FractionLeft, unsigned IntegerRight, unsigned FractionRight >
|
|
|
|
constexpr bool operator <(const UFixed<IntegerLeft, FractionLeft> & left, const UFixed<IntegerRight, FractionRight> & right)
|
|
|
|
{
|
|
|
|
using LeftType = UFixed<IntegerLeft, FractionLeft>;
|
|
|
|
using RightType = UFixed<IntegerRight, FractionRight>;
|
|
|
|
|
|
|
|
static_assert(LeftType::InternalSize != RightType::InternalSize, "operator < has ambiguous result");
|
|
|
|
|
|
|
|
using CompareType = FIXED_POINTS_DETAILS::LargerType<LeftType, RightType>;
|
|
|
|
|
|
|
|
return (static_cast<CompareType>(left) < static_cast<CompareType>(right));
|
|
|
|
}
|
|
|
|
|
|
|
|
template< unsigned IntegerLeft, unsigned FractionLeft, unsigned IntegerRight, unsigned FractionRight >
|
|
|
|
constexpr bool operator >(const UFixed<IntegerLeft, FractionLeft> & left, const UFixed<IntegerRight, FractionRight> & right)
|
|
|
|
{
|
|
|
|
using LeftType = UFixed<IntegerLeft, FractionLeft>;
|
|
|
|
using RightType = UFixed<IntegerRight, FractionRight>;
|
|
|
|
|
|
|
|
static_assert(LeftType::InternalSize != RightType::InternalSize, "operator > has ambiguous result");
|
|
|
|
|
|
|
|
using CompareType = FIXED_POINTS_DETAILS::LargerType<LeftType, RightType>;
|
|
|
|
|
|
|
|
return (static_cast<CompareType>(left) > static_cast<CompareType>(right));
|
|
|
|
}
|
|
|
|
|
|
|
|
template< unsigned IntegerLeft, unsigned FractionLeft, unsigned IntegerRight, unsigned FractionRight >
|
|
|
|
constexpr bool operator <=(const UFixed<IntegerLeft, FractionLeft> & left, const UFixed<IntegerRight, FractionRight> & right)
|
|
|
|
{
|
|
|
|
using LeftType = UFixed<IntegerLeft, FractionLeft>;
|
|
|
|
using RightType = UFixed<IntegerRight, FractionRight>;
|
|
|
|
|
|
|
|
static_assert(LeftType::InternalSize != RightType::InternalSize, "operator <= has ambiguous result");
|
|
|
|
|
|
|
|
using CompareType = FIXED_POINTS_DETAILS::LargerType<LeftType, RightType>;
|
|
|
|
|
|
|
|
return (static_cast<CompareType>(left) <= static_cast<CompareType>(right));
|
|
|
|
}
|
|
|
|
|
|
|
|
template< unsigned IntegerLeft, unsigned FractionLeft, unsigned IntegerRight, unsigned FractionRight >
|
|
|
|
constexpr bool operator >=(const UFixed<IntegerLeft, FractionLeft> & left, const UFixed<IntegerRight, FractionRight> & right)
|
|
|
|
{
|
|
|
|
using LeftType = UFixed<IntegerLeft, FractionLeft>;
|
|
|
|
using RightType = UFixed<IntegerRight, FractionRight>;
|
|
|
|
|
|
|
|
static_assert(LeftType::InternalSize != RightType::InternalSize, "operator >= has ambiguous result");
|
|
|
|
|
|
|
|
using CompareType = FIXED_POINTS_DETAILS::LargerType<LeftType, RightType>;
|
|
|
|
|
|
|
|
return (static_cast<CompareType>(left) >= static_cast<CompareType>(right));
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Basic Arithmetic Operations
|
|
|
|
//
|
|
|
|
|
|
|
|
template< unsigned Integer, unsigned Fraction >
|
|
|
|
constexpr UFixed<Integer, Fraction> operator +(const UFixed<Integer, Fraction> & left, const UFixed<Integer, Fraction> & right)
|
|
|
|
{
|
|
|
|
using InternalType = typename UFixed<Integer, Fraction>::InternalType;
|
|
|
|
return UFixed<Integer, Fraction>::fromInternal(static_cast<InternalType>(left.getInternal() + right.getInternal()));
|
|
|
|
}
|
|
|
|
|
|
|
|
template< unsigned Integer, unsigned Fraction >
|
|
|
|
constexpr UFixed<Integer, Fraction> operator -(const UFixed<Integer, Fraction> & left, const UFixed<Integer, Fraction> & right)
|
|
|
|
{
|
|
|
|
using InternalType = typename UFixed<Integer, Fraction>::InternalType;
|
|
|
|
return UFixed<Integer, Fraction>::fromInternal(static_cast<InternalType>(left.getInternal() - right.getInternal()));
|
|
|
|
}
|
|
|
|
|
|
|
|
template< unsigned Integer, unsigned Fraction >
|
|
|
|
constexpr UFixed<Integer, Fraction> operator *(const UFixed<Integer, Fraction> & left, const UFixed<Integer, Fraction> & right)
|
|
|
|
{
|
|
|
|
using InternalType = typename UFixed<Integer, Fraction>::InternalType;
|
|
|
|
using PrecisionType = typename UFixed<Integer * 2, Fraction * 2>::InternalType;
|
|
|
|
return UFixed<Integer, Fraction>::fromInternal(static_cast<InternalType>((static_cast<PrecisionType>(left.getInternal()) * static_cast<PrecisionType>(right.getInternal())) >> Fraction));
|
|
|
|
}
|
|
|
|
|
|
|
|
template< unsigned Integer, unsigned Fraction >
|
|
|
|
constexpr UFixed<Integer, Fraction> operator /(const UFixed<Integer, Fraction> & left, const UFixed<Integer, Fraction> & right)
|
|
|
|
{
|
|
|
|
using InternalType = typename UFixed<Integer, Fraction>::InternalType;
|
|
|
|
using PrecisionType = typename UFixed<Integer * 2, Fraction * 2>::InternalType;
|
|
|
|
return UFixed<Integer, Fraction>::fromInternal(static_cast<InternalType>((static_cast<PrecisionType>(left.getInternal()) << Fraction) / static_cast<PrecisionType>(right.getInternal())));
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Inter-size Arithmetic Operations
|
|
|
|
//
|
|
|
|
|
|
|
|
template< unsigned IntegerLeft, unsigned FractionLeft, unsigned IntegerRight, unsigned FractionRight >
|
|
|
|
constexpr auto operator +(const UFixed<IntegerLeft, FractionLeft> & left, const UFixed<IntegerRight, FractionRight> & right)
|
|
|
|
-> FIXED_POINTS_DETAILS::LargerType< UFixed<IntegerLeft, FractionLeft>, UFixed<IntegerRight, FractionRight> >
|
|
|
|
{
|
|
|
|
using LeftType = UFixed<IntegerLeft, FractionLeft>;
|
|
|
|
using RightType = UFixed<IntegerRight, FractionRight>;
|
|
|
|
|
|
|
|
static_assert(LeftType::InternalSize != RightType::InternalSize, "operator + has ambiguous result");
|
|
|
|
|
|
|
|
using CompareType = FIXED_POINTS_DETAILS::LargerType<LeftType, RightType>;
|
|
|
|
|
|
|
|
return (static_cast<CompareType>(left) + static_cast<CompareType>(right));
|
|
|
|
}
|
|
|
|
|
|
|
|
template< unsigned IntegerLeft, unsigned FractionLeft, unsigned IntegerRight, unsigned FractionRight >
|
|
|
|
constexpr auto operator -(const UFixed<IntegerLeft, FractionLeft> & left, const UFixed<IntegerRight, FractionRight> & right)
|
|
|
|
-> FIXED_POINTS_DETAILS::LargerType< UFixed<IntegerLeft, FractionLeft>, UFixed<IntegerRight, FractionRight> >
|
|
|
|
{
|
|
|
|
using LeftType = UFixed<IntegerLeft, FractionLeft>;
|
|
|
|
using RightType = UFixed<IntegerRight, FractionRight>;
|
|
|
|
|
|
|
|
static_assert(LeftType::InternalSize != RightType::InternalSize, "operator - has ambiguous result");
|
|
|
|
|
|
|
|
using CompareType = FIXED_POINTS_DETAILS::LargerType<LeftType, RightType>;
|
|
|
|
|
|
|
|
return (static_cast<CompareType>(left) - static_cast<CompareType>(right));
|
|
|
|
}
|
|
|
|
|
|
|
|
template< unsigned IntegerLeft, unsigned FractionLeft, unsigned IntegerRight, unsigned FractionRight >
|
|
|
|
constexpr auto operator *(const UFixed<IntegerLeft, FractionLeft> & left, const UFixed<IntegerRight, FractionRight> & right)
|
|
|
|
-> FIXED_POINTS_DETAILS::LargerType< UFixed<IntegerLeft, FractionLeft>, UFixed<IntegerRight, FractionRight> >
|
|
|
|
{
|
|
|
|
using LeftType = UFixed<IntegerLeft, FractionLeft>;
|
|
|
|
using RightType = UFixed<IntegerRight, FractionRight>;
|
|
|
|
|
|
|
|
static_assert(LeftType::InternalSize != RightType::InternalSize, "operator * has ambiguous result");
|
|
|
|
|
|
|
|
using CompareType = FIXED_POINTS_DETAILS::LargerType<LeftType, RightType>;
|
|
|
|
|
|
|
|
return (static_cast<CompareType>(left) * static_cast<CompareType>(right));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template< unsigned IntegerLeft, unsigned FractionLeft, unsigned IntegerRight, unsigned FractionRight >
|
|
|
|
constexpr auto operator /(const UFixed<IntegerLeft, FractionLeft> & left, const UFixed<IntegerRight, FractionRight> & right)
|
|
|
|
-> FIXED_POINTS_DETAILS::LargerType< UFixed<IntegerLeft, FractionLeft>, UFixed<IntegerRight, FractionRight> >
|
|
|
|
{
|
|
|
|
using LeftType = UFixed<IntegerLeft, FractionLeft>;
|
|
|
|
using RightType = UFixed<IntegerRight, FractionRight>;
|
|
|
|
|
|
|
|
static_assert(LeftType::InternalSize != RightType::InternalSize, "operator / has ambiguous result");
|
|
|
|
|
|
|
|
using CompareType = FIXED_POINTS_DETAILS::LargerType<LeftType, RightType>;
|
|
|
|
|
|
|
|
return (static_cast<CompareType>(left) / static_cast<CompareType>(right));
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Literal-type Operators
|
|
|
|
// Generated by macro to make maintenance easier
|
|
|
|
//
|
|
|
|
|
|
|
|
#define LOGIC_OPERATOR( type, op )\
|
|
|
|
template< unsigned Integer, unsigned Fraction >\
|
|
|
|
constexpr bool operator op (const UFixed<Integer, Fraction> & left, const type & right)\
|
|
|
|
{\
|
|
|
|
return (left op UFixed<Integer, Fraction>(right));\
|
|
|
|
}\
|
|
|
|
\
|
|
|
|
template< unsigned Integer, unsigned Fraction >\
|
|
|
|
constexpr bool operator op (const type & left, const UFixed<Integer, Fraction> & right)\
|
|
|
|
{\
|
|
|
|
return (UFixed<Integer, Fraction>(left) op right);\
|
|
|
|
}
|
|
|
|
|
|
|
|
#define ARITHMETIC_OPERATOR( type, op )\
|
|
|
|
template< unsigned Integer, unsigned Fraction >\
|
|
|
|
constexpr UFixed<Integer, Fraction> operator op (const UFixed<Integer, Fraction> & left, const type & right)\
|
|
|
|
{\
|
|
|
|
return (left op UFixed<Integer, Fraction>(right));\
|
|
|
|
}\
|
|
|
|
\
|
|
|
|
template< unsigned Integer, unsigned Fraction >\
|
|
|
|
constexpr UFixed<Integer, Fraction> operator op (const type & left, const UFixed<Integer, Fraction> & right)\
|
|
|
|
{\
|
|
|
|
return (UFixed<Integer, Fraction>(left) op right);\
|
|
|
|
}
|
|
|
|
|
|
|
|
#define OPERATORS( opType, op ) \
|
|
|
|
opType##_OPERATOR( FIXED_POINTS_DETAILS::IntegerLiteral, op )\
|
|
|
|
opType##_OPERATOR( FIXED_POINTS_DETAILS::IntegerLiteralU, op )\
|
|
|
|
opType##_OPERATOR( FIXED_POINTS_DETAILS::IntegerLiteralL, op )\
|
|
|
|
opType##_OPERATOR( FIXED_POINTS_DETAILS::IntegerLiteralUL, op )\
|
|
|
|
opType##_OPERATOR( FIXED_POINTS_DETAILS::IntegerLiteralLL, op )\
|
|
|
|
opType##_OPERATOR( FIXED_POINTS_DETAILS::IntegerLiteralULL, op )\
|
|
|
|
opType##_OPERATOR( FIXED_POINTS_DETAILS::DecimalLiteral, op )\
|
|
|
|
opType##_OPERATOR( FIXED_POINTS_DETAILS::DecimalLiteralF, op )\
|
|
|
|
opType##_OPERATOR( FIXED_POINTS_DETAILS::DecimalLiteralL, op )
|
|
|
|
|
|
|
|
#define LOGIC_OPERATORS( op ) OPERATORS( LOGIC, op )
|
|
|
|
#define ARITHMETIC_OPERATORS( op ) OPERATORS( ARITHMETIC, op )
|
|
|
|
|
|
|
|
LOGIC_OPERATORS( == )
|
|
|
|
LOGIC_OPERATORS( != )
|
|
|
|
LOGIC_OPERATORS( < )
|
|
|
|
LOGIC_OPERATORS( > )
|
|
|
|
LOGIC_OPERATORS( <= )
|
|
|
|
LOGIC_OPERATORS( >= )
|
|
|
|
|
|
|
|
ARITHMETIC_OPERATORS( + )
|
|
|
|
ARITHMETIC_OPERATORS( - )
|
|
|
|
ARITHMETIC_OPERATORS( * )
|
|
|
|
ARITHMETIC_OPERATORS( / )
|
|
|
|
|
|
|
|
// Prevent Macro-bleed:
|
|
|
|
|
|
|
|
#undef LOGIC_OPERATOR
|
|
|
|
#undef ARITHMETIC_OPERATOR
|
|
|
|
#undef OPERATORS
|
|
|
|
#undef LOGIC_OPERATORS
|
|
|
|
#undef ARITHMETIC_OPERATORS
|
|
|
|
|
|
|
|
FIXED_POINTS_END_NAMESPACE
|