Unit: Added overflow/underflow checking.

This commit is contained in:
Eivind Kvedalen 2015-06-22 23:02:56 +02:00 committed by wmayer
parent 165261e358
commit c61c12d834
2 changed files with 80 additions and 10 deletions

View File

@ -27,9 +27,32 @@
#endif
#include "Unit.h"
#include "Exception.h"
using namespace Base;
static inline void checkRange(const char * op, int length, int mass, int time, int electricCurrent,
int thermodynamicTemperature, int amountOfSubstance, int luminoseIntensity, int angle)
{
if ( ( length >= (1 << (UnitSignatureLengthBits - 1)) ) ||
( mass >= (1 << (UnitSignatureMassBits - 1)) ) ||
( time >= (1 << (UnitSignatureTimeBits - 1)) ) ||
( electricCurrent >= (1 << (UnitSignatureElectricCurrentBits - 1)) ) ||
( thermodynamicTemperature >= (1 << (UnitSignatureThermodynamicTemperatureBits - 1)) ) ||
( amountOfSubstance >= (1 << (UnitSignatureAmountOfSubstanceBits - 1)) ) ||
( luminoseIntensity >= (1 << (UnitSignatureLuminoseIntensityBits - 1)) ) ||
( angle >= (1 << (UnitSignatureAngleBits - 1)) ) )
throw Base::Exception((std::string("Unit overflow in ") + std::string(op)).c_str());
if ( ( length < -(1 << (UnitSignatureLengthBits - 1)) ) ||
( mass < -(1 << (UnitSignatureMassBits - 1)) ) ||
( time < -(1 << (UnitSignatureTimeBits - 1)) ) ||
( electricCurrent < -(1 << (UnitSignatureElectricCurrentBits - 1)) ) ||
( thermodynamicTemperature < -(1 << (UnitSignatureThermodynamicTemperatureBits - 1)) ) ||
( amountOfSubstance < -(1 << (UnitSignatureAmountOfSubstanceBits - 1)) ) ||
( luminoseIntensity < -(1 << (UnitSignatureLuminoseIntensityBits - 1)) ) ||
( angle < -(1 << (UnitSignatureAngleBits - 1)) ) )
throw Base::Exception((std::string("Unit underflow in ") + std::string(op)).c_str());
}
Unit::Unit(int8_t Length,
int8_t Mass,
@ -40,7 +63,17 @@ Unit::Unit(int8_t Length,
int8_t LuminoseIntensity,
int8_t Angle)
{
Sig.Length = Length;
checkRange("unit",
(int32_t)Length,
(int32_t)Mass,
(int32_t)Time,
(int32_t)ElectricCurrent,
(int32_t)ThermodynamicTemperature,
(int32_t)AmountOfSubstance,
(int32_t)LuminoseIntensity,
(int32_t)Angle);
Sig.Length = Length;
Sig.Mass = Mass;
Sig.Time = Time;
Sig.ElectricCurrent = ElectricCurrent;
@ -75,6 +108,16 @@ Unit::Unit(const std::string& Pars)
Unit Unit::pow(char exp)const
{
checkRange("pow()",
(int32_t)Sig.Length * (int32_t)exp,
(int32_t)Sig.Mass * (int32_t)exp,
(int32_t)Sig.Time * (int32_t)exp,
(int32_t)Sig.ElectricCurrent * (int32_t)exp,
(int32_t)Sig.ThermodynamicTemperature * (int32_t)exp,
(int32_t)Sig.AmountOfSubstance * (int32_t)exp,
(int32_t)Sig.LuminoseIntensity * (int32_t)exp,
(int32_t)Sig.Angle * (int32_t)exp);
Unit result;
result.Sig.Length = Sig.Length * exp;
result.Sig.Mass = Sig.Mass * exp;
@ -86,7 +129,6 @@ Unit Unit::pow(char exp)const
result.Sig.Angle = Sig.Angle * exp;
return result;
}
bool Unit::isEmpty(void)const
@ -116,6 +158,16 @@ bool Unit::operator ==(const Unit& that) const
Unit Unit::operator *(const Unit &right) const
{
checkRange("* operator",
(int32_t)Sig.Length + (int32_t)right.Sig.Length,
(int32_t)Sig.Mass + (int32_t)right.Sig.Mass,
(int32_t)Sig.Time + (int32_t)right.Sig.Time,
(int32_t)Sig.ElectricCurrent + (int32_t)right.Sig.ElectricCurrent,
(int32_t)Sig.ThermodynamicTemperature + (int32_t)right.Sig.ThermodynamicTemperature,
(int32_t)Sig.AmountOfSubstance + (int32_t)right.Sig.AmountOfSubstance,
(int32_t)Sig.LuminoseIntensity + (int32_t)right.Sig.LuminoseIntensity,
(int32_t)Sig.Angle + (int32_t)right.Sig.Angle);
Unit result;
result.Sig.Length = Sig.Length + right.Sig.Length;
result.Sig.Mass = Sig.Mass + right.Sig.Mass;
@ -131,6 +183,16 @@ Unit Unit::operator *(const Unit &right) const
Unit Unit::operator /(const Unit &right) const
{
checkRange("/ operator",
(int32_t)Sig.Length - (int32_t)right.Sig.Length,
(int32_t)Sig.Mass - (int32_t)right.Sig.Mass,
(int32_t)Sig.Time - (int32_t)right.Sig.Time,
(int32_t)Sig.ElectricCurrent - (int32_t)right.Sig.ElectricCurrent,
(int32_t)Sig.ThermodynamicTemperature - (int32_t)right.Sig.ThermodynamicTemperature,
(int32_t)Sig.AmountOfSubstance - (int32_t)right.Sig.AmountOfSubstance,
(int32_t)Sig.LuminoseIntensity - (int32_t)right.Sig.LuminoseIntensity,
(int32_t)Sig.Angle - (int32_t)right.Sig.Angle);
Unit result;
result.Sig.Length = Sig.Length - right.Sig.Length;
result.Sig.Mass = Sig.Mass - right.Sig.Mass;

View File

@ -34,16 +34,24 @@
namespace Base {
#define UnitSignatureLengthBits 4
#define UnitSignatureMassBits 4
#define UnitSignatureTimeBits 4
#define UnitSignatureElectricCurrentBits 4
#define UnitSignatureThermodynamicTemperatureBits 4
#define UnitSignatureAmountOfSubstanceBits 4
#define UnitSignatureLuminoseIntensityBits 4
#define UnitSignatureAngleBits 4
struct UnitSignature{
int32_t Length:4;
int32_t Mass:4;
int32_t Time:4;
int32_t ElectricCurrent:4;
int32_t ThermodynamicTemperature:4;
int32_t AmountOfSubstance:4;
int32_t LuminoseIntensity:4;
int32_t Angle:4;
int32_t Length:UnitSignatureLengthBits;
int32_t Mass:UnitSignatureMassBits;
int32_t Time:UnitSignatureTimeBits;
int32_t ElectricCurrent:UnitSignatureElectricCurrentBits;
int32_t ThermodynamicTemperature:UnitSignatureThermodynamicTemperatureBits;
int32_t AmountOfSubstance:UnitSignatureAmountOfSubstanceBits;
int32_t LuminoseIntensity:UnitSignatureLuminoseIntensityBits;
int32_t Angle:UnitSignatureAngleBits;
};
/**
* The Unit class.