// 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 Integer, unsigned Fraction > constexpr SFixed::SFixed(const RawType & value) : value(static_cast(value)) { } template< unsigned Integer, unsigned Fraction > constexpr SFixed::SFixed(void) : value(0) { } template< unsigned Integer, unsigned Fraction > constexpr SFixed::SFixed(const IntegerType & integer, const FractionType & fraction) : value((static_cast(integer) << FractionSize) | fraction) { } template< unsigned Integer, unsigned Fraction > constexpr SFixed::SFixed(const char & value) : value(static_cast(static_cast< FIXED_POINTS_DETAILS::LargerType >(value) << FractionSize)) { } template< unsigned Integer, unsigned Fraction > constexpr SFixed::SFixed(const unsigned char & value) : value(static_cast(static_cast< FIXED_POINTS_DETAILS::LargerType >(value) << FractionSize)) { } template< unsigned Integer, unsigned Fraction > constexpr SFixed::SFixed(const signed char & value) : value(static_cast(static_cast< FIXED_POINTS_DETAILS::LargerType >(value) << FractionSize)) { } template< unsigned Integer, unsigned Fraction > constexpr SFixed::SFixed(const unsigned short int & value) : value(static_cast(static_cast< FIXED_POINTS_DETAILS::LargerType >(value) << FractionSize)) { } template< unsigned Integer, unsigned Fraction > constexpr SFixed::SFixed(const signed short int & value) : value(static_cast(static_cast< FIXED_POINTS_DETAILS::LargerType >(value) << FractionSize)) { } template< unsigned Integer, unsigned Fraction > constexpr SFixed::SFixed(const unsigned int & value) : value(static_cast(static_cast< FIXED_POINTS_DETAILS::LargerType >(value) << FractionSize)) { } template< unsigned Integer, unsigned Fraction > constexpr SFixed::SFixed(const signed int & value) : value(static_cast(static_cast< FIXED_POINTS_DETAILS::LargerType >(value) << FractionSize)) { } template< unsigned Integer, unsigned Fraction > constexpr SFixed::SFixed(const unsigned long int & value) : value(static_cast(static_cast< FIXED_POINTS_DETAILS::LargerType >(value) << FractionSize)) { } template< unsigned Integer, unsigned Fraction > constexpr SFixed::SFixed(const signed long int & value) : value(static_cast(static_cast< FIXED_POINTS_DETAILS::LargerType >(value) << FractionSize)) { } template< unsigned Integer, unsigned Fraction > constexpr SFixed::SFixed(const unsigned long long int & value) : value(static_cast(static_cast< FIXED_POINTS_DETAILS::LargerType >(value) << FractionSize)) { } template< unsigned Integer, unsigned Fraction > constexpr SFixed::SFixed(const signed long long int & value) : value(static_cast(static_cast< FIXED_POINTS_DETAILS::LargerType >(value) << FractionSize)) { } template< unsigned Integer, unsigned Fraction > constexpr SFixed::SFixed(const double & value) : value(static_cast(value * static_cast(Scale))) { } template< unsigned Integer, unsigned Fraction > constexpr SFixed::SFixed(const float & value) : value(static_cast(value * static_cast(Scale))) { } template< unsigned Integer, unsigned Fraction > constexpr SFixed::SFixed(const long double & value) : value(static_cast(value * static_cast(Scale))) { } // // Getters // template< unsigned Integer, unsigned Fraction > constexpr typename SFixed::InternalType SFixed::getInternal(void) const { return this->value; } template< unsigned Integer, unsigned Fraction > constexpr typename SFixed::IntegerType SFixed::getInteger(void) const { return (static_cast(this->value >> IntegerShift) & IntegerMask) | ((this->value < 0) ? ~IntegerMask : 0); } template< unsigned Integer, unsigned Fraction > constexpr typename SFixed::FractionType SFixed::getFraction(void) const { return static_cast(this->value >> FractionShift) & FractionMask; } // // Cast Operators // template< unsigned Integer, unsigned Fraction > constexpr SFixed::operator IntegerType(void) const { return this->getInteger(); } template< unsigned Integer, unsigned Fraction > constexpr SFixed::operator float(void) const { return (1.0F / Scale) * static_cast ((this->value & IdentityMask) | ((this->value < 0) ? ~IdentityMask : 0)); } template< unsigned Integer, unsigned Fraction > constexpr SFixed::operator double(void) const { return (1.0 / Scale) * static_cast ((this->value & IdentityMask) | ((this->value < 0) ? ~IdentityMask : 0)); } template< unsigned Integer, unsigned Fraction > constexpr SFixed::operator long double(void) const { return (1.0L / Scale) * static_cast ((this->value & IdentityMask) | ((this->value < 0) ? ~IdentityMask : 0)); } template< unsigned Integer, unsigned Fraction > template< unsigned IntegerOut, unsigned FractionOut > constexpr SFixed::operator SFixed(void) const { using OutputType = SFixed; using OutputInternalType = typename OutputType::InternalType; using OutputShiftType = typename OutputType::ShiftType; using InputType = SFixed; 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 Integer, unsigned Fraction > constexpr SFixed SFixed::fromInternal(const typename SFixed::InternalType & value) { return SFixed(RawType(value)); } template< unsigned Integer, unsigned Fraction > constexpr SFixed SFixed::operator -(void) const { return SFixed::fromInternal(-this->value); } // // Member Operators // template< unsigned Integer, unsigned Fraction > SFixed & SFixed::operator ++(void) { this->value += (1 << FractionSize); return *this; } template< unsigned Integer, unsigned Fraction > SFixed & SFixed::operator --(void) { this->value -= (1 << FractionSize); return *this; } // // Compound Assignment Operators // template< unsigned Integer, unsigned Fraction > SFixed & SFixed::operator +=(const SFixed & other) { this->value += other.value; return *this; } template< unsigned Integer, unsigned Fraction > SFixed & SFixed::operator -=(const SFixed & other) { this->value -= other.value; return *this; } template< unsigned Integer, unsigned Fraction > SFixed & SFixed::operator *=(const SFixed & other) { using InternalType = typename SFixed::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 Integer, unsigned Fraction > SFixed & SFixed::operator /=(const SFixed & other) { using InternalType = typename SFixed::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