From daa23162a4dec0d4da9cb9851fac96030eadbe29 Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 27 Feb 2023 15:42:46 +0100 Subject: [PATCH] Base: fix pow() of Unit --- src/Base/Unit.cpp | 56 ++++++++++++++++++++++++++++++++--------------- src/Base/Unit.h | 2 +- 2 files changed, 39 insertions(+), 19 deletions(-) diff --git a/src/Base/Unit.cpp b/src/Base/Unit.cpp index a57efe8f9d..f6fe744224 100644 --- a/src/Base/Unit.cpp +++ b/src/Base/Unit.cpp @@ -22,6 +22,8 @@ #include "PreCompiled.h" #ifndef _PreComp_ +# include +# include # include #endif @@ -32,6 +34,23 @@ using namespace Base; +static inline void checkPow(UnitSignature sig, double exp) +{ + auto isInt = [](double value) { + return std::fabs(std::round(value) - value) < std::numeric_limits::epsilon(); + }; + if (!isInt(sig.Length * exp) || + !isInt(sig.Mass * exp) || + !isInt(sig.Time * exp) || + !isInt(sig.ElectricCurrent * exp) || + !isInt(sig.ThermodynamicTemperature * exp) || + !isInt(sig.AmountOfSubstance * exp) || + !isInt(sig.LuminousIntensity * exp) || + !isInt(sig.Angle * exp)) { + throw Base::UnitsMismatchError("pow() of unit not possible"); + } +} + static inline void checkRange(const char * op, int length, int mass, int time, int electricCurrent, int thermodynamicTemperature, int amountOfSubstance, int luminousIntensity, int angle) { @@ -52,7 +71,7 @@ static inline void checkRange(const char * op, int length, int mass, int time, i ( amountOfSubstance < -(1 << (UnitSignatureAmountOfSubstanceBits - 1)) ) || ( luminousIntensity < -(1 << (UnitSignatureLuminousIntensityBits - 1)) ) || ( angle < -(1 << (UnitSignatureAngleBits - 1)) ) ) - throw Base::OverflowError((std::string("Unit underflow in ") + std::string(op)).c_str()); + throw Base::UnderflowError((std::string("Unit underflow in ") + std::string(op)).c_str()); } Unit::Unit(int8_t Length, @@ -119,27 +138,28 @@ Unit::Unit(const QString& expr) } } -Unit Unit::pow(signed char exp) const +Unit Unit::pow(double exp) const { + checkPow(Sig, exp); checkRange("pow()", - Sig.Length * exp, - Sig.Mass * exp, - Sig.Time * exp, - Sig.ElectricCurrent * exp, - Sig.ThermodynamicTemperature * exp, - Sig.AmountOfSubstance * exp, - Sig.LuminousIntensity * exp, - Sig.Angle * exp); + static_cast(Sig.Length * exp), + static_cast(Sig.Mass * exp), + static_cast(Sig.Time * exp), + static_cast(Sig.ElectricCurrent * exp), + static_cast(Sig.ThermodynamicTemperature * exp), + static_cast(Sig.AmountOfSubstance * exp), + static_cast(Sig.LuminousIntensity * exp), + static_cast(Sig.Angle * exp)); Unit result; - result.Sig.Length = Sig.Length * exp; - result.Sig.Mass = Sig.Mass * exp; - result.Sig.Time = Sig.Time * exp; - result.Sig.ElectricCurrent = Sig.ElectricCurrent * exp; - result.Sig.ThermodynamicTemperature = Sig.ThermodynamicTemperature * exp; - result.Sig.AmountOfSubstance = Sig.AmountOfSubstance * exp; - result.Sig.LuminousIntensity = Sig.LuminousIntensity * exp; - result.Sig.Angle = Sig.Angle * exp; + result.Sig.Length = static_cast(Sig.Length * exp); + result.Sig.Mass = static_cast(Sig.Mass * exp); + result.Sig.Time = static_cast(Sig.Time * exp); + result.Sig.ElectricCurrent = static_cast(Sig.ElectricCurrent * exp); + result.Sig.ThermodynamicTemperature = static_cast(Sig.ThermodynamicTemperature * exp); + result.Sig.AmountOfSubstance = static_cast(Sig.AmountOfSubstance * exp); + result.Sig.LuminousIntensity = static_cast(Sig.LuminousIntensity * exp); + result.Sig.Angle = static_cast(Sig.Angle * exp); return result; } diff --git a/src/Base/Unit.h b/src/Base/Unit.h index 6e94b71e01..bc2e31d128 100644 --- a/src/Base/Unit.h +++ b/src/Base/Unit.h @@ -76,7 +76,7 @@ public: bool operator ==(const Unit&) const; bool operator !=(const Unit&that) const {return !(*this == that);} Unit& operator =(const Unit&); - Unit pow(signed char exp)const; + Unit pow(double exp)const; //@} /// get the unit signature const UnitSignature & getSignature()const {return Sig;}