1
/***************************************************************************
2
* Copyright (c) 2011 Jürgen Riegel <juergen.riegel@web.de> *
4
* This file is part of the FreeCAD CAx development system. *
6
* This library is free software; you can redistribute it and/or *
7
* modify it under the terms of the GNU Library General Public *
8
* License as published by the Free Software Foundation; either *
9
* version 2 of the License, or (at your option) any later version. *
11
* This library is distributed in the hope that it will be useful, *
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14
* GNU Library General Public License for more details. *
16
* You should have received a copy of the GNU Library General Public *
17
* License along with this library; see the file COPYING.LIB. If not, *
18
* write to the Free Software Foundation, Inc., 59 Temple Place, *
19
* Suite 330, Boston, MA 02111-1307, USA *
21
***************************************************************************/
23
#include "PreCompiled.h"
38
static inline void checkPow(UnitSignature sig, double exp)
40
auto isInt = [](double value) {
41
return std::fabs(std::round(value) - value) < std::numeric_limits<double>::epsilon();
43
if (!isInt(sig.Length * exp) ||
44
!isInt(sig.Mass * exp) ||
45
!isInt(sig.Time * exp) ||
46
!isInt(sig.ElectricCurrent * exp) ||
47
!isInt(sig.ThermodynamicTemperature * exp) ||
48
!isInt(sig.AmountOfSubstance * exp) ||
49
!isInt(sig.LuminousIntensity * exp) ||
50
!isInt(sig.Angle * exp)) {
51
throw Base::UnitsMismatchError("pow() of unit not possible");
55
static inline void checkRange(const char * op, int length, int mass, int time, int electricCurrent,
56
int thermodynamicTemperature, int amountOfSubstance, int luminousIntensity, int angle)
58
if ( ( length >= (1 << (UnitSignatureLengthBits - 1)) ) ||
59
( mass >= (1 << (UnitSignatureMassBits - 1)) ) ||
60
( time >= (1 << (UnitSignatureTimeBits - 1)) ) ||
61
( electricCurrent >= (1 << (UnitSignatureElectricCurrentBits - 1)) ) ||
62
( thermodynamicTemperature >= (1 << (UnitSignatureThermodynamicTemperatureBits - 1)) ) ||
63
( amountOfSubstance >= (1 << (UnitSignatureAmountOfSubstanceBits - 1)) ) ||
64
( luminousIntensity >= (1 << (UnitSignatureLuminousIntensityBits - 1)) ) ||
65
( angle >= (1 << (UnitSignatureAngleBits - 1)) ) ) {
66
throw Base::OverflowError((std::string("Unit overflow in ") + std::string(op)).c_str());
68
if ( ( length < -(1 << (UnitSignatureLengthBits - 1)) ) ||
69
( mass < -(1 << (UnitSignatureMassBits - 1)) ) ||
70
( time < -(1 << (UnitSignatureTimeBits - 1)) ) ||
71
( electricCurrent < -(1 << (UnitSignatureElectricCurrentBits - 1)) ) ||
72
( thermodynamicTemperature < -(1 << (UnitSignatureThermodynamicTemperatureBits - 1)) ) ||
73
( amountOfSubstance < -(1 << (UnitSignatureAmountOfSubstanceBits - 1)) ) ||
74
( luminousIntensity < -(1 << (UnitSignatureLuminousIntensityBits - 1)) ) ||
75
( angle < -(1 << (UnitSignatureAngleBits - 1)) ) ) {
76
throw Base::UnderflowError((std::string("Unit underflow in ") + std::string(op)).c_str());
80
Unit::Unit(int8_t Length, //NOLINT
83
int8_t ElectricCurrent,
84
int8_t ThermodynamicTemperature,
85
int8_t AmountOfSubstance,
86
int8_t LuminousIntensity,
94
ThermodynamicTemperature,
102
Sig.ElectricCurrent = ElectricCurrent;
103
Sig.ThermodynamicTemperature = ThermodynamicTemperature;
104
Sig.AmountOfSubstance = AmountOfSubstance;
105
Sig.LuminousIntensity = LuminousIntensity;
115
Sig.ElectricCurrent = 0;
116
Sig.ThermodynamicTemperature = 0;
117
Sig.AmountOfSubstance = 0;
118
Sig.LuminousIntensity = 0;
122
Unit::Unit(const QString& expr) // NOLINT
125
*this = Quantity::parse(expr).getUnit();
127
catch (const Base::ParserError&) {
131
Sig.ElectricCurrent = 0;
132
Sig.ThermodynamicTemperature = 0;
133
Sig.AmountOfSubstance = 0;
134
Sig.LuminousIntensity = 0;
139
Unit Unit::pow(double exp) const
143
static_cast<int>(Sig.Length * exp),
144
static_cast<int>(Sig.Mass * exp),
145
static_cast<int>(Sig.Time * exp),
146
static_cast<int>(Sig.ElectricCurrent * exp),
147
static_cast<int>(Sig.ThermodynamicTemperature * exp),
148
static_cast<int>(Sig.AmountOfSubstance * exp),
149
static_cast<int>(Sig.LuminousIntensity * exp),
150
static_cast<int>(Sig.Angle * exp));
153
result.Sig.Length = static_cast<int8_t>(Sig.Length * exp);
154
result.Sig.Mass = static_cast<int8_t>(Sig.Mass * exp);
155
result.Sig.Time = static_cast<int8_t>(Sig.Time * exp);
156
result.Sig.ElectricCurrent = static_cast<int8_t>(Sig.ElectricCurrent * exp);
157
result.Sig.ThermodynamicTemperature = static_cast<int8_t>(Sig.ThermodynamicTemperature * exp);
158
result.Sig.AmountOfSubstance = static_cast<int8_t>(Sig.AmountOfSubstance * exp);
159
result.Sig.LuminousIntensity = static_cast<int8_t>(Sig.LuminousIntensity * exp);
160
result.Sig.Angle = static_cast<int8_t>(Sig.Angle * exp);
165
bool Unit::isEmpty()const
167
return (this->Sig.Length == 0)
168
&& (this->Sig.Mass == 0)
169
&& (this->Sig.Time == 0)
170
&& (this->Sig.ElectricCurrent == 0)
171
&& (this->Sig.ThermodynamicTemperature == 0)
172
&& (this->Sig.AmountOfSubstance == 0)
173
&& (this->Sig.LuminousIntensity == 0)
174
&& (this->Sig.Angle == 0);
177
bool Unit::operator ==(const Unit& that) const
179
return (this->Sig.Length == that.Sig.Length)
180
&& (this->Sig.Mass == that.Sig.Mass)
181
&& (this->Sig.Time == that.Sig.Time)
182
&& (this->Sig.ElectricCurrent == that.Sig.ElectricCurrent)
183
&& (this->Sig.ThermodynamicTemperature == that.Sig.ThermodynamicTemperature)
184
&& (this->Sig.AmountOfSubstance == that.Sig.AmountOfSubstance)
185
&& (this->Sig.LuminousIntensity == that.Sig.LuminousIntensity)
186
&& (this->Sig.Angle == that.Sig.Angle);
190
Unit Unit::operator *(const Unit &right) const
192
checkRange("* operator",
193
Sig.Length +right.Sig.Length,
194
Sig.Mass + right.Sig.Mass,
195
Sig.Time + right.Sig.Time,
196
Sig.ElectricCurrent + right.Sig.ElectricCurrent,
197
Sig.ThermodynamicTemperature + right.Sig.ThermodynamicTemperature,
198
Sig.AmountOfSubstance + right.Sig.AmountOfSubstance,
199
Sig.LuminousIntensity + right.Sig.LuminousIntensity,
200
Sig.Angle + right.Sig.Angle);
203
result.Sig.Length = Sig.Length + right.Sig.Length;
204
result.Sig.Mass = Sig.Mass + right.Sig.Mass;
205
result.Sig.Time = Sig.Time + right.Sig.Time;
206
result.Sig.ElectricCurrent = Sig.ElectricCurrent + right.Sig.ElectricCurrent;
207
result.Sig.ThermodynamicTemperature = Sig.ThermodynamicTemperature + right.Sig.ThermodynamicTemperature;
208
result.Sig.AmountOfSubstance = Sig.AmountOfSubstance + right.Sig.AmountOfSubstance;
209
result.Sig.LuminousIntensity = Sig.LuminousIntensity + right.Sig.LuminousIntensity;
210
result.Sig.Angle = Sig.Angle + right.Sig.Angle;
215
Unit Unit::operator /(const Unit &right) const
217
checkRange("/ operator",
218
Sig.Length - right.Sig.Length,
219
Sig.Mass - right.Sig.Mass,
220
Sig.Time - right.Sig.Time,
221
Sig.ElectricCurrent - right.Sig.ElectricCurrent,
222
Sig.ThermodynamicTemperature - right.Sig.ThermodynamicTemperature,
223
Sig.AmountOfSubstance - right.Sig.AmountOfSubstance,
224
Sig.LuminousIntensity - right.Sig.LuminousIntensity,
225
Sig.Angle - right.Sig.Angle);
228
result.Sig.Length = Sig.Length - right.Sig.Length;
229
result.Sig.Mass = Sig.Mass - right.Sig.Mass;
230
result.Sig.Time = Sig.Time - right.Sig.Time;
231
result.Sig.ElectricCurrent = Sig.ElectricCurrent - right.Sig.ElectricCurrent;
232
result.Sig.ThermodynamicTemperature = Sig.ThermodynamicTemperature - right.Sig.ThermodynamicTemperature;
233
result.Sig.AmountOfSubstance = Sig.AmountOfSubstance - right.Sig.AmountOfSubstance;
234
result.Sig.LuminousIntensity = Sig.LuminousIntensity - right.Sig.LuminousIntensity;
235
result.Sig.Angle = Sig.Angle - right.Sig.Angle;
240
QString Unit::getString() const
242
std::stringstream ret;
248
if (Sig.Length > 0 ||
251
Sig.ElectricCurrent > 0 ||
252
Sig.ThermodynamicTemperature> 0 ||
253
Sig.AmountOfSubstance > 0 ||
254
Sig.LuminousIntensity > 0 ||
258
if (Sig.Length > 0) {
261
if (Sig.Length > 1) {
262
ret << "^" << Sig.Length;
273
ret << "^" << Sig.Mass;
284
ret << "^" << Sig.Time;
288
if (Sig.ElectricCurrent > 0) {
294
if (Sig.ElectricCurrent > 1) {
295
ret << "^" << Sig.ElectricCurrent;
299
if (Sig.ThermodynamicTemperature > 0) {
305
if (Sig.ThermodynamicTemperature > 1) {
306
ret << "^" << Sig.ThermodynamicTemperature;
310
if (Sig.AmountOfSubstance > 0){
316
if (Sig.AmountOfSubstance > 1) {
317
ret << "^" << Sig.AmountOfSubstance;
321
if (Sig.LuminousIntensity > 0) {
327
if (Sig.LuminousIntensity > 1) {
328
ret << "^" << Sig.LuminousIntensity;
336
mult = true; //NOLINT
339
ret << "^" << Sig.Angle;
347
if (Sig.Length < 0 ||
350
Sig.ElectricCurrent < 0 ||
351
Sig.ThermodynamicTemperature< 0 ||
352
Sig.AmountOfSubstance < 0 ||
353
Sig.LuminousIntensity < 0 ||
358
nnom += Sig.Length<0?1:0;
359
nnom += Sig.Mass<0?1:0;
360
nnom += Sig.Time<0?1:0;
361
nnom += Sig.ElectricCurrent<0?1:0;
362
nnom += Sig.ThermodynamicTemperature<0?1:0;
363
nnom += Sig.AmountOfSubstance<0?1:0;
364
nnom += Sig.LuminousIntensity<0?1:0;
365
nnom += Sig.Angle<0?1:0;
372
if (Sig.Length < 0) {
375
if (Sig.Length < -1) {
376
ret << "^" << abs(Sig.Length);
387
ret << "^" << abs(Sig.Mass);
398
ret << "^" << abs(Sig.Time);
402
if (Sig.ElectricCurrent < 0) {
408
if (Sig.ElectricCurrent < -1) {
409
ret << "^" << abs(Sig.ElectricCurrent);
413
if (Sig.ThermodynamicTemperature < 0) {
419
if (Sig.ThermodynamicTemperature < -1) {
420
ret << "^" << abs(Sig.ThermodynamicTemperature);
424
if (Sig.AmountOfSubstance < 0) {
430
if (Sig.AmountOfSubstance < -1) {
431
ret << "^" << abs(Sig.AmountOfSubstance);
435
if (Sig.LuminousIntensity < 0) {
441
if (Sig.LuminousIntensity < -1) {
442
ret << "^" << abs(Sig.LuminousIntensity);
450
mult = true; //NOLINT
452
if (Sig.Angle < -1) {
453
ret << "^" << abs(Sig.Angle);
462
return QString::fromUtf8(ret.str().c_str());
465
QString Unit::getTypeString() const
467
if (*this == Unit::Acceleration) {
468
return QString::fromLatin1("Acceleration");
470
if (*this == Unit::AmountOfSubstance) {
471
return QString::fromLatin1("AmountOfSubstance");
473
if (*this == Unit::Angle) {
474
return QString::fromLatin1("Angle");
476
if (*this == Unit::AngleOfFriction) {
477
return QString::fromLatin1("AngleOfFriction");
479
if (*this == Unit::Area) {
480
return QString::fromLatin1("Area");
482
if (*this == Unit::CurrentDensity) {
483
return QString::fromLatin1("CurrentDensity");
485
if (*this == Unit::Density) {
486
return QString::fromLatin1("Density");
488
if (*this == Unit::DissipationRate) {
489
return QString::fromLatin1("DissipationRate");
491
if (*this == Unit::DynamicViscosity) {
492
return QString::fromLatin1("DynamicViscosity");
494
if (*this == Unit::ElectricalCapacitance) {
495
return QString::fromLatin1("ElectricalCapacitance");
497
if (*this == Unit::ElectricalConductance) {
498
return QString::fromLatin1("ElectricalConductance");
500
if (*this == Unit::ElectricalConductivity) {
501
return QString::fromLatin1("ElectricalConductivity");
503
if (*this == Unit::ElectricalInductance) {
504
return QString::fromLatin1("ElectricalInductance");
506
if (*this == Unit::ElectricalResistance) {
507
return QString::fromLatin1("ElectricalResistance");
509
if (*this == Unit::ElectricCharge) {
510
return QString::fromLatin1("ElectricCharge");
512
if (*this == Unit::ElectricCurrent) {
513
return QString::fromLatin1("ElectricCurrent");
515
if (*this == Unit::ElectricPotential) {
516
return QString::fromLatin1("ElectricPotential");
518
if (*this == Unit::Frequency) {
519
return QString::fromLatin1("Frequency");
521
if (*this == Unit::Force) {
522
return QString::fromLatin1("Force");
524
if (*this == Unit::HeatFlux) {
525
return QString::fromLatin1("HeatFlux");
527
if (*this == Unit::InverseArea) {
528
return QString::fromLatin1("InverseArea");
530
if (*this == Unit::InverseLength) {
531
return QString::fromLatin1("InverseLength");
533
if (*this == Unit::InverseVolume) {
534
return QString::fromLatin1("InverseVolume");
536
if (*this == Unit::KinematicViscosity) {
537
return QString::fromLatin1("KinematicViscosity");
539
if (*this == Unit::Length) {
540
return QString::fromLatin1("Length");
542
if (*this == Unit::LuminousIntensity) {
543
return QString::fromLatin1("LuminousIntensity");
545
if (*this == Unit::MagneticFieldStrength) {
546
return QString::fromLatin1("MagneticFieldStrength");
548
if (*this == Unit::MagneticFlux) {
549
return QString::fromLatin1("MagneticFlux");
551
if (*this == Unit::MagneticFluxDensity) {
552
return QString::fromLatin1("MagneticFluxDensity");
554
if (*this == Unit::Magnetization) {
555
return QString::fromLatin1("Magnetization");
557
if (*this == Unit::Mass) {
558
return QString::fromLatin1("Mass");
560
if (*this == Unit::Pressure) {
561
return QString::fromLatin1("Pressure");
563
if (*this == Unit::Power) {
564
return QString::fromLatin1("Power");
566
if (*this == Unit::ShearModulus) {
567
return QString::fromLatin1("ShearModulus");
569
if (*this == Unit::SpecificEnergy) {
570
return QString::fromLatin1("SpecificEnergy");
572
if (*this == Unit::SpecificHeat) {
573
return QString::fromLatin1("SpecificHeat");
575
if (*this == Unit::Stiffness) {
576
return QString::fromLatin1("Stiffness");
578
if (*this == Unit::StiffnessDensity) {
579
return QString::fromLatin1("StiffnessDensity");
581
if (*this == Unit::Stress) {
582
return QString::fromLatin1("Stress");
584
if (*this == Unit::Temperature) {
585
return QString::fromLatin1("Temperature");
587
if (*this == Unit::ThermalConductivity) {
588
return QString::fromLatin1("ThermalConductivity");
590
if (*this == Unit::ThermalExpansionCoefficient) {
591
return QString::fromLatin1("ThermalExpansionCoefficient");
593
if (*this == Unit::ThermalTransferCoefficient) {
594
return QString::fromLatin1("ThermalTransferCoefficient");
596
if (*this == Unit::TimeSpan) {
597
return QString::fromLatin1("TimeSpan");
599
if (*this == Unit::UltimateTensileStrength) {
600
return QString::fromLatin1("UltimateTensileStrength");
602
if (*this == Unit::VacuumPermittivity) {
603
return QString::fromLatin1("VacuumPermittivity");
605
if (*this == Unit::Velocity) {
606
return QString::fromLatin1("Velocity");
608
if (*this == Unit::Volume) {
609
return QString::fromLatin1("Volume");
611
if (*this == Unit::VolumeFlowRate) {
612
return QString::fromLatin1("VolumeFlowRate");
614
if (*this == Unit::VolumetricThermalExpansionCoefficient) {
615
return QString::fromLatin1("VolumetricThermalExpansionCoefficient");
617
if (*this == Unit::Work) {
618
return QString::fromLatin1("Work");
620
if (*this == Unit::YieldStrength) {
621
return QString::fromLatin1("YieldStrength");
623
if (*this == Unit::YoungsModulus) {
624
return QString::fromLatin1("YoungsModulus");
631
const Unit Unit::AmountOfSubstance (0, 0, 0, 0, 0, 1);
632
const Unit Unit::ElectricCurrent (0, 0, 0, 1);
633
const Unit Unit::Length (1);
634
const Unit Unit::LuminousIntensity (0, 0, 0, 0, 0, 0, 1);
635
const Unit Unit::Mass (0, 1);
636
const Unit Unit::Temperature (0, 0, 0, 0, 1);
637
const Unit Unit::TimeSpan (0, 0, 1);
640
const Unit Unit::Acceleration (1, 0, -2);
641
const Unit Unit::Angle (0, 0, 0, 0, 0, 0, 0, 1);
642
const Unit Unit::AngleOfFriction (0, 0, 0, 0, 0, 0, 0, 1);
643
const Unit Unit::Area (2);
644
const Unit Unit::CompressiveStrength (-1, 1, -2);
645
const Unit Unit::CurrentDensity (-2, 0, 0, 1);
646
const Unit Unit::Density (-3, 1);
647
const Unit Unit::DissipationRate (2, 0, -3); // https://cfd-online.com/Wiki/Turbulence_dissipation_rate
648
const Unit Unit::DynamicViscosity (-1, 1, -1);
649
const Unit Unit::ElectricalCapacitance (-2, -1, 4, 2);
650
const Unit Unit::ElectricalConductance (-2, -1, 3, 2);
651
const Unit Unit::ElectricalConductivity (-3, -1, 3, 2);
652
const Unit Unit::ElectricalInductance (2, 1, -2, -2);
653
const Unit Unit::ElectricalResistance (2, 1, -3, -2);
654
const Unit Unit::ElectricCharge (0, 0, 1, 1);
655
const Unit Unit::ElectricPotential (2, 1, -3, -1);
656
const Unit Unit::Force (1, 1, -2);
657
const Unit Unit::Frequency (0, 0, -1);
658
const Unit Unit::HeatFlux (0, 1, -3, 0, 0);
659
const Unit Unit::InverseArea (-2, 0, 0);
660
const Unit Unit::InverseLength (-1, 0, 0);
661
const Unit Unit::InverseVolume (-3, 0, 0);
662
const Unit Unit::KinematicViscosity (2, 0, -1);
663
const Unit Unit::MagneticFieldStrength (-1,0,0,1);
664
const Unit Unit::MagneticFlux (2,1,-2,-1);
665
const Unit Unit::MagneticFluxDensity (0,1,-2,-1);
666
const Unit Unit::Magnetization (-1,0,0,1);
667
const Unit Unit::Pressure (-1,1,-2);
668
const Unit Unit::Power (2, 1, -3);
669
const Unit Unit::ShearModulus (-1,1,-2);
670
const Unit Unit::SpecificEnergy (2, 0, -2);
671
const Unit Unit::SpecificHeat (2, 0, -2, 0, -1);
672
const Unit Unit::Stiffness (0, 1, -2);
673
const Unit Unit::StiffnessDensity (-2, 1, -2);
674
const Unit Unit::Stress (-1,1,-2);
675
const Unit Unit::ThermalConductivity (1, 1, -3, 0, -1);
676
const Unit Unit::ThermalExpansionCoefficient(0, 0, 0, 0, -1);
677
const Unit Unit::ThermalTransferCoefficient (0, 1, -3, 0, -1);
678
const Unit Unit::UltimateTensileStrength (-1,1,-2);
679
const Unit Unit::VacuumPermittivity (-3, -1, 4, 2);
680
const Unit Unit::Velocity (1, 0, -1);
681
const Unit Unit::Volume (3);
682
const Unit Unit::VolumeFlowRate (3, 0, -1);
683
const Unit Unit::VolumetricThermalExpansionCoefficient(0, 0, 0, 0, -1);
684
const Unit Unit::Work (2, 1, -2);
685
const Unit Unit::YieldStrength (-1,1,-2);
686
const Unit Unit::YoungsModulus (-1,1,-2);