From 95dba437d720d6f01ce53733264066a6f18055da Mon Sep 17 00:00:00 2001 From: Dirk Petrautzki <dirk@dirk-petrautzki.de> Date: Fri, 4 Sep 2020 11:01:45 +0200 Subject: [PATCH] Add support for casting UFixed to SFixed and vice versa --- README.md | 4 ++-- src/FixedPoints/SFixed.h | 5 +++++ src/FixedPoints/SFixedMemberFunctions.h | 25 ++++++++++++++++++++++--- src/FixedPoints/UFixed.h | 5 +++++ src/FixedPoints/UFixedMemberFunctions.h | 19 +++++++++++++++++++ 5 files changed, 53 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index d6173af..8093173 100644 --- a/README.md +++ b/README.md @@ -176,11 +176,11 @@ This means that you may write code such as `UFixed<8, 8> value = 0.5;` without i - `double`. - The smallest unsigned type capable of holding its integer part. I.e. a type of at least `I` bits. - Another `UFixed` type of a different scale. E.g. `UFixed<4, 4>` may be converted to `UFixed<8, 8>` and vice versa. +- Another `SFixed` type of a different scale. E.g. `UFixed<4, 4>` may be converted to `SFixed<7, 8>` and vice versa. `SFixed<I, F>` is explicitly convertible to: - `float`. - `double`. - The smallest signed type capable of holding its integer part. I.e. a type of at least `I + 1` bits. - Another `SFixed` type of a different scale. E.g. `SFixed<3, 4>` may be converted to `SFixed<7, 8>` and vice versa. - - +- Another `UFixed` type of a different scale. E.g. `SFixed<3, 4>` may be converted to `UFixed<8, 8>` and vice versa. diff --git a/src/FixedPoints/SFixed.h b/src/FixedPoints/SFixed.h index b2aa96d..1d9fab7 100644 --- a/src/FixedPoints/SFixed.h +++ b/src/FixedPoints/SFixed.h @@ -22,6 +22,9 @@ FIXED_POINTS_BEGIN_NAMESPACE // Declaration // +template< unsigned IntegerOut, unsigned FractionOut > +class UFixed; // forward declaration of UFixed for casting between UFixed and SFixed + template< unsigned Integer, unsigned Fraction > class SFixed { @@ -102,6 +105,8 @@ public: template< unsigned IntegerOut, unsigned FractionOut > constexpr explicit operator SFixed<IntegerOut, FractionOut>() const; + template< unsigned IntegerOut, unsigned FractionOut > + constexpr explicit operator UFixed<IntegerOut, FractionOut>() const; static constexpr SFixed fromInternal(const InternalType & value); diff --git a/src/FixedPoints/SFixedMemberFunctions.h b/src/FixedPoints/SFixedMemberFunctions.h index e2ab090..43b167f 100644 --- a/src/FixedPoints/SFixedMemberFunctions.h +++ b/src/FixedPoints/SFixedMemberFunctions.h @@ -182,14 +182,33 @@ constexpr SFixed<Integer, Fraction>::operator long double() const template< unsigned Integer, unsigned Fraction > template< unsigned IntegerOut, unsigned FractionOut > constexpr SFixed<Integer, Fraction>::operator SFixed<IntegerOut, FractionOut>() const -{ +{ using OutputType = SFixed<IntegerOut, FractionOut>; using OutputInternalType = typename OutputType::InternalType; using OutputShiftType = typename OutputType::ShiftType; - + + using InputType = SFixed<Integer, Fraction>; + using InputShiftType = typename InputType::ShiftType; + + return + (FractionOut > FractionSize) ? + OutputType::fromInternal(static_cast<OutputInternalType>(static_cast<OutputShiftType>(this->value) << ((FractionOut > FractionSize) ? (FractionOut - FractionSize) : 0))) : + (FractionSize > FractionOut) ? + OutputType::fromInternal(static_cast<OutputInternalType>(static_cast<InputShiftType>(this->value) >> ((FractionSize > FractionOut) ? (FractionSize - FractionOut) : 0))) : + OutputType::fromInternal(this->value); +} + +template< unsigned Integer, unsigned Fraction > +template< unsigned IntegerOut, unsigned FractionOut > +constexpr SFixed<Integer, Fraction>::operator UFixed<IntegerOut, FractionOut>() const +{ + using OutputType = UFixed<IntegerOut, FractionOut>; + using OutputInternalType = typename OutputType::InternalType; + using OutputShiftType = typename OutputType::ShiftType; + using InputType = SFixed<Integer, Fraction>; using InputShiftType = typename InputType::ShiftType; - + return (FractionOut > FractionSize) ? OutputType::fromInternal(static_cast<OutputInternalType>(static_cast<OutputShiftType>(this->value) << ((FractionOut > FractionSize) ? (FractionOut - FractionSize) : 0))) : diff --git a/src/FixedPoints/UFixed.h b/src/FixedPoints/UFixed.h index 64079da..7c64a80 100644 --- a/src/FixedPoints/UFixed.h +++ b/src/FixedPoints/UFixed.h @@ -22,6 +22,9 @@ FIXED_POINTS_BEGIN_NAMESPACE // Declaration // +template< unsigned IntegerOut, unsigned FractionOut > +class SFixed; // forward declaration of SFixed for casting between SFixed and UFixed + template< unsigned Integer, unsigned Fraction > class UFixed { @@ -103,6 +106,8 @@ public: template< unsigned IntegerOut, unsigned FractionOut > constexpr explicit operator UFixed<IntegerOut, FractionOut>() const; + template< unsigned IntegerOut, unsigned FractionOut > + constexpr explicit operator SFixed<IntegerOut, FractionOut>() const; static constexpr UFixed fromInternal(const InternalType & value); diff --git a/src/FixedPoints/UFixedMemberFunctions.h b/src/FixedPoints/UFixedMemberFunctions.h index 9f7ddd0..c55cde2 100644 --- a/src/FixedPoints/UFixedMemberFunctions.h +++ b/src/FixedPoints/UFixedMemberFunctions.h @@ -189,6 +189,25 @@ constexpr UFixed<Integer, Fraction>::operator UFixed<IntegerOut, FractionOut>() OutputType::fromInternal(this->value); } +template< unsigned Integer, unsigned Fraction > +template< unsigned IntegerOut, unsigned FractionOut > +constexpr UFixed<Integer, Fraction>::operator SFixed<IntegerOut, FractionOut>() const +{ + using OutputType = SFixed<IntegerOut, FractionOut>; + using OutputInternalType = typename OutputType::InternalType; + using OutputShiftType = typename OutputType::ShiftType; + + using InputType = UFixed<Integer, Fraction>; + using InputShiftType = typename InputType::ShiftType; + + return + (FractionOut > FractionSize) ? + OutputType::fromInternal(static_cast<OutputInternalType>(static_cast<OutputShiftType>(this->value) << ((FractionOut > FractionSize) ? (FractionOut - FractionSize) : 0))) : + (FractionSize > FractionOut) ? + OutputType::fromInternal(static_cast<OutputInternalType>(static_cast<InputShiftType>(this->value) >> ((FractionSize > FractionOut) ? (FractionSize - FractionOut) : 0))) : + OutputType::fromInternal(this->value); +} + // // Static Functions //