Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-06-02 08:51:49

0001 #ifndef PHYSICAL_TYPE_H
0002 #define PHYSICAL_TYPE_H
0003 
0004 /**
0005  * @file PhysicalType.h
0006  * @author: Bryan BERTHOU (SPhN / CEA Saclay)
0007  * @date January 20, 2016
0008  * @version 1.0
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  * @class PhysicalType
0027  *
0028  * @brief Value with unit.
0029  *
0030  * This class is a container for a value, unit and switch to mark if the value is initialized or not. Setting a value (either via setter or one of constructors) make the object "initialized".
0031  */
0032 template<class T>
0033 class PhysicalType: public BaseObject {
0034 
0035 public:
0036 
0037     /**
0038      * Default constructor.
0039      */
0040     PhysicalType() :
0041             BaseObject("PhysicalType"), m_initialized(false), m_value(), m_unit(
0042                     PhysicalUnit::UNDEFINED) {
0043     }
0044 
0045     /**
0046      * Assignment constructor.
0047      */
0048     PhysicalType(PhysicalUnit::Type unit) :
0049             BaseObject("PhysicalType"), m_initialized(false), m_value(), m_unit(
0050                     unit) {
0051     }
0052 
0053     /**
0054      * Assignment constructor.
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      * Assignment constructor.
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      * Assignment constructor.
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      * Copy constructor.
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      * Return string representing the whole object.
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      * Serialize into given Packet.
0103      * @param packet Target Packet.
0104      */
0105     void serialize(ElemUtils::Packet &packet) const {
0106         packet << m_initialized << m_value << PhysicalUnit(m_unit);
0107     }
0108 
0109     /**
0110      * Retrieve data from given Packet.
0111      * @param packet Input Packet.
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      * Serialize into std::vector<double>
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      * Uneserialize from std::vector<double>
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      * Return string representing value and unit. To be used mainly in the generation of hash sums.
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      * Assignment operator.
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      * Operator to return value.
0188      */
0189     inline T operator()() {
0190         return m_value;
0191     }
0192 
0193     // ******************************************
0194     // **** GETTERS AND SETTERS *****************
0195     // ******************************************
0196 
0197     /**
0198      * Get value.
0199      */
0200     T getValue() const {
0201         return m_value;
0202     }
0203 
0204     /**
0205      * Set value. This function makes the object marked as initialized.
0206      */
0207     void setValue(T value) {
0208 
0209         m_value = value;
0210         m_initialized = true;
0211     }
0212 
0213     /**
0214      * Get unit.
0215      */
0216     PhysicalUnit::Type getUnit() const {
0217         return m_unit;
0218     }
0219 
0220     /**
0221      * Set unit.
0222      */
0223     void setUnit(PhysicalUnit::Type unit) {
0224         m_unit = unit;
0225     }
0226 
0227     /**
0228      * Check if initialized.
0229      */
0230     bool isInitialized() const {
0231         return m_initialized;
0232     }
0233 
0234     /**
0235      * Set as initialized.
0236      */
0237     void setInitialized(bool initialized) {
0238         m_initialized = initialized;
0239     }
0240 
0241     /**
0242      * Check if the same unit category. If units are different make the conversion.
0243      */
0244     PhysicalType<T> makeSameUnitAs(PhysicalUnit::Type other) const {
0245 
0246         //check if different units
0247         if (m_unit != other) {
0248 
0249             //check unit category
0250             checkIfSameUnitCategoryAs(other);
0251 
0252             //check if not PhysicalUnit::UNDEFINED
0253             if (other == PhysicalUnit::UNDEFINED) {
0254                 throw ElemUtils::CustomException(this->getClassName(), __func__,
0255                         "Can not make conversion from PhysicalUnit::UNDEFINED");
0256             }
0257 
0258             //make conversion
0259             return PhysicalType<T>(
0260                     m_value * PhysicalUnit(m_unit).getConversionFactor()
0261                             / PhysicalUnit(other).getConversionFactor(), other);
0262         }
0263 
0264         //return
0265         return PhysicalType<T>(*this);
0266     }
0267 
0268     /**
0269      * Check if the same unit category. If units are different make the conversion.
0270      */
0271     PhysicalType<T> makeSameUnitAs(const PhysicalType<T>& other) const {
0272         return makeSameUnitAs(other.getUnit());
0273     }
0274 
0275     /**
0276      * Check if the same unit. If units are different throw exception.
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      * Check if the same unit. If units are different throw exception.
0290      */
0291     void checkIfSameUnitAs(const PhysicalType<T>& other) const {
0292         checkIfSameUnitAs(other.getUnit());
0293     }
0294 
0295     /**
0296      * Check if the same unit category. If units are different throw exception.
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      * Check if the same unit category. If units are different throw exception.
0312      */
0313     void checkIfSameUnitCategoryAs(const PhysicalType<T>& other) const {
0314         checkIfSameUnitCategoryAs(other.getUnit());
0315     }
0316 
0317 private:
0318 
0319     /**
0320      * Set value from std::string.
0321      */
0322     void valueFromStdString(const std::string &stringValue) {
0323 
0324         //string stream
0325         std::stringstream sstream(stringValue);
0326 
0327         // if conversion failed then print an exception
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      * True if value initialized.
0338      */
0339     bool m_initialized;
0340 
0341     /**
0342      * Value.
0343      */
0344     T m_value;
0345 
0346     /**
0347      * Unit.
0348      */
0349     PhysicalUnit::Type m_unit;
0350 };
0351 
0352 /**
0353  * Stream operator to serialize class into Packet. See also Kinematic::serialize().
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  * Stream operator to retrieve class from Packet. See also GPDType::unserialize().
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 /// Comparison operators
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 /// Arithmetic operators
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 /// Arithmetic operators
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 } /* namespace PARTONS */
0483 
0484 #endif /* PHYSICAL_TYPE_H */