// 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 multiply(const UFixed & left, const UFixed & right) { using ResultType = UFixed; using InternalType = typename ResultType::InternalType; return ResultType::fromInternal(static_cast(static_cast(left.getInternal()) * static_cast(right.getInternal()))); } // // Basic Logic Operations // template< unsigned Integer, unsigned Fraction > constexpr bool operator ==(const UFixed & left, const UFixed & right) { return (left.getInternal() == right.getInternal()); } template< unsigned Integer, unsigned Fraction > constexpr bool operator !=(const UFixed & left, const UFixed & right) { return (left.getInternal() != right.getInternal()); } template< unsigned Integer, unsigned Fraction > constexpr bool operator <(const UFixed & left, const UFixed & right) { return (left.getInternal() < right.getInternal()); } template< unsigned Integer, unsigned Fraction > constexpr bool operator >(const UFixed & left, const UFixed & right) { return (left.getInternal() > right.getInternal()); } template< unsigned Integer, unsigned Fraction > constexpr bool operator <=(const UFixed & left, const UFixed & right) { return (left.getInternal() <= right.getInternal()); } template< unsigned Integer, unsigned Fraction > constexpr bool operator >=(const UFixed & left, const UFixed & right) { return (left.getInternal() >= right.getInternal()); } // // Inter-size Logic Operations // template< unsigned IntegerLeft, unsigned FractionLeft, unsigned IntegerRight, unsigned FractionRight > constexpr bool operator ==(const UFixed & left, const UFixed & right) { using LeftType = UFixed; using RightType = UFixed; static_assert(LeftType::InternalSize != RightType::InternalSize, "operator == has ambiguous result"); using CompareType = FIXED_POINTS_DETAILS::LargerType; return (static_cast(left) == static_cast(right)); } template< unsigned IntegerLeft, unsigned FractionLeft, unsigned IntegerRight, unsigned FractionRight > constexpr bool operator !=(const UFixed & left, const UFixed & right) { using LeftType = UFixed; using RightType = UFixed; static_assert(LeftType::InternalSize != RightType::InternalSize, "operator != has ambiguous result"); using CompareType = FIXED_POINTS_DETAILS::LargerType; return (static_cast(left) != static_cast(right)); } template< unsigned IntegerLeft, unsigned FractionLeft, unsigned IntegerRight, unsigned FractionRight > constexpr bool operator <(const UFixed & left, const UFixed & right) { using LeftType = UFixed; using RightType = UFixed; static_assert(LeftType::InternalSize != RightType::InternalSize, "operator < has ambiguous result"); using CompareType = FIXED_POINTS_DETAILS::LargerType; return (static_cast(left) < static_cast(right)); } template< unsigned IntegerLeft, unsigned FractionLeft, unsigned IntegerRight, unsigned FractionRight > constexpr bool operator >(const UFixed & left, const UFixed & right) { using LeftType = UFixed; using RightType = UFixed; static_assert(LeftType::InternalSize != RightType::InternalSize, "operator > has ambiguous result"); using CompareType = FIXED_POINTS_DETAILS::LargerType; return (static_cast(left) > static_cast(right)); } template< unsigned IntegerLeft, unsigned FractionLeft, unsigned IntegerRight, unsigned FractionRight > constexpr bool operator <=(const UFixed & left, const UFixed & right) { using LeftType = UFixed; using RightType = UFixed; static_assert(LeftType::InternalSize != RightType::InternalSize, "operator <= has ambiguous result"); using CompareType = FIXED_POINTS_DETAILS::LargerType; return (static_cast(left) <= static_cast(right)); } template< unsigned IntegerLeft, unsigned FractionLeft, unsigned IntegerRight, unsigned FractionRight > constexpr bool operator >=(const UFixed & left, const UFixed & right) { using LeftType = UFixed; using RightType = UFixed; static_assert(LeftType::InternalSize != RightType::InternalSize, "operator >= has ambiguous result"); using CompareType = FIXED_POINTS_DETAILS::LargerType; return (static_cast(left) >= static_cast(right)); } // // Basic Arithmetic Operations // template< unsigned Integer, unsigned Fraction > constexpr UFixed operator +(const UFixed & left, const UFixed & right) { using InternalType = typename UFixed::InternalType; return UFixed::fromInternal(static_cast(left.getInternal() + right.getInternal())); } template< unsigned Integer, unsigned Fraction > constexpr UFixed operator -(const UFixed & left, const UFixed & right) { using InternalType = typename UFixed::InternalType; return UFixed::fromInternal(static_cast(left.getInternal() - right.getInternal())); } template< unsigned Integer, unsigned Fraction > constexpr UFixed operator *(const UFixed & left, const UFixed & right) { using InternalType = typename UFixed::InternalType; using PrecisionType = typename UFixed::InternalType; return UFixed::fromInternal(static_cast((static_cast(left.getInternal()) * static_cast(right.getInternal())) >> Fraction)); } template< unsigned Integer, unsigned Fraction > constexpr UFixed operator /(const UFixed & left, const UFixed & right) { using InternalType = typename UFixed::InternalType; using PrecisionType = typename UFixed::InternalType; return UFixed::fromInternal(static_cast((static_cast(left.getInternal()) << Fraction) / static_cast(right.getInternal()))); } // // Inter-size Arithmetic Operations // template< unsigned IntegerLeft, unsigned FractionLeft, unsigned IntegerRight, unsigned FractionRight > constexpr auto operator +(const UFixed & left, const UFixed & right) -> FIXED_POINTS_DETAILS::LargerType< UFixed, UFixed > { using LeftType = UFixed; using RightType = UFixed; static_assert(LeftType::InternalSize != RightType::InternalSize, "operator + has ambiguous result"); using CompareType = FIXED_POINTS_DETAILS::LargerType; return (static_cast(left) + static_cast(right)); } template< unsigned IntegerLeft, unsigned FractionLeft, unsigned IntegerRight, unsigned FractionRight > constexpr auto operator -(const UFixed & left, const UFixed & right) -> FIXED_POINTS_DETAILS::LargerType< UFixed, UFixed > { using LeftType = UFixed; using RightType = UFixed; static_assert(LeftType::InternalSize != RightType::InternalSize, "operator - has ambiguous result"); using CompareType = FIXED_POINTS_DETAILS::LargerType; return (static_cast(left) - static_cast(right)); } template< unsigned IntegerLeft, unsigned FractionLeft, unsigned IntegerRight, unsigned FractionRight > constexpr auto operator *(const UFixed & left, const UFixed & right) -> FIXED_POINTS_DETAILS::LargerType< UFixed, UFixed > { using LeftType = UFixed; using RightType = UFixed; static_assert(LeftType::InternalSize != RightType::InternalSize, "operator * has ambiguous result"); using CompareType = FIXED_POINTS_DETAILS::LargerType; return (static_cast(left) * static_cast(right)); } template< unsigned IntegerLeft, unsigned FractionLeft, unsigned IntegerRight, unsigned FractionRight > constexpr auto operator /(const UFixed & left, const UFixed & right) -> FIXED_POINTS_DETAILS::LargerType< UFixed, UFixed > { using LeftType = UFixed; using RightType = UFixed; static_assert(LeftType::InternalSize != RightType::InternalSize, "operator / has ambiguous result"); using CompareType = FIXED_POINTS_DETAILS::LargerType; return (static_cast(left) / static_cast(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 & left, const type & right)\ {\ return (left op UFixed(right));\ }\ \ template< unsigned Integer, unsigned Fraction >\ constexpr bool operator op (const type & left, const UFixed & right)\ {\ return (UFixed(left) op right);\ } #define ARITHMETIC_OPERATOR( type, op )\ template< unsigned Integer, unsigned Fraction >\ constexpr UFixed operator op (const UFixed & left, const type & right)\ {\ return (left op UFixed(right));\ }\ \ template< unsigned Integer, unsigned Fraction >\ constexpr UFixed operator op (const type & left, const UFixed & right)\ {\ return (UFixed(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