SST  12.0.1
StructuralSimulationToolkit
unitAlgebra.h
1 // -*- c++ -*-
2 
3 // Copyright 2009-2022 NTESS. Under the terms
4 // of Contract DE-NA0003525 with NTESS, the U.S.
5 // Government retains certain rights in this software.
6 //
7 // Copyright (c) 2009-2022, NTESS
8 // All rights reserved.
9 //
10 // This file is part of the SST software package. For license
11 // information, see the LICENSE file in the top level directory of the
12 // distribution.
13 
14 #ifndef SST_CORE_UNITALGEBRA_H
15 #define SST_CORE_UNITALGEBRA_H
16 
17 #include "sst/core/decimal_fixedpoint.h"
18 #include "sst/core/serialization/serializable.h"
19 #include "sst/core/serialization/serializer.h"
20 #include "sst/core/sst_types.h"
21 #include "sst/core/warnmacros.h"
22 
23 #include <map>
24 #include <mutex>
25 #include <string>
26 #include <vector>
27 
28 namespace SST {
29 
30 // typedef decimal_fixedpoint<3,3> sst_dec_float;
31 typedef decimal_fixedpoint<3, 3> sst_big_num;
32 
33 /**
34  * Helper class internal to UnitAlgebra.
35  *
36  * Contains information on valid units
37  */
38 class Units
39 {
40 
41  typedef uint8_t unit_id_t;
42 
43 private:
44  friend class UnitAlgebra;
45 
46  // Static data members and functions
47  static std::recursive_mutex unit_lock;
48  static std::map<std::string, unit_id_t> valid_base_units;
49  static std::map<std::string, std::pair<Units, sst_big_num>> valid_compound_units;
50  static std::map<unit_id_t, std::string> unit_strings;
51  static unit_id_t count;
52  static bool initialized;
53 
54  static bool initialize();
55 
56  // Non-static data members and functions
57  std::vector<unit_id_t> numerator;
58  std::vector<unit_id_t> denominator;
59 
60  void reduce();
61  // Used in constructor to incrementally build up unit from string
62  void addUnit(const std::string&, sst_big_num& multiplier, bool invert);
63 
64 public:
65  // Static data members and functions
66  /** Create a new Base Unit type */
67  static void registerBaseUnit(const std::string& u);
68  /** Create a new Compound Unit type */
69  static void registerCompoundUnit(const std::string& u, const std::string& v);
70 
71  // Non-static data members and functions
72  /** Create a new instantiation of a Units with a base unit string, and multiplier
73  * \param units String representing the new unit
74  * \param multiplier Value by which to multiply to get to this unit
75  */
76  Units(const std::string& units, sst_big_num& multiplier);
77  Units() {}
78  virtual ~Units() {}
79 
80  /** Copy constructor */
81  Units(const Units&) = default;
82 
83  /** Assignment operator */
84  Units& operator=(const Units& v);
85  /** Self-multiplication operator */
86  Units& operator*=(const Units& v);
87  /** Self-division operator */
88  Units& operator/=(const Units& v);
89  /** Equality Operator */
90  bool operator==(const Units& lhs) const;
91  /** Inequality Operator */
92  bool operator!=(const Units& lhs) const { return !(*this == lhs); }
93  /** Perform a reciprocal operation. Numerator and Denominator swap. */
94  Units& invert();
95 
96  /** Return a String representation if this Unit */
97  std::string toString() const;
98 };
99 
100 /**
101  * Performs Unit math in full precision
102  *
103  * Allows operations such as multiplying a frequency by 2.
104  *
105  */
106 class UnitAlgebra :
109 {
110 private:
111  Units unit;
112  sst_big_num value;
113 
114  static std::string trim(const std::string& str);
115 
116 public:
117  void init(const std::string& val);
118 
119  UnitAlgebra() {}
120  /**
121  Create a new UnitAlgebra instance, and pre-populate with a parsed value.
122 
123  \param val Value to parse. It is of the following format:
124  \code
125  val := NUMBER( )?UNITS
126  NUMBER := (-)?[0-9]+(.[0-9]+)?
127  UNITS := UNITGROUP(/UNITGROUP)
128  UNITGROUP := UNIT(-UNIT)*
129  UNIT := (SIPREFIX)?(BASEUNIT|COMPUNIT)
130  SIPREFIX := {a,f,p,n,u,m,[kKMGTPE]i?}
131  BASEUNIT := {s,B,b,events}
132  COMPUNIT := {Hz,hz,Bps,bps,event}
133  \endcode
134  */
135  UnitAlgebra(const std::string& val);
136  virtual ~UnitAlgebra();
137 
138  /** Copy constructor */
139  UnitAlgebra(const UnitAlgebra&) = default;
140 
141  /** Print to an ostream the value */
142  void print(std::ostream& stream);
143  /** Print to an ostream the value
144  * Formats the number using SI-prefixes
145  */
146  void printWithBestSI(std::ostream& stream);
147  /** Return a string representation of this value */
148  std::string toString() const;
149  /** Return a string representation of this value
150  * Formats the number using SI-prefixes
151  */
152  std::string toStringBestSI() const;
153 
154  UnitAlgebra& operator=(const std::string& v);
155 
156  /** Multiply by an argument; */
158  /** Multiply by an argument; */
159  template <typename T>
160  UnitAlgebra& operator*=(const T& v)
161  {
162  value *= v;
163  return *this;
164  }
165 
166  /** Divide by an argument; */
168  /** Divide by an argument; */
169  template <typename T>
170  UnitAlgebra& operator/=(const T& v)
171  {
172  value /= v;
173  return *this;
174  }
175 
176  /** Add an argument; */
178  /** Multiply by an argument; */
179  template <typename T>
180  UnitAlgebra& operator+=(const T& v)
181  {
182  value += v;
183  return *this;
184  }
185 
186  /** Subtract an argument; */
188  /** Divide by an argument; */
189  template <typename T>
190  UnitAlgebra& operator-=(const T& v)
191  {
192  value -= v;
193  return *this;
194  }
195 
196  /** Compare if this object is greater than the argument */
197  bool operator>(const UnitAlgebra& v) const;
198  /** Compare if this object is greater than, or equal to, the argument */
199  bool operator>=(const UnitAlgebra& v) const;
200  /** Compare if this object is less than the argument */
201  bool operator<(const UnitAlgebra& v) const;
202  /** Compare if this object is less than, or equal to, the argument */
203  bool operator<=(const UnitAlgebra& v) const;
204  /** Compare if this object is equal to, the argument */
205  bool operator==(const UnitAlgebra& v) const;
206  /** Compare if this object is not equal to, the argument */
207  bool operator!=(const UnitAlgebra& v) const;
208  /** Apply a reciprocal operation to the object */
209  UnitAlgebra& invert();
210 
211  /** Returns true if the units in the parameter string are found
212  * in this object.
213  */
214  bool hasUnits(const std::string& u) const;
215  /** Return the raw value */
216  sst_big_num getValue() const { return value; }
217  /** Return the rounded value as a 64bit integer */
218  int64_t getRoundedValue() const;
219  double getDoubleValue() const;
220  bool isValueZero() const;
221 
222  void serialize_order(SST::Core::Serialization::serializer& ser) override
223  {
224  // Do the unit
225  ser& unit.numerator;
226  ser& unit.denominator;
227 
228  // For value, need to convert cpp_dec_float to string and
229  // reinit from string
230  switch ( ser.mode() ) {
231  case SST::Core::Serialization::serializer::SIZER:
232  case SST::Core::Serialization::serializer::PACK:
233  {
234  // std::string s = value.str(40, std::ios_base::fixed);
235  std::string s = value.toString(0);
236  ser& s;
237  break;
238  }
239  case SST::Core::Serialization::serializer::UNPACK:
240  {
241  std::string s;
242  ser& s;
243  value = sst_big_num(s);
244  break;
245  }
246  }
247  }
248  ImplementSerializable(SST::UnitAlgebra)
249 };
250 
251 // template <typename T>
252 // UnitAlgebra operator* (UnitAlgebra lhs, const T& rhs);
253 
254 // template <typename T>
255 // UnitAlgebra operator* (const T& lhs, UnitAlgebra rhs);
256 
257 // UnitAlgebra operator* (UnitAlgebra& lhs, const UnitAlgebra rhs);
258 
259 // template <typename T>
260 // UnitAlgebra operator/ (UnitAlgebra lhs, const T& rhs);
261 
262 // std::ostream& operator<< (std::ostream& os, const UnitAlgebra& r);
263 
264 // std::ostream& operator<< (std::ostream& os, const Units& r);
265 
266 template <typename T>
267 UnitAlgebra
268 operator*(UnitAlgebra lhs, const T& rhs)
269 {
270  lhs *= rhs;
271  return lhs;
272 }
273 
274 // template <typename T>
275 // UnitAlgebra operator* (const T& lhs, UnitAlgebra rhs)
276 // {
277 // rhs *= lhs;
278 // return rhs;
279 // }
280 
281 inline UnitAlgebra
282 operator*(UnitAlgebra lhs, const UnitAlgebra& rhs)
283 {
284  lhs *= rhs;
285  return lhs;
286 }
287 
288 template <typename T>
289 UnitAlgebra
290 operator/(UnitAlgebra lhs, const T& rhs)
291 {
292  lhs /= rhs;
293  return lhs;
294 }
295 
296 inline UnitAlgebra
297 operator/(UnitAlgebra lhs, const UnitAlgebra& rhs)
298 {
299  lhs /= rhs;
300  return lhs;
301 }
302 
303 template <typename T>
304 UnitAlgebra
305 operator+(UnitAlgebra lhs, const T& rhs)
306 {
307  lhs += rhs;
308  return lhs;
309 }
310 
311 inline UnitAlgebra
312 operator+(UnitAlgebra lhs, const UnitAlgebra& rhs)
313 {
314  lhs += rhs;
315  return lhs;
316 }
317 
318 template <typename T>
319 UnitAlgebra
320 operator-(UnitAlgebra lhs, const T& rhs)
321 {
322  lhs -= rhs;
323  return lhs;
324 }
325 
326 inline UnitAlgebra
327 operator-(UnitAlgebra lhs, const UnitAlgebra& rhs)
328 {
329  lhs -= rhs;
330  return lhs;
331 }
332 
333 inline std::ostream&
334 operator<<(std::ostream& os, const UnitAlgebra& r)
335 {
336  os << r.toString();
337  return os;
338 }
339 
340 inline std::ostream&
341 operator<<(std::ostream& os, const Units& r)
342 {
343  os << r.toString();
344  return os;
345 }
346 
347 } // namespace SST
348 
349 #endif // SST_CORE_UNITALGEBRA_H
bool operator>(const UnitAlgebra &v) const
Compare if this object is greater than the argument.
Definition: unitAlgebra.cc:473
Units & operator*=(const Units &v)
Self-multiplication operator.
Definition: unitAlgebra.cc:246
UnitAlgebra & operator/=(const UnitAlgebra &v)
Divide by an argument;.
Definition: unitAlgebra.cc:435
This class is basically a wrapper for objects to declare the order in which their members should be s...
Definition: serializer.h:34
void print(std::ostream &stream)
Print to an ostream the value.
Definition: unitAlgebra.cc:378
std::string toString(int32_t precision=6) const
Create a string representation of this decimal_fixedpoint.
Definition: decimal_fixedpoint.h:439
bool operator==(const UnitAlgebra &v) const
Compare if this object is equal to, the argument.
Definition: unitAlgebra.cc:529
bool operator>=(const UnitAlgebra &v) const
Compare if this object is greater than, or equal to, the argument.
Definition: unitAlgebra.cc:487
std::string toString() const
Return a string representation of this value.
Definition: unitAlgebra.cc:390
int64_t getRoundedValue() const
Return the rounded value as a 64bit integer.
Definition: unitAlgebra.cc:562
UnitAlgebra & operator+=(const T &v)
Multiply by an argument;.
Definition: unitAlgebra.h:180
Units & operator=(const Units &v)
Assignment operator.
Definition: unitAlgebra.cc:238
static void registerBaseUnit(const std::string &u)
Create a new Base Unit type.
Definition: unitAlgebra.cc:185
std::string toStringBestSI() const
Return a string representation of this value Formats the number using SI-prefixes.
Definition: unitAlgebra.cc:398
bool operator==(const Units &lhs) const
Equality Operator.
Definition: unitAlgebra.cc:266
Definition: serializable.h:118
Units & invert()
Perform a reciprocal operation.
Definition: unitAlgebra.cc:280
sst_big_num getValue() const
Return the raw value.
Definition: unitAlgebra.h:216
UnitAlgebra & operator*=(const T &v)
Multiply by an argument;.
Definition: unitAlgebra.h:160
void printWithBestSI(std::ostream &stream)
Print to an ostream the value Formats the number using SI-prefixes.
Definition: unitAlgebra.cc:384
UnitAlgebra & operator-=(const T &v)
Divide by an argument;.
Definition: unitAlgebra.h:190
bool operator!=(const UnitAlgebra &v) const
Compare if this object is not equal to, the argument.
Definition: unitAlgebra.cc:536
UnitAlgebra & invert()
Apply a reciprocal operation to the object.
Definition: unitAlgebra.cc:543
std::string toString() const
Return a String representation if this Unit.
Definition: unitAlgebra.cc:289
UnitAlgebra & operator/=(const T &v)
Divide by an argument;.
Definition: unitAlgebra.h:170
UnitAlgebra & operator*=(const UnitAlgebra &v)
Multiply by an argument;.
Definition: unitAlgebra.cc:427
UnitAlgebra & operator+=(const UnitAlgebra &v)
Add an argument;.
Definition: unitAlgebra.cc:443
static void registerCompoundUnit(const std::string &u, const std::string &v)
Create a new Compound Unit type.
Definition: unitAlgebra.cc:196
UnitAlgebra & operator-=(const UnitAlgebra &v)
Subtract an argument;.
Definition: unitAlgebra.cc:458
bool hasUnits(const std::string &u) const
Returns true if the units in the parameter string are found in this object.
Definition: unitAlgebra.cc:552
bool operator<=(const UnitAlgebra &v) const
Compare if this object is less than, or equal to, the argument.
Definition: unitAlgebra.cc:515
bool operator!=(const Units &lhs) const
Inequality Operator.
Definition: unitAlgebra.h:92
Performs Unit math in full precision.
Definition: unitAlgebra.h:106
Units & operator/=(const Units &v)
Self-division operator.
Definition: unitAlgebra.cc:257
Helper class internal to UnitAlgebra.
Definition: unitAlgebra.h:38
bool operator<(const UnitAlgebra &v) const
Compare if this object is less than the argument.
Definition: unitAlgebra.cc:501
Definition: serializable.h:138