File indexing completed on 2026-06-02 08:51:49
0001 #ifndef PHYSICAL_TYPE_H
0002 #define PHYSICAL_TYPE_H
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <ElementaryUtils/logger/CustomException.h>
0012 #include <ElementaryUtils/parameters/GenericType.h>
0013 #include <ElementaryUtils/string_utils/Formatter.h>
0014 #include <ElementaryUtils/thread/Packet.h>
0015 #include <iterator>
0016 #include <sstream>
0017 #include <string>
0018 #include <vector>
0019
0020 #include "../../BaseObject.h"
0021 #include "PhysicalUnit.h"
0022
0023 namespace PARTONS {
0024
0025
0026
0027
0028
0029
0030
0031
0032 template<class T>
0033 class PhysicalType: public BaseObject {
0034
0035 public:
0036
0037
0038
0039
0040 PhysicalType() :
0041 BaseObject("PhysicalType"), m_initialized(false), m_value(), m_unit(
0042 PhysicalUnit::UNDEFINED) {
0043 }
0044
0045
0046
0047
0048 PhysicalType(PhysicalUnit::Type unit) :
0049 BaseObject("PhysicalType"), m_initialized(false), m_value(), m_unit(
0050 unit) {
0051 }
0052
0053
0054
0055
0056 PhysicalType(T value, PhysicalUnit::Type unit) :
0057 BaseObject("PhysicalType"), m_initialized(true), m_value(value), m_unit(
0058 unit) {
0059 }
0060
0061
0062
0063
0064 PhysicalType(const std::string &stringValue, PhysicalUnit::Type unit) :
0065 BaseObject("PhysicalType"), m_initialized(true), m_unit(unit) {
0066 valueFromStdString(stringValue);
0067 }
0068
0069
0070
0071
0072 PhysicalType(const ElemUtils::GenericType& value, PhysicalUnit::Type unit) :
0073 BaseObject("PhysicalType"), m_initialized(true), m_unit(unit) {
0074 valueFromStdString(value.getString());
0075 }
0076
0077
0078
0079
0080 PhysicalType(const PhysicalType& other) :
0081 BaseObject(other), m_initialized(other.m_initialized), m_value(
0082 other.m_value), m_unit(other.m_unit) {
0083
0084 }
0085
0086
0087
0088
0089 std::string toString() const {
0090
0091 ElemUtils::Formatter formatter;
0092
0093 formatter << m_value;
0094 formatter << " [";
0095 formatter << PhysicalUnit(m_unit).getShortName();
0096 formatter << "]";
0097
0098 return formatter.str();
0099 }
0100
0101
0102
0103
0104
0105 void serialize(ElemUtils::Packet &packet) const {
0106 packet << m_initialized << m_value << PhysicalUnit(m_unit);
0107 }
0108
0109
0110
0111
0112
0113 void unserialize(ElemUtils::Packet &packet) {
0114
0115 packet >> m_initialized;
0116 packet >> m_value;
0117
0118 PhysicalUnit type;
0119 packet >> type;
0120 m_unit = type;
0121 }
0122
0123
0124
0125
0126 void serializeIntoStdVector(std::vector<double>& vec) const {
0127
0128 vec.push_back(static_cast<double>(m_initialized));
0129 vec.push_back(static_cast<double>(m_value));
0130 vec.push_back(static_cast<double>(m_unit));
0131 }
0132
0133
0134
0135
0136 void unserializeFromStdVector(std::vector<double>::const_iterator& it,
0137 const std::vector<double>::const_iterator& end) {
0138
0139 if (it >= end) {
0140 throw ElemUtils::CustomException(this->getClassName(), __func__,
0141 "Input vector is too short");
0142 }
0143
0144 m_initialized = static_cast<bool>(*it);
0145 it++;
0146
0147 if (it >= end) {
0148 throw ElemUtils::CustomException(this->getClassName(), __func__,
0149 "Input vector is too short");
0150 }
0151
0152 m_value = static_cast<T>(*it);
0153 it++;
0154
0155 if (it >= end) {
0156 throw ElemUtils::CustomException(this->getClassName(), __func__,
0157 "Input vector is too short");
0158 }
0159
0160 m_unit = static_cast<PhysicalUnit::Type>(*it);
0161 it++;
0162 }
0163
0164
0165
0166
0167 std::string toStdString() const {
0168
0169 std::stringstream sstream;
0170 sstream << m_value << " " << m_unit;
0171 return sstream.str();
0172 }
0173
0174
0175
0176
0177 inline PhysicalType<T>& operator=(PhysicalType<T> const &rhs) {
0178
0179 setValue(rhs.m_value);
0180 setUnit(rhs.m_unit);
0181 setInitialized(rhs.m_initialized);
0182
0183 return *this;
0184 }
0185
0186
0187
0188
0189 inline T operator()() {
0190 return m_value;
0191 }
0192
0193
0194
0195
0196
0197
0198
0199
0200 T getValue() const {
0201 return m_value;
0202 }
0203
0204
0205
0206
0207 void setValue(T value) {
0208
0209 m_value = value;
0210 m_initialized = true;
0211 }
0212
0213
0214
0215
0216 PhysicalUnit::Type getUnit() const {
0217 return m_unit;
0218 }
0219
0220
0221
0222
0223 void setUnit(PhysicalUnit::Type unit) {
0224 m_unit = unit;
0225 }
0226
0227
0228
0229
0230 bool isInitialized() const {
0231 return m_initialized;
0232 }
0233
0234
0235
0236
0237 void setInitialized(bool initialized) {
0238 m_initialized = initialized;
0239 }
0240
0241
0242
0243
0244 PhysicalType<T> makeSameUnitAs(PhysicalUnit::Type other) const {
0245
0246
0247 if (m_unit != other) {
0248
0249
0250 checkIfSameUnitCategoryAs(other);
0251
0252
0253 if (other == PhysicalUnit::UNDEFINED) {
0254 throw ElemUtils::CustomException(this->getClassName(), __func__,
0255 "Can not make conversion from PhysicalUnit::UNDEFINED");
0256 }
0257
0258
0259 return PhysicalType<T>(
0260 m_value * PhysicalUnit(m_unit).getConversionFactor()
0261 / PhysicalUnit(other).getConversionFactor(), other);
0262 }
0263
0264
0265 return PhysicalType<T>(*this);
0266 }
0267
0268
0269
0270
0271 PhysicalType<T> makeSameUnitAs(const PhysicalType<T>& other) const {
0272 return makeSameUnitAs(other.getUnit());
0273 }
0274
0275
0276
0277
0278 void checkIfSameUnitAs(PhysicalUnit::Type other) const {
0279 if (m_unit != other) {
0280 throw ElemUtils::CustomException(this->getClassName(), __func__,
0281 ElemUtils::Formatter() << "Units are different, this unit: "
0282 << PhysicalUnit(m_unit).toString()
0283 << " other unit: "
0284 << PhysicalUnit(other).toString());
0285 }
0286 }
0287
0288
0289
0290
0291 void checkIfSameUnitAs(const PhysicalType<T>& other) const {
0292 checkIfSameUnitAs(other.getUnit());
0293 }
0294
0295
0296
0297
0298 void checkIfSameUnitCategoryAs(PhysicalUnit::Type other) const {
0299 if (PhysicalUnit(m_unit).getUnitCategory()
0300 != PhysicalUnit(other).getUnitCategory()) {
0301 throw ElemUtils::CustomException(this->getClassName(), __func__,
0302 ElemUtils::Formatter()
0303 << "Units have different categories, this unit: "
0304 << PhysicalUnit(m_unit).toString()
0305 << " other unit: "
0306 << PhysicalUnit(other).toString());
0307 }
0308 }
0309
0310
0311
0312
0313 void checkIfSameUnitCategoryAs(const PhysicalType<T>& other) const {
0314 checkIfSameUnitCategoryAs(other.getUnit());
0315 }
0316
0317 private:
0318
0319
0320
0321
0322 void valueFromStdString(const std::string &stringValue) {
0323
0324
0325 std::stringstream sstream(stringValue);
0326
0327
0328 if ((sstream >> m_value).fail()) {
0329 throw ElemUtils::CustomException(getClassName(), __func__,
0330 ElemUtils::Formatter()
0331 << "Cast from std::string to type<T> failed for: "
0332 << stringValue);
0333 }
0334 }
0335
0336
0337
0338
0339 bool m_initialized;
0340
0341
0342
0343
0344 T m_value;
0345
0346
0347
0348
0349 PhysicalUnit::Type m_unit;
0350 };
0351
0352
0353
0354
0355 template<class T>
0356 ElemUtils::Packet& operator <<(ElemUtils::Packet& packet,
0357 const PhysicalType<T>& physicalType) {
0358
0359 physicalType.serialize(packet);
0360 return packet;
0361 }
0362
0363
0364
0365
0366 template<class T>
0367 ElemUtils::Packet& operator >>(ElemUtils::Packet& packet,
0368 PhysicalType<T>& physicalType) {
0369
0370 physicalType.unserialize(packet);
0371 return packet;
0372 }
0373
0374
0375
0376 template<class T>
0377 inline bool operator==(PhysicalType<T> const &lhs, PhysicalType<T> const &rhs) {
0378 return (lhs.getValue() == rhs.makeSameUnitAs(lhs).getValue());
0379 }
0380
0381 template<class T>
0382 inline bool operator!=(PhysicalType<T> const &lhs, PhysicalType<T> const &rhs) {
0383 return (lhs.getValue() != rhs.makeSameUnitAs(lhs).getValue());
0384 }
0385
0386 template<class T>
0387 inline bool operator<(PhysicalType<T> const &lhs, PhysicalType<T> const &rhs) {
0388 return (lhs.getValue() < rhs.makeSameUnitAs(lhs).getValue());
0389 }
0390
0391 template<class T>
0392 inline bool operator>(PhysicalType<T> const &lhs, PhysicalType<T> const &rhs) {
0393 return (lhs.getValue() > rhs.makeSameUnitAs(lhs).getValue());
0394 }
0395
0396 template<class T>
0397 inline bool operator<=(PhysicalType<T> const &lhs, PhysicalType<T> const &rhs) {
0398 return (lhs.getValue() <= rhs.makeSameUnitAs(lhs).getValue());
0399 }
0400
0401 template<class T>
0402 inline bool operator>=(PhysicalType<T> const &lhs, PhysicalType<T> const &rhs) {
0403 return (lhs.getValue() >= rhs.makeSameUnitAs(lhs).getValue());
0404 }
0405
0406
0407
0408 template<class T>
0409 inline PhysicalType<T> operator+(PhysicalType<T> const &lhs,
0410 PhysicalType<T> const &rhs) {
0411
0412 lhs.checkIfSameUnitAs(rhs);
0413 return PhysicalType<T>(lhs.getValue() + rhs.getValue(), lhs.getUnit());
0414 }
0415
0416 template<class T>
0417 inline PhysicalType<T>& operator+=(PhysicalType<T> &lhs,
0418 PhysicalType<T> const &rhs) {
0419 lhs = lhs + rhs;
0420 return lhs;
0421 }
0422
0423 template<class T>
0424 inline PhysicalType<T> operator-(PhysicalType<T> const &lhs,
0425 PhysicalType<T> const &rhs) {
0426
0427 lhs.checkIfSameUnitAs(rhs);
0428 return PhysicalType<T>(lhs.getValue() - rhs.getValue(), lhs.getUnit());
0429 }
0430
0431 template<class T>
0432 inline PhysicalType<T>& operator-=(PhysicalType<T> &lhs,
0433 PhysicalType<T> const &rhs) {
0434 lhs = lhs - rhs;
0435 return lhs;
0436 }
0437
0438 template<class T>
0439 inline PhysicalType<T> operator/(PhysicalType<T> const &lhs,
0440 PhysicalType<T> const &rhs) {
0441
0442 lhs.checkIfSameUnitAs(rhs);
0443 return PhysicalType<T>(lhs.getValue() / rhs.getValue(), PhysicalUnit::NONE);
0444 }
0445
0446 template<class T>
0447 inline PhysicalType<T>& operator/=(PhysicalType<T> &lhs,
0448 PhysicalType<T> const &rhs) {
0449 lhs = lhs / rhs;
0450 return lhs;
0451 }
0452
0453
0454
0455 template<class T>
0456 inline PhysicalType<T> operator*(PhysicalType<T> const &lhs, T const &rhs) {
0457 return PhysicalType<T>(lhs.getValue() * rhs, lhs.getUnit());
0458 }
0459
0460 template<class T>
0461 inline PhysicalType<T>& operator*=(PhysicalType<T> &lhs, T const &rhs) {
0462 lhs = lhs * rhs;
0463 return lhs;
0464 }
0465
0466 template<class T>
0467 inline PhysicalType<T> operator*(T const &lhs, PhysicalType<T> const &rhs) {
0468 return PhysicalType<T>(lhs * rhs.getValue(), rhs.getUnit());
0469 }
0470
0471 template<class T>
0472 inline PhysicalType<T> operator/(PhysicalType<T> const &lhs, T const &rhs) {
0473 return PhysicalType<T>(lhs.getValue() / rhs, lhs.getUnit());
0474 }
0475
0476 template<class T>
0477 inline PhysicalType<T>& operator/=(PhysicalType<T> &lhs, T const &rhs) {
0478 lhs = lhs / rhs;
0479 return lhs;
0480 }
0481
0482 }
0483
0484 #endif