Base: Units: hide internals
This commit is contained in:
committed by
Yorik van Havre
parent
c4a8bd680a
commit
539b7d43cf
@@ -2453,56 +2453,12 @@ Py::Object FunctionExpression::evaluate(const Expression *expr, int f, const std
|
||||
case ABS:
|
||||
unit = v1.getUnit();
|
||||
break;
|
||||
case SQRT: {
|
||||
unit = v1.getUnit();
|
||||
|
||||
// All components of unit must be either zero or dividable by 2
|
||||
UnitSignature s = unit.getSignature();
|
||||
if ( !((s.Length % 2) == 0) &&
|
||||
((s.Mass % 2) == 0) &&
|
||||
((s.Time % 2) == 0) &&
|
||||
((s.ElectricCurrent % 2) == 0) &&
|
||||
((s.ThermodynamicTemperature % 2) == 0) &&
|
||||
((s.AmountOfSubstance % 2) == 0) &&
|
||||
((s.LuminousIntensity % 2) == 0) &&
|
||||
((s.Angle % 2) == 0))
|
||||
_EXPR_THROW("All dimensions must be even to compute the square root.",expr);
|
||||
|
||||
unit = Unit(s.Length /2,
|
||||
s.Mass / 2,
|
||||
s.Time / 2,
|
||||
s.ElectricCurrent / 2,
|
||||
s.ThermodynamicTemperature / 2,
|
||||
s.AmountOfSubstance / 2,
|
||||
s.LuminousIntensity / 2,
|
||||
s.Angle);
|
||||
case SQRT:
|
||||
unit = v1.getUnit().sqrt();
|
||||
break;
|
||||
}
|
||||
case CBRT: {
|
||||
unit = v1.getUnit();
|
||||
|
||||
// All components of unit must be either zero or dividable by 3
|
||||
UnitSignature s = unit.getSignature();
|
||||
if ( !((s.Length % 3) == 0) &&
|
||||
((s.Mass % 3) == 0) &&
|
||||
((s.Time % 3) == 0) &&
|
||||
((s.ElectricCurrent % 3) == 0) &&
|
||||
((s.ThermodynamicTemperature % 3) == 0) &&
|
||||
((s.AmountOfSubstance % 3) == 0) &&
|
||||
((s.LuminousIntensity % 3) == 0) &&
|
||||
((s.Angle % 3) == 0))
|
||||
_EXPR_THROW("All dimensions must be multiples of 3 to compute the cube root.",expr);
|
||||
|
||||
unit = Unit(s.Length /3,
|
||||
s.Mass / 3,
|
||||
s.Time / 3,
|
||||
s.ElectricCurrent / 3,
|
||||
s.ThermodynamicTemperature / 3,
|
||||
s.AmountOfSubstance / 3,
|
||||
s.LuminousIntensity / 3,
|
||||
s.Angle);
|
||||
case CBRT:
|
||||
unit = v1.getUnit().cbrt();
|
||||
break;
|
||||
}
|
||||
case ATAN2:
|
||||
if (e2.isNone())
|
||||
_EXPR_THROW("Invalid second argument.",expr);
|
||||
|
||||
@@ -35,24 +35,28 @@
|
||||
using namespace Base;
|
||||
|
||||
// clang-format off
|
||||
static inline void checkPow(UnitSignature sig, double exp)
|
||||
{
|
||||
auto isInt = [](double value) {
|
||||
return std::fabs(std::round(value) - value) < std::numeric_limits<double>::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");
|
||||
}
|
||||
}
|
||||
constexpr int UnitSignatureLengthBits = 4;
|
||||
constexpr int UnitSignatureMassBits = 4;
|
||||
constexpr int UnitSignatureTimeBits = 4;
|
||||
constexpr int UnitSignatureElectricCurrentBits = 4;
|
||||
constexpr int UnitSignatureThermodynamicTemperatureBits = 4;
|
||||
constexpr int UnitSignatureAmountOfSubstanceBits = 4;
|
||||
constexpr int UnitSignatureLuminousIntensityBits = 4;
|
||||
constexpr int UnitSignatureAngleBits = 4;
|
||||
|
||||
static inline void checkRange(const char * op, int length, int mass, int time, int electricCurrent,
|
||||
struct UnitSignature {
|
||||
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 LuminousIntensity: UnitSignatureLuminousIntensityBits;
|
||||
int32_t Angle: UnitSignatureAngleBits;
|
||||
};
|
||||
|
||||
static inline uint32_t sigVal(const std::string &op,
|
||||
int length, int mass, int time, int electricCurrent,
|
||||
int thermodynamicTemperature, int amountOfSubstance, int luminousIntensity, int angle)
|
||||
{
|
||||
if ( ( length >= (1 << (UnitSignatureLengthBits - 1)) ) ||
|
||||
@@ -63,7 +67,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 overflow in ") + std::string(op)).c_str());
|
||||
throw Base::OverflowError(("Unit overflow in " + op).c_str());
|
||||
}
|
||||
if ( ( length < -(1 << (UnitSignatureLengthBits - 1)) ) ||
|
||||
( mass < -(1 << (UnitSignatureMassBits - 1)) ) ||
|
||||
@@ -73,10 +77,25 @@ 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::UnderflowError((std::string("Unit underflow in ") + std::string(op)).c_str());
|
||||
throw Base::UnderflowError(("Unit underflow in " + op).c_str());
|
||||
}
|
||||
|
||||
UnitSignature Sig;
|
||||
Sig.Length = length;
|
||||
Sig.Mass = mass;
|
||||
Sig.Time = time;
|
||||
Sig.ElectricCurrent = electricCurrent;
|
||||
Sig.ThermodynamicTemperature = thermodynamicTemperature;
|
||||
Sig.AmountOfSubstance = amountOfSubstance;
|
||||
Sig.LuminousIntensity = luminousIntensity;
|
||||
Sig.Angle = angle;
|
||||
|
||||
uint32_t ret;
|
||||
memcpy(&ret, &Sig, sizeof(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
Unit::Unit(int8_t Length, //NOLINT
|
||||
int8_t Mass,
|
||||
int8_t Time,
|
||||
@@ -86,37 +105,21 @@ Unit::Unit(int8_t Length, //NOLINT
|
||||
int8_t LuminousIntensity,
|
||||
int8_t Angle)
|
||||
{
|
||||
checkRange("unit",
|
||||
Length,
|
||||
Mass,
|
||||
Time,
|
||||
ElectricCurrent,
|
||||
ThermodynamicTemperature,
|
||||
AmountOfSubstance,
|
||||
LuminousIntensity,
|
||||
Angle);
|
||||
|
||||
Sig.Length = Length;
|
||||
Sig.Mass = Mass;
|
||||
Sig.Time = Time;
|
||||
Sig.ElectricCurrent = ElectricCurrent;
|
||||
Sig.ThermodynamicTemperature = ThermodynamicTemperature;
|
||||
Sig.AmountOfSubstance = AmountOfSubstance;
|
||||
Sig.LuminousIntensity = LuminousIntensity;
|
||||
Sig.Angle = Angle;
|
||||
Val = sigVal("unit",
|
||||
Length,
|
||||
Mass,
|
||||
Time,
|
||||
ElectricCurrent,
|
||||
ThermodynamicTemperature,
|
||||
AmountOfSubstance,
|
||||
LuminousIntensity,
|
||||
Angle);
|
||||
}
|
||||
|
||||
|
||||
Unit::Unit() //NOLINT
|
||||
{
|
||||
Sig.Length = 0;
|
||||
Sig.Mass = 0;
|
||||
Sig.Time = 0;
|
||||
Sig.ElectricCurrent = 0;
|
||||
Sig.ThermodynamicTemperature = 0;
|
||||
Sig.AmountOfSubstance = 0;
|
||||
Sig.LuminousIntensity = 0;
|
||||
Sig.Angle = 0;
|
||||
Val = 0;
|
||||
}
|
||||
|
||||
Unit::Unit(const QString& expr) // NOLINT
|
||||
@@ -125,218 +128,335 @@ Unit::Unit(const QString& expr) // NOLINT
|
||||
*this = Quantity::parse(expr).getUnit();
|
||||
}
|
||||
catch (const Base::ParserError&) {
|
||||
Sig.Length = 0;
|
||||
Sig.Mass = 0;
|
||||
Sig.Time = 0;
|
||||
Sig.ElectricCurrent = 0;
|
||||
Sig.ThermodynamicTemperature = 0;
|
||||
Sig.AmountOfSubstance = 0;
|
||||
Sig.LuminousIntensity = 0;
|
||||
Sig.Angle = 0;
|
||||
Val = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Unit Unit::pow(double exp) const
|
||||
{
|
||||
checkPow(Sig, exp);
|
||||
checkRange("pow()",
|
||||
static_cast<int>(Sig.Length * exp),
|
||||
static_cast<int>(Sig.Mass * exp),
|
||||
static_cast<int>(Sig.Time * exp),
|
||||
static_cast<int>(Sig.ElectricCurrent * exp),
|
||||
static_cast<int>(Sig.ThermodynamicTemperature * exp),
|
||||
static_cast<int>(Sig.AmountOfSubstance * exp),
|
||||
static_cast<int>(Sig.LuminousIntensity * exp),
|
||||
static_cast<int>(Sig.Angle * exp));
|
||||
UnitSignature sig;
|
||||
memcpy(&sig, &Val, sizeof(Val));
|
||||
auto isInt = [](double value) {
|
||||
return std::fabs(std::round(value) - value) < std::numeric_limits<double>::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");
|
||||
|
||||
Unit result;
|
||||
result.Sig.Length = static_cast<int8_t>(Sig.Length * exp);
|
||||
result.Sig.Mass = static_cast<int8_t>(Sig.Mass * exp);
|
||||
result.Sig.Time = static_cast<int8_t>(Sig.Time * exp);
|
||||
result.Sig.ElectricCurrent = static_cast<int8_t>(Sig.ElectricCurrent * exp);
|
||||
result.Sig.ThermodynamicTemperature = static_cast<int8_t>(Sig.ThermodynamicTemperature * exp);
|
||||
result.Sig.AmountOfSubstance = static_cast<int8_t>(Sig.AmountOfSubstance * exp);
|
||||
result.Sig.LuminousIntensity = static_cast<int8_t>(Sig.LuminousIntensity * exp);
|
||||
result.Sig.Angle = static_cast<int8_t>(Sig.Angle * exp);
|
||||
result.Val = sigVal("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);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Unit::isEmpty()const
|
||||
Unit Unit::sqrt() const
|
||||
{
|
||||
return (this->Sig.Length == 0)
|
||||
&& (this->Sig.Mass == 0)
|
||||
&& (this->Sig.Time == 0)
|
||||
&& (this->Sig.ElectricCurrent == 0)
|
||||
&& (this->Sig.ThermodynamicTemperature == 0)
|
||||
&& (this->Sig.AmountOfSubstance == 0)
|
||||
&& (this->Sig.LuminousIntensity == 0)
|
||||
&& (this->Sig.Angle == 0);
|
||||
UnitSignature sig;
|
||||
memcpy(&sig, &Val, sizeof(Val));
|
||||
// All components of unit must be either zero or dividable by 2
|
||||
if (!((sig.Length % 2) == 0) &&
|
||||
((sig.Mass % 2) == 0) &&
|
||||
((sig.Time % 2) == 0) &&
|
||||
((sig.ElectricCurrent % 2) == 0) &&
|
||||
((sig.ThermodynamicTemperature % 2) == 0) &&
|
||||
((sig.AmountOfSubstance % 2) == 0) &&
|
||||
((sig.LuminousIntensity % 2) == 0) &&
|
||||
((sig.Angle % 2) == 0))
|
||||
throw Base::UnitsMismatchError("sqrt() needs even dimensions");
|
||||
|
||||
Unit result;
|
||||
result.Val = sigVal("sqrt()",
|
||||
sig.Length >> 1,
|
||||
sig.Mass >> 1,
|
||||
sig.Time >> 1,
|
||||
sig.ElectricCurrent >> 1,
|
||||
sig.ThermodynamicTemperature >> 1,
|
||||
sig.AmountOfSubstance >> 1,
|
||||
sig.LuminousIntensity >> 1,
|
||||
sig.Angle >> 1);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Unit Unit::cbrt() const
|
||||
{
|
||||
UnitSignature sig;
|
||||
memcpy(&sig, &Val, sizeof(Val));
|
||||
// All components of unit must be either zero or dividable by 3
|
||||
if (!((sig.Length % 3) == 0) &&
|
||||
((sig.Mass % 3) == 0) &&
|
||||
((sig.Time % 3) == 0) &&
|
||||
((sig.ElectricCurrent % 3) == 0) &&
|
||||
((sig.ThermodynamicTemperature % 3) == 0) &&
|
||||
((sig.AmountOfSubstance % 3) == 0) &&
|
||||
((sig.LuminousIntensity % 3) == 0) &&
|
||||
((sig.Angle % 3) == 0))
|
||||
throw Base::UnitsMismatchError("cbrt() needs dimensions to be multiples of 3");
|
||||
|
||||
Unit result;
|
||||
result.Val = sigVal("cbrt()",
|
||||
sig.Length / 3,
|
||||
sig.Mass / 3,
|
||||
sig.Time / 3,
|
||||
sig.ElectricCurrent / 3,
|
||||
sig.ThermodynamicTemperature / 3,
|
||||
sig.AmountOfSubstance / 3,
|
||||
sig.LuminousIntensity / 3,
|
||||
sig.Angle / 3);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int Unit::length() const
|
||||
{
|
||||
UnitSignature sig;
|
||||
memcpy(&sig, &Val, sizeof(Val));
|
||||
return sig.Length;
|
||||
}
|
||||
|
||||
int Unit::mass() const
|
||||
{
|
||||
UnitSignature sig;
|
||||
memcpy(&sig, &Val, sizeof(Val));
|
||||
return sig.Mass;
|
||||
}
|
||||
|
||||
|
||||
int Unit::time() const
|
||||
{
|
||||
UnitSignature sig;
|
||||
memcpy(&sig, &Val, sizeof(Val));
|
||||
return sig.Time;
|
||||
}
|
||||
|
||||
int Unit::electricCurrent() const
|
||||
{
|
||||
UnitSignature sig;
|
||||
memcpy(&sig, &Val, sizeof(Val));
|
||||
return sig.ElectricCurrent;
|
||||
}
|
||||
|
||||
int Unit::thermodynamicTemperature() const
|
||||
{
|
||||
UnitSignature sig;
|
||||
memcpy(&sig, &Val, sizeof(Val));
|
||||
return sig.ThermodynamicTemperature;
|
||||
}
|
||||
|
||||
int Unit::amountOfSubstance() const
|
||||
{
|
||||
UnitSignature sig;
|
||||
memcpy(&sig, &Val, sizeof(Val));
|
||||
return sig.AmountOfSubstance;
|
||||
}
|
||||
|
||||
int Unit::luminousIntensity() const
|
||||
{
|
||||
UnitSignature sig;
|
||||
memcpy(&sig, &Val, sizeof(Val));
|
||||
return sig.LuminousIntensity;
|
||||
}
|
||||
|
||||
int Unit::angle() const
|
||||
{
|
||||
UnitSignature sig;
|
||||
memcpy(&sig, &Val, sizeof(Val));
|
||||
return sig.Angle;
|
||||
}
|
||||
|
||||
bool Unit::isEmpty() const
|
||||
{
|
||||
return Val == 0;
|
||||
}
|
||||
|
||||
int Unit::operator [](int index) const
|
||||
{
|
||||
UnitSignature sig;
|
||||
memcpy(&sig, &Val, sizeof(Val));
|
||||
|
||||
switch (index) {
|
||||
case 0:
|
||||
return sig.Length;
|
||||
case 1:
|
||||
return sig.Mass;
|
||||
case 2:
|
||||
return sig.Time;
|
||||
case 3:
|
||||
return sig.ElectricCurrent;
|
||||
case 4:
|
||||
return sig.ThermodynamicTemperature;
|
||||
case 5:
|
||||
return sig.AmountOfSubstance;
|
||||
case 6:
|
||||
return sig.LuminousIntensity;
|
||||
case 7:
|
||||
return sig.Angle;
|
||||
default:
|
||||
throw Base::IndexError("Unknown Unit element");
|
||||
}
|
||||
}
|
||||
|
||||
bool Unit::operator ==(const Unit& that) const
|
||||
{
|
||||
return (this->Sig.Length == that.Sig.Length)
|
||||
&& (this->Sig.Mass == that.Sig.Mass)
|
||||
&& (this->Sig.Time == that.Sig.Time)
|
||||
&& (this->Sig.ElectricCurrent == that.Sig.ElectricCurrent)
|
||||
&& (this->Sig.ThermodynamicTemperature == that.Sig.ThermodynamicTemperature)
|
||||
&& (this->Sig.AmountOfSubstance == that.Sig.AmountOfSubstance)
|
||||
&& (this->Sig.LuminousIntensity == that.Sig.LuminousIntensity)
|
||||
&& (this->Sig.Angle == that.Sig.Angle);
|
||||
return Val == that.Val;
|
||||
}
|
||||
|
||||
|
||||
Unit Unit::operator *(const Unit &right) const
|
||||
{
|
||||
checkRange("* operator",
|
||||
Sig.Length +right.Sig.Length,
|
||||
Sig.Mass + right.Sig.Mass,
|
||||
Sig.Time + right.Sig.Time,
|
||||
Sig.ElectricCurrent + right.Sig.ElectricCurrent,
|
||||
Sig.ThermodynamicTemperature + right.Sig.ThermodynamicTemperature,
|
||||
Sig.AmountOfSubstance + right.Sig.AmountOfSubstance,
|
||||
Sig.LuminousIntensity + right.Sig.LuminousIntensity,
|
||||
Sig.Angle + right.Sig.Angle);
|
||||
|
||||
Unit result;
|
||||
result.Sig.Length = Sig.Length + right.Sig.Length;
|
||||
result.Sig.Mass = Sig.Mass + right.Sig.Mass;
|
||||
result.Sig.Time = Sig.Time + right.Sig.Time;
|
||||
result.Sig.ElectricCurrent = Sig.ElectricCurrent + right.Sig.ElectricCurrent;
|
||||
result.Sig.ThermodynamicTemperature = Sig.ThermodynamicTemperature + right.Sig.ThermodynamicTemperature;
|
||||
result.Sig.AmountOfSubstance = Sig.AmountOfSubstance + right.Sig.AmountOfSubstance;
|
||||
result.Sig.LuminousIntensity = Sig.LuminousIntensity + right.Sig.LuminousIntensity;
|
||||
result.Sig.Angle = Sig.Angle + right.Sig.Angle;
|
||||
UnitSignature sig, rsig;
|
||||
|
||||
memcpy(&sig, &Val, sizeof(Val));
|
||||
memcpy(&rsig, &right.Val, sizeof(right.Val));
|
||||
result.Val = sigVal("* operator",
|
||||
sig.Length + rsig.Length,
|
||||
sig.Mass + rsig.Mass,
|
||||
sig.Time + rsig.Time,
|
||||
sig.ElectricCurrent + rsig.ElectricCurrent,
|
||||
sig.ThermodynamicTemperature + rsig.ThermodynamicTemperature,
|
||||
sig.AmountOfSubstance + rsig.AmountOfSubstance,
|
||||
sig.LuminousIntensity + rsig.LuminousIntensity,
|
||||
sig.Angle + rsig.Angle);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Unit Unit::operator /(const Unit &right) const
|
||||
{
|
||||
checkRange("/ operator",
|
||||
Sig.Length - right.Sig.Length,
|
||||
Sig.Mass - right.Sig.Mass,
|
||||
Sig.Time - right.Sig.Time,
|
||||
Sig.ElectricCurrent - right.Sig.ElectricCurrent,
|
||||
Sig.ThermodynamicTemperature - right.Sig.ThermodynamicTemperature,
|
||||
Sig.AmountOfSubstance - right.Sig.AmountOfSubstance,
|
||||
Sig.LuminousIntensity - right.Sig.LuminousIntensity,
|
||||
Sig.Angle - right.Sig.Angle);
|
||||
|
||||
Unit result;
|
||||
result.Sig.Length = Sig.Length - right.Sig.Length;
|
||||
result.Sig.Mass = Sig.Mass - right.Sig.Mass;
|
||||
result.Sig.Time = Sig.Time - right.Sig.Time;
|
||||
result.Sig.ElectricCurrent = Sig.ElectricCurrent - right.Sig.ElectricCurrent;
|
||||
result.Sig.ThermodynamicTemperature = Sig.ThermodynamicTemperature - right.Sig.ThermodynamicTemperature;
|
||||
result.Sig.AmountOfSubstance = Sig.AmountOfSubstance - right.Sig.AmountOfSubstance;
|
||||
result.Sig.LuminousIntensity = Sig.LuminousIntensity - right.Sig.LuminousIntensity;
|
||||
result.Sig.Angle = Sig.Angle - right.Sig.Angle;
|
||||
UnitSignature sig, rsig;
|
||||
|
||||
memcpy(&sig, &Val, sizeof(Val));
|
||||
memcpy(&rsig, &right.Val, sizeof(right.Val));
|
||||
result.Val = sigVal("/ operator",
|
||||
sig.Length - rsig.Length,
|
||||
sig.Mass - rsig.Mass,
|
||||
sig.Time - rsig.Time,
|
||||
sig.ElectricCurrent - rsig.ElectricCurrent,
|
||||
sig.ThermodynamicTemperature - rsig.ThermodynamicTemperature,
|
||||
sig.AmountOfSubstance - rsig.AmountOfSubstance,
|
||||
sig.LuminousIntensity - rsig.LuminousIntensity,
|
||||
sig.Angle - rsig.Angle);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
QString Unit::getString() const
|
||||
{
|
||||
std::stringstream ret;
|
||||
|
||||
if (isEmpty()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
if (Sig.Length > 0 ||
|
||||
Sig.Mass > 0 ||
|
||||
Sig.Time > 0 ||
|
||||
Sig.ElectricCurrent > 0 ||
|
||||
Sig.ThermodynamicTemperature> 0 ||
|
||||
Sig.AmountOfSubstance > 0 ||
|
||||
Sig.LuminousIntensity > 0 ||
|
||||
Sig.Angle > 0 ){
|
||||
std::stringstream ret;
|
||||
UnitSignature sig;
|
||||
memcpy(&sig, &Val, sizeof(Val));
|
||||
|
||||
if (sig.Length > 0 ||
|
||||
sig.Mass > 0 ||
|
||||
sig.Time > 0 ||
|
||||
sig.ElectricCurrent > 0 ||
|
||||
sig.ThermodynamicTemperature > 0 ||
|
||||
sig.AmountOfSubstance > 0 ||
|
||||
sig.LuminousIntensity > 0 ||
|
||||
sig.Angle > 0 ) {
|
||||
|
||||
bool mult = false;
|
||||
if (Sig.Length > 0) {
|
||||
if (sig.Length > 0) {
|
||||
mult = true;
|
||||
ret << "mm";
|
||||
if (Sig.Length > 1) {
|
||||
ret << "^" << Sig.Length;
|
||||
if (sig.Length > 1) {
|
||||
ret << "^" << sig.Length;
|
||||
}
|
||||
}
|
||||
|
||||
if (Sig.Mass > 0) {
|
||||
if (sig.Mass > 0) {
|
||||
if (mult) {
|
||||
ret<<'*';
|
||||
ret << '*';
|
||||
}
|
||||
mult = true;
|
||||
ret << "kg";
|
||||
if (Sig.Mass > 1) {
|
||||
ret << "^" << Sig.Mass;
|
||||
if (sig.Mass > 1) {
|
||||
ret << "^" << sig.Mass;
|
||||
}
|
||||
}
|
||||
|
||||
if (Sig.Time > 0) {
|
||||
if (sig.Time > 0) {
|
||||
if (mult) {
|
||||
ret<<'*';
|
||||
ret << '*';
|
||||
}
|
||||
mult = true;
|
||||
ret << "s";
|
||||
if (Sig.Time > 1) {
|
||||
ret << "^" << Sig.Time;
|
||||
if (sig.Time > 1) {
|
||||
ret << "^" << sig.Time;
|
||||
}
|
||||
}
|
||||
|
||||
if (Sig.ElectricCurrent > 0) {
|
||||
if (sig.ElectricCurrent > 0) {
|
||||
if (mult) {
|
||||
ret<<'*';
|
||||
ret << '*';
|
||||
}
|
||||
mult = true;
|
||||
ret << "A";
|
||||
if (Sig.ElectricCurrent > 1) {
|
||||
ret << "^" << Sig.ElectricCurrent;
|
||||
if (sig.ElectricCurrent > 1) {
|
||||
ret << "^" << sig.ElectricCurrent;
|
||||
}
|
||||
}
|
||||
|
||||
if (Sig.ThermodynamicTemperature > 0) {
|
||||
if (sig.ThermodynamicTemperature > 0) {
|
||||
if (mult) {
|
||||
ret<<'*';
|
||||
ret << '*';
|
||||
}
|
||||
mult = true;
|
||||
ret << "K";
|
||||
if (Sig.ThermodynamicTemperature > 1) {
|
||||
ret << "^" << Sig.ThermodynamicTemperature;
|
||||
if (sig.ThermodynamicTemperature > 1) {
|
||||
ret << "^" << sig.ThermodynamicTemperature;
|
||||
}
|
||||
}
|
||||
|
||||
if (Sig.AmountOfSubstance > 0){
|
||||
if (sig.AmountOfSubstance > 0) {
|
||||
if (mult) {
|
||||
ret<<'*';
|
||||
ret << '*';
|
||||
}
|
||||
mult = true;
|
||||
ret << "mol";
|
||||
if (Sig.AmountOfSubstance > 1) {
|
||||
ret << "^" << Sig.AmountOfSubstance;
|
||||
if (sig.AmountOfSubstance > 1) {
|
||||
ret << "^" << sig.AmountOfSubstance;
|
||||
}
|
||||
}
|
||||
|
||||
if (Sig.LuminousIntensity > 0) {
|
||||
if (sig.LuminousIntensity > 0) {
|
||||
if (mult) {
|
||||
ret<<'*';
|
||||
ret << '*';
|
||||
}
|
||||
mult = true;
|
||||
ret << "cd";
|
||||
if (Sig.LuminousIntensity > 1) {
|
||||
ret << "^" << Sig.LuminousIntensity;
|
||||
if (sig.LuminousIntensity > 1) {
|
||||
ret << "^" << sig.LuminousIntensity;
|
||||
}
|
||||
}
|
||||
|
||||
if (Sig.Angle > 0) {
|
||||
if (sig.Angle > 0) {
|
||||
if (mult) {
|
||||
ret<<'*';
|
||||
ret << '*';
|
||||
}
|
||||
mult = true; //NOLINT
|
||||
mult = true;
|
||||
ret << "deg";
|
||||
if (Sig.Angle > 1) {
|
||||
ret << "^" << Sig.Angle;
|
||||
if (sig.Angle > 1) {
|
||||
ret << "^" << sig.Angle;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -344,113 +464,113 @@ QString Unit::getString() const
|
||||
ret << "1";
|
||||
}
|
||||
|
||||
if (Sig.Length < 0 ||
|
||||
Sig.Mass < 0 ||
|
||||
Sig.Time < 0 ||
|
||||
Sig.ElectricCurrent < 0 ||
|
||||
Sig.ThermodynamicTemperature< 0 ||
|
||||
Sig.AmountOfSubstance < 0 ||
|
||||
Sig.LuminousIntensity < 0 ||
|
||||
Sig.Angle < 0 ){
|
||||
if (sig.Length < 0 ||
|
||||
sig.Mass < 0 ||
|
||||
sig.Time < 0 ||
|
||||
sig.ElectricCurrent < 0 ||
|
||||
sig.ThermodynamicTemperature < 0 ||
|
||||
sig.AmountOfSubstance < 0 ||
|
||||
sig.LuminousIntensity < 0 ||
|
||||
sig.Angle < 0 ) {
|
||||
ret << "/";
|
||||
|
||||
int nnom = 0;
|
||||
nnom += Sig.Length<0?1:0;
|
||||
nnom += Sig.Mass<0?1:0;
|
||||
nnom += Sig.Time<0?1:0;
|
||||
nnom += Sig.ElectricCurrent<0?1:0;
|
||||
nnom += Sig.ThermodynamicTemperature<0?1:0;
|
||||
nnom += Sig.AmountOfSubstance<0?1:0;
|
||||
nnom += Sig.LuminousIntensity<0?1:0;
|
||||
nnom += Sig.Angle<0?1:0;
|
||||
nnom += sig.Length < 0 ? 1 : 0;
|
||||
nnom += sig.Mass < 0 ? 1 : 0;
|
||||
nnom += sig.Time < 0 ? 1 : 0;
|
||||
nnom += sig.ElectricCurrent < 0 ? 1 : 0;
|
||||
nnom += sig.ThermodynamicTemperature < 0 ? 1 : 0;
|
||||
nnom += sig.AmountOfSubstance < 0 ? 1 : 0;
|
||||
nnom += sig.LuminousIntensity < 0 ? 1 : 0;
|
||||
nnom += sig.Angle < 0 ? 1 : 0;
|
||||
|
||||
if (nnom > 1) {
|
||||
ret << '(';
|
||||
}
|
||||
|
||||
bool mult=false;
|
||||
if (Sig.Length < 0) {
|
||||
bool mult = false;
|
||||
if (sig.Length < 0) {
|
||||
ret << "mm";
|
||||
mult = true;
|
||||
if (Sig.Length < -1) {
|
||||
ret << "^" << abs(Sig.Length);
|
||||
if (sig.Length < -1) {
|
||||
ret << "^" << abs(sig.Length);
|
||||
}
|
||||
}
|
||||
|
||||
if (Sig.Mass < 0) {
|
||||
if (sig.Mass < 0) {
|
||||
if (mult) {
|
||||
ret<<'*';
|
||||
ret << '*';
|
||||
}
|
||||
mult = true;
|
||||
ret << "kg";
|
||||
if (Sig.Mass < -1) {
|
||||
ret << "^" << abs(Sig.Mass);
|
||||
if (sig.Mass < -1) {
|
||||
ret << "^" << abs(sig.Mass);
|
||||
}
|
||||
}
|
||||
|
||||
if (Sig.Time < 0) {
|
||||
if (sig.Time < 0) {
|
||||
if (mult) {
|
||||
ret<<'*';
|
||||
ret << '*';
|
||||
}
|
||||
mult = true;
|
||||
ret << "s";
|
||||
if (Sig.Time < -1) {
|
||||
ret << "^" << abs(Sig.Time);
|
||||
if (sig.Time < -1) {
|
||||
ret << "^" << abs(sig.Time);
|
||||
}
|
||||
}
|
||||
|
||||
if (Sig.ElectricCurrent < 0) {
|
||||
if (sig.ElectricCurrent < 0) {
|
||||
if (mult) {
|
||||
ret<<'*';
|
||||
ret << '*';
|
||||
}
|
||||
mult = true;
|
||||
ret << "A";
|
||||
if (Sig.ElectricCurrent < -1) {
|
||||
ret << "^" << abs(Sig.ElectricCurrent);
|
||||
if (sig.ElectricCurrent < -1) {
|
||||
ret << "^" << abs(sig.ElectricCurrent);
|
||||
}
|
||||
}
|
||||
|
||||
if (Sig.ThermodynamicTemperature < 0) {
|
||||
if (sig.ThermodynamicTemperature < 0) {
|
||||
if (mult) {
|
||||
ret<<'*';
|
||||
ret << '*';
|
||||
}
|
||||
mult = true;
|
||||
ret << "K";
|
||||
if (Sig.ThermodynamicTemperature < -1) {
|
||||
ret << "^" << abs(Sig.ThermodynamicTemperature);
|
||||
if (sig.ThermodynamicTemperature < -1) {
|
||||
ret << "^" << abs(sig.ThermodynamicTemperature);
|
||||
}
|
||||
}
|
||||
|
||||
if (Sig.AmountOfSubstance < 0) {
|
||||
if (sig.AmountOfSubstance < 0) {
|
||||
if (mult) {
|
||||
ret<<'*';
|
||||
ret << '*';
|
||||
}
|
||||
mult = true;
|
||||
ret << "mol";
|
||||
if (Sig.AmountOfSubstance < -1) {
|
||||
ret << "^" << abs(Sig.AmountOfSubstance);
|
||||
if (sig.AmountOfSubstance < -1) {
|
||||
ret << "^" << abs(sig.AmountOfSubstance);
|
||||
}
|
||||
}
|
||||
|
||||
if (Sig.LuminousIntensity < 0) {
|
||||
if (sig.LuminousIntensity < 0) {
|
||||
if (mult) {
|
||||
ret<<'*';
|
||||
ret << '*';
|
||||
}
|
||||
mult = true;
|
||||
ret << "cd";
|
||||
if (Sig.LuminousIntensity < -1) {
|
||||
ret << "^" << abs(Sig.LuminousIntensity);
|
||||
if (sig.LuminousIntensity < -1) {
|
||||
ret << "^" << abs(sig.LuminousIntensity);
|
||||
}
|
||||
}
|
||||
|
||||
if (Sig.Angle < 0) {
|
||||
if (sig.Angle < 0) {
|
||||
if (mult) {
|
||||
ret<<'*';
|
||||
ret << '*';
|
||||
}
|
||||
mult = true; //NOLINT
|
||||
mult = true;
|
||||
ret << "deg";
|
||||
if (Sig.Angle < -1) {
|
||||
ret << "^" << abs(Sig.Angle);
|
||||
if (sig.Angle < -1) {
|
||||
ret << "^" << abs(sig.Angle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,29 +31,6 @@
|
||||
namespace Base
|
||||
{
|
||||
|
||||
#define UnitSignatureLengthBits 4
|
||||
#define UnitSignatureMassBits 4
|
||||
#define UnitSignatureTimeBits 4
|
||||
#define UnitSignatureElectricCurrentBits 4
|
||||
#define UnitSignatureThermodynamicTemperatureBits 4
|
||||
#define UnitSignatureAmountOfSubstanceBits 4
|
||||
#define UnitSignatureLuminousIntensityBits 4
|
||||
#define UnitSignatureAngleBits 4
|
||||
|
||||
// Hint:
|
||||
// https://en.cppreference.com/w/cpp/language/bit_field
|
||||
// https://stackoverflow.com/questions/33723631/signed-bit-field-in-c14
|
||||
struct UnitSignature
|
||||
{
|
||||
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 LuminousIntensity: UnitSignatureLuminousIntensityBits;
|
||||
int32_t Angle: UnitSignatureAngleBits;
|
||||
};
|
||||
/**
|
||||
* The Unit class.
|
||||
*/
|
||||
@@ -76,11 +53,11 @@ public:
|
||||
/// Destruction
|
||||
~Unit() = default;
|
||||
|
||||
|
||||
/** Operators. */
|
||||
//@{
|
||||
inline Unit& operator*=(const Unit& that);
|
||||
inline Unit& operator/=(const Unit& that);
|
||||
int operator[](int index) const;
|
||||
Unit operator*(const Unit&) const;
|
||||
Unit operator/(const Unit&) const;
|
||||
bool operator==(const Unit&) const;
|
||||
@@ -91,12 +68,17 @@ public:
|
||||
Unit& operator=(const Unit&) = default;
|
||||
Unit& operator=(Unit&&) = default;
|
||||
Unit pow(double exp) const;
|
||||
Unit sqrt() const;
|
||||
Unit cbrt() const;
|
||||
//@}
|
||||
/// get the unit signature
|
||||
const UnitSignature& getSignature() const
|
||||
{
|
||||
return Sig;
|
||||
}
|
||||
int length() const;
|
||||
int mass() const;
|
||||
int time() const;
|
||||
int electricCurrent() const;
|
||||
int thermodynamicTemperature() const;
|
||||
int amountOfSubstance() const;
|
||||
int luminousIntensity() const;
|
||||
int angle() const;
|
||||
bool isEmpty() const;
|
||||
|
||||
QString getString() const;
|
||||
@@ -177,7 +159,7 @@ public:
|
||||
|
||||
//@}
|
||||
private:
|
||||
UnitSignature Sig;
|
||||
uint32_t Val;
|
||||
};
|
||||
|
||||
inline Unit& Unit::operator*=(const Unit& that)
|
||||
|
||||
@@ -34,23 +34,24 @@ using namespace Base;
|
||||
// returns a string which represents the object e.g. when printed in python
|
||||
std::string UnitPy::representation() const
|
||||
{
|
||||
const UnitSignature& Sig = getUnitPtr()->getSignature();
|
||||
std::stringstream ret;
|
||||
Unit* self = getUnitPtr();
|
||||
|
||||
ret << "Unit: ";
|
||||
ret << getUnitPtr()->getString().toUtf8().constData() << " (";
|
||||
ret << Sig.Length << ",";
|
||||
ret << Sig.Mass << ",";
|
||||
ret << Sig.Time << ",";
|
||||
ret << Sig.ElectricCurrent << ",";
|
||||
ret << Sig.ThermodynamicTemperature << ",";
|
||||
ret << Sig.AmountOfSubstance << ",";
|
||||
ret << Sig.LuminousIntensity << ",";
|
||||
ret << Sig.Angle << ")";
|
||||
std::string type = getUnitPtr()->getTypeString().toUtf8().constData();
|
||||
ret << self->getString().toUtf8().constData() << " (";
|
||||
ret << (*self).length() << ",";
|
||||
ret << (*self).mass() << ",";
|
||||
ret << (*self).time() << ",";
|
||||
ret << (*self).electricCurrent() << ",";
|
||||
ret << (*self).thermodynamicTemperature() << ",";
|
||||
ret << (*self).amountOfSubstance() << ",";
|
||||
ret << (*self).luminousIntensity() << ",";
|
||||
ret << (*self).angle() << ")";
|
||||
|
||||
std::string type = self->getTypeString().toUtf8().constData();
|
||||
if (!type.empty()) {
|
||||
ret << " [" << type << "]";
|
||||
}
|
||||
|
||||
return ret.str();
|
||||
}
|
||||
|
||||
@@ -211,20 +212,16 @@ Py::String UnitPy::getType() const
|
||||
|
||||
Py::Tuple UnitPy::getSignature() const
|
||||
{
|
||||
const UnitSignature& Sig = getUnitPtr()->getSignature();
|
||||
Py::Tuple tuple(8);
|
||||
tuple.setItem(0, Py::Long(Sig.Length));
|
||||
tuple.setItem(1, Py::Long(Sig.Mass));
|
||||
tuple.setItem(2, Py::Long(Sig.Time));
|
||||
tuple.setItem(3, Py::Long(Sig.ElectricCurrent));
|
||||
tuple.setItem(4, Py::Long(Sig.ThermodynamicTemperature));
|
||||
tuple.setItem(5, Py::Long(Sig.AmountOfSubstance));
|
||||
tuple.setItem(6, Py::Long(Sig.LuminousIntensity));
|
||||
tuple.setItem(7, Py::Long(Sig.Angle));
|
||||
Unit* self = getUnitPtr();
|
||||
|
||||
for (auto i = 0; i < tuple.size(); i++) {
|
||||
tuple.setItem(i, Py::Long((*self)[i]));
|
||||
}
|
||||
|
||||
return tuple;
|
||||
}
|
||||
|
||||
|
||||
PyObject* UnitPy::getCustomAttributes(const char* /*attr*/) const
|
||||
{
|
||||
return nullptr;
|
||||
|
||||
@@ -201,11 +201,11 @@ void DlgUnitsCalculator::onUnitsBoxActivated(int index)
|
||||
// SI units use [m], not [mm] for lengths
|
||||
//
|
||||
Base::Quantity q = ui->quantitySpinBox->value();
|
||||
int32_t old = q.getUnit().getSignature().Length;
|
||||
int32_t old = q.getUnit().length();
|
||||
double value = q.getValue();
|
||||
|
||||
Base::Unit unit = units[index];
|
||||
int32_t len = unit.getSignature().Length;
|
||||
int32_t len = unit.length();
|
||||
ui->quantitySpinBox->setValue(Base::Quantity(value * std::pow(10.0, 3 * (len - old)), unit));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user