PScalar.h
1 /**************************************************************************************
2 Copyright 2015 Applied Research Associates, Inc.
3 Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 this file except in compliance with the License. You may obtain a copy of the License
5 at:
6 http://www.apache.org/licenses/LICENSE-2.0
7 Unless required by applicable law or agreed to in writing, software distributed under
8 the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
9 CONDITIONS OF ANY KIND, either express or implied. See the License for the
10 specific language governing permissions and limitations under the License.
11 **************************************************************************************/
12 
13 //----------------------------------------------------------------------------
22 //----------------------------------------------------------------------------
23 
24 #pragma once
25 #include <biogears/cdm/utils/unitconversion/UnitConversionEngine.h>
26 #include <biogears/cdm/utils/unitconversion/CompoundUnit.h>
27 
28 namespace biogears{
29 class BIOGEARS_API CPScalar {
30 public:
31  // Default ctor
33  : m_dValue(0.0)
34  {
35  // Do nothing
36  }
37 
38  // Construct from value and string unit spec
39  CPScalar(double val, const char* unitSpec);
40  // Construct from value and string unit spec
41  CPScalar(double val, const std::string& unitSpec);
42 
43  // Construct from value. No units.
44  explicit CPScalar(double val)
45  : m_dValue(val)
46  {
47  // Do nothing
48  }
49 
50  // Construct from string unit. Initial value is 1.0 so that we can multiply by a pure
51 // unit specification.
52  CPScalar(const char* unitSpec);
53  // Construct from string unit. Initial value is 1.0 so that we can multiply by a pure
54  // unit specification.
55  CPScalar(const std::string& unitSpec);
56 
57  // Copy ctor
58  CPScalar(const CPScalar& src)
59  : m_dValue(src.m_dValue)
60  , m_CCU(src.m_CCU)
61  {
62  // Do nothing
63  }
64 
65  // Overload arithmetic operators in the proper fashion.
67  {
68  if (this != &rhs) {
69  m_dValue = rhs.m_dValue;
70  m_CCU = rhs.m_CCU;
71  }
72  return *this;
73  }
74 
76  {
77  m_dValue *= rhs.m_dValue;
78  m_CCU *= rhs.m_CCU;
79  return *this;
80  }
81 
83  {
84  m_dValue /= rhs.m_dValue;
85  m_CCU /= rhs.m_CCU;
86  return *this;
87  }
88 
89  CPScalar operator*(const CPScalar& rhs) const
90  {
91  return CPScalar(*this) *= rhs;
92  }
93 
94  CPScalar operator/(const CPScalar& rhs) const
95  {
96  return CPScalar(*this) /= rhs;
97  }
98 
99  // Addition and subtraction require a little care. Adding values requires
100  // they be in the same units, so we will convert the right hand side operand
101  // to the units of the left hand side. We use the interval conversion function
102  // so that we don't get thrown off by biases in the conversion process
103 
105  {
107  double newVal = uce.ConvertValueInterval(rhs.m_dValue, rhs.m_CCU, m_CCU);
108  m_dValue += newVal;
109  return *this;
110  }
111 
113  {
115  double newVal = uce.ConvertValueInterval(rhs.m_dValue, rhs.m_CCU, m_CCU);
116  m_dValue -= newVal;
117  return *this;
118  }
119 
120  // Use ConvertValue here rather than ConvertValueInterval so that we can
121  // correctly determine that 0 degC == 32 degF
122  bool operator==(const CPScalar& rhs) const
123  {
125  double newVal = uce.ConvertValue(rhs.m_dValue, rhs.m_CCU, m_CCU);
126  return m_dValue == newVal;
127  }
128 
129  // We can implement this in terms of overloaded == because in case of type mismatch, NaN is
130  // returned by the conversion, which "==" will treat as false, and we want "!=" to
131  // yield true in that circumstance
132  bool operator!=(const CPScalar& rhs) const
133  {
134  return !(*this == rhs);
135  }
136 
137  // Instead of implementing < in terms of !(>=), and > in terms of !(<=) (or vice versa),
138  // we provide separate implementations for them all, because we don't want anything
139  // to return true in case of NaN (see above), since NAN is always supposed to have an
140  // unordered result.
141  bool operator<(const CPScalar& rhs) const
142  {
144  double newVal = uce.ConvertValue(rhs.m_dValue, rhs.m_CCU, m_CCU);
145  return m_dValue < newVal;
146  }
147 
148  bool operator>(const CPScalar& rhs) const
149  {
151  double newVal = uce.ConvertValue(rhs.m_dValue, rhs.m_CCU, m_CCU);
152  return m_dValue > newVal;
153  }
154 
155  bool operator<=(const CPScalar& rhs) const
156  {
158  double newVal = uce.ConvertValue(rhs.m_dValue, rhs.m_CCU, m_CCU);
159  return m_dValue <= newVal;
160  }
161 
162  bool operator>=(const CPScalar& rhs) const
163  {
165  double newVal = uce.ConvertValue(rhs.m_dValue, rhs.m_CCU, m_CCU);
166  return m_dValue >= newVal;
167  }
168 
169  CPScalar operator+(const CPScalar& rhs) const
170  {
171  return CPScalar(*this) += rhs;
172  }
173 
174  CPScalar operator-(const CPScalar& rhs) const
175  {
176  return CPScalar(*this) -= rhs;
177  }
178 
179  CPScalar operator+() const // unary +
180  {
181  return CPScalar(*this); // make a copy anyway!
182  }
183 
185  {
186  m_dValue *= -1.0;
187  return *this;
188  }
189 
190  CPScalar operator-() const // unary -
191  {
192  return CPScalar(*this).Negate();
193  }
194 
195  // conversion operators. Casting to the designated type invokes these functions.
196  operator bool() const
197  {
198  return m_dValue != 0.0;
199  }
200 
201  operator int() const
202  {
203  return static_cast<int>(static_cast<double>(*this));
204  }
205 
206  operator float() const
207  {
208  return static_cast<float>(static_cast<double>(*this));
209  }
210 
211  operator double() const
212  {
213  double newval;
215  static CCompoundUnit unitless(""); // dimensionless unitless CompoundUnit
216  if (*unitless.GetDimension() == *m_CCU.GetDimension()) {
217  // We are dimensionless, but we potentially have a scale factor
218  // due to quantity-type cancellation, such as knots/mph. So
219  // convert to *unitless* to incorporate that bigness difference
220  // into the value.
221 
222  newval = uce.ConvertValue(m_dValue, m_CCU, unitless);
223  } else {
224  throw "PScalar value can't be cast to numeric unless already dimensionless!";
225  }
226  return newval;
227  }
228 
229  double GetValue() const
230  {
231  return m_dValue;
232  }
233 
234  // Function call operator! Overload to take a string unit spec and return a new
235  // value equal to the conversion of the current instance to the specified unit.
236  // Usage: myPScalar("newUnit").
237  // This creates a new CPScalar value and does not change the state of the object
238  // upon which it is invoked (unlike the method it calls: ConvertTo)
239  CPScalar operator()(const std::string& unitSpec) const
240  {
241  return CPScalar(*this).ConvertTo(unitSpec);
242  }
243 
244  // Raise myself to a given power
245  // Return reference to self so it can be applied to the temporary created
246  // in implementation of pow(). Same thing below for SQRoot() and sqrt()
247  CPScalar& Raise(double pwr)
248  {
249  m_dValue = std::pow(m_dValue, pwr);
250  m_CCU.Raise(pwr);
251  return *this;
252  }
253 
254  // Compute square root of myself
255  // This method modifies the current object
257  {
258  // Rather than just invoking Raise(0.5) on ourselves, use sqrt(double) on the
259  // value so that we can take advantage of intrinsic implementations on the X86
260  m_dValue = std::sqrt(m_dValue);
261  m_CCU.Raise(0.5);
262  return *this;
263  }
264 
265  // Compute absolute value of myself
266  // This method modified the current object
268  {
269  m_dValue = std::abs(m_dValue);
270  return *this;
271  }
272 
273  // Convert this object to a new set of units
274  CPScalar& ConvertTo(const char* unitSpec);
275  // Convert this object to a new set of units
276  CPScalar& ConvertTo(const std::string& unitSpec);
277 
278  // Convert this object to a new set of units
280  {
282  double newval = uce.ConvertValue(m_dValue, m_CCU, newUnit);
283  m_CCU = newUnit;
284  m_dValue = newval;
285  return *this;
286  }
287 
288  // Convert this object to the units of another object
289  CPScalar& ConvertTo(const CPScalar& target)
290  {
291  return ConvertTo(target.m_CCU);
292  }
293 
294  std::ostream& PrintSelf(std::ostream& output) const
295  {
296  return output << m_dValue << " " << m_CCU;
297  }
298 
299  bool IsSameType(const CPScalar& target) const
300  {
301  return (*m_CCU.GetDimension() == *target.m_CCU.GetDimension());
302  }
303 
304  bool IsDimensionless() const
305  {
306  return m_CCU.IsDimensionless();
307  }
308 
309  // Is this CompoundUnit in "decibel" mode
310  bool IsDecible() const
311  {
312  return m_CCU.IsDecibel();
313  }
314 
315  template <class T>
316  friend CPScalar& operator*=(CPScalar& lhs, const T& rhs);
317  template <class T>
318  friend CPScalar& operator/=(CPScalar& lhs, const T& rhs);
319 
320 private:
321  double m_dValue;
323 };
324 
325 inline CPScalar pow(const CPScalar& baseref, double pwr)
326 {
327  return (CPScalar(baseref)).Raise(pwr);
328 }
329 
330 inline CPScalar pow(const CPScalar& baseref, int pwr)
331 {
332  return (CPScalar(baseref)).Raise(static_cast<double>(pwr));
333 }
334 
335 inline CPScalar sqrt(const CPScalar& argref)
336 {
337  return (CPScalar(argref)).SQRoot();
338 }
339 
340 inline CPScalar abs(const CPScalar& argref)
341 {
342  return (CPScalar(argref)).Abs();
343 }
344 
345 inline std::ostream& operator<<(std::ostream& output, const CPScalar& self)
346 {
347  return self.PrintSelf(output);
348 }
349 
350 // Due to the fact that we have casts to double, etc defined, we can't
351 // rely on the CPScalar(double) constructor to promote non-CPScalar
352 // operands, since the conversion in the other direction is just as
353 // valid, according to the compiler, and therefore ambiguous.
354 // In these templates, "T" can be bool, int, float, double
355 // Each operator has two signatures, one in which the CPScalar
356 // value comes first, and one in which it comes second. In each case,
357 // we construct a CPScalar out of the templated arg and add it to the
358 // existing CPScalar object using the overloaded *member* form of the
359 // operator.
360 // Note that the assignment versions return a reference to the LHS operand
361 
362 // Multiply
363 template <class T>
364 CPScalar operator*(const CPScalar& lhs, const T& rhs)
365 {
366  return lhs * CPScalar(rhs);
367 }
368 
369 template <class T>
370 CPScalar operator*(const T& lhs, const CPScalar& rhs)
371 {
372  return CPScalar(lhs) * rhs;
373 }
374 
375 template <class T>
376 CPScalar& operator*=(CPScalar& lhs, const T& rhs)
377 {
378  lhs.m_dValue *= rhs;
379  return lhs;
380 }
381 
382 // Divide
383 template <class T>
384 CPScalar operator/(const CPScalar& lhs, const T& rhs)
385 {
386  return lhs / CPScalar(rhs);
387 }
388 
389 template <class T>
390 CPScalar operator/(const T& lhs, const CPScalar& rhs)
391 {
392  return CPScalar(lhs) / rhs;
393 }
394 
395 template <class T>
396 CPScalar& operator/=(CPScalar& lhs, const T& rhs)
397 {
398  lhs.m_dValue /= rhs;
399  return lhs;
400 }
401 
402 // Add
403 template <class T>
404 CPScalar operator+(const CPScalar& lhs, const T& rhs)
405 {
406  return lhs + CPScalar(rhs);
407 }
408 
409 template <class T>
410 CPScalar operator+(const T& lhs, const CPScalar& rhs)
411 {
412  return CPScalar(lhs) + rhs;
413 }
414 
415 // Subtract
416 template <class T>
417 CPScalar operator-(const CPScalar& lhs, const T& rhs)
418 {
419  return lhs - CPScalar(rhs);
420 }
421 
422 template <class T>
423 CPScalar operator-(const T& lhs, const CPScalar& rhs)
424 {
425  return CPScalar(lhs) - rhs;
426 }
427 
428 // Less than
429 template <class T>
430 bool operator<(const CPScalar& lhs, const T& rhs)
431 {
432  return lhs < CPScalar(rhs);
433 }
434 
435 template <class T>
436 bool operator<(const T& lhs, const CPScalar& rhs)
437 {
438  return CPScalar(lhs) < rhs;
439 }
440 
441 // Less than or equal to
442 template <class T>
443 bool operator<=(const CPScalar& lhs, const T& rhs)
444 {
445  return lhs <= CPScalar(rhs);
446 }
447 
448 template <class T>
449 bool operator<=(const T& lhs, const CPScalar& rhs)
450 {
451  return CPScalar(lhs) <= rhs;
452 }
453 
454 // Greater than
455 template <class T>
456 bool operator>(const CPScalar& lhs, const T& rhs)
457 {
458  return lhs > CPScalar(rhs);
459 }
460 
461 template <class T>
462 bool operator>(const T& lhs, const CPScalar& rhs)
463 {
464  return CPScalar(lhs) > rhs;
465 }
466 
467 // Greater than or equal to
468 template <class T>
469 bool operator>=(const CPScalar& lhs, const T& rhs)
470 {
471  return lhs >= CPScalar(rhs);
472 }
473 
474 template <class T>
475 bool operator>=(const T& lhs, const CPScalar& rhs)
476 {
477  return CPScalar(lhs) >= rhs;
478 }
479 
480 // Equal
481 template <class T>
482 bool operator==(const CPScalar& lhs, const T& rhs)
483 {
484  return lhs == CPScalar(rhs);
485 }
486 
487 template <class T>
488 bool operator==(const T& lhs, const CPScalar& rhs)
489 {
490  return CPScalar(lhs) == rhs;
491 }
492 
493 // Not equal
494 template <class T>
495 bool operator!=(const CPScalar& lhs, const T& rhs)
496 {
497  return lhs != CPScalar(rhs);
498 }
499 
500 template <class T>
501 bool operator!=(const T& lhs, const CPScalar& rhs)
502 {
503  return CPScalar(lhs) != rhs;
504 }
505 }
bool operator>=(double lhs, const SEScalar &rhs)
Definition: SEScalar.h:127
bool operator<=(double lhs, const SEScalar &rhs)
Definition: SEScalar.h:125
std::ostream & PrintSelf(std::ostream &output) const
Definition: PScalar.h:294
bool operator>=(const CPScalar &rhs) const
Definition: PScalar.h:162
CPScalar operator-(const CPScalar &rhs) const
Definition: PScalar.h:174
static CUnitConversionEngine & GetEngine(void)
Definition: UnitConversionEngine.cpp:97
CPScalar operator+(const CPScalar &rhs) const
Definition: PScalar.h:169
CCompoundUnit pow(const CCompoundUnit &baseref, CCompoundUnitElement::ExponentType exp)
Definition: CompoundUnit.h:269
CPScalar & SQRoot()
Definition: PScalar.h:256
CPScalar & operator=(const CPScalar &rhs)
Definition: PScalar.h:66
CPScalar(const CPScalar &src)
Definition: PScalar.h:58
CPScalar & ConvertTo(const CPScalar &target)
Definition: PScalar.h:289
SEScalar operator+(double lhs, const SEScalar &rhs)
Definition: SEScalar.h:120
CPScalar & ConvertTo(const CCompoundUnit &newUnit)
Definition: PScalar.h:279
double m_dValue
Definition: PScalar.h:321
bool operator!=(const CPScalar &rhs) const
Definition: PScalar.h:132
CPScalar & ConvertTo(const char *unitSpec)
Definition: PScalar.cpp:77
CPScalar & Abs()
Definition: PScalar.h:267
const CUnitDimension * GetDimension() const
Definition: CompoundUnit.cpp:281
CPScalar & operator*=(CPScalar &lhs, const T &rhs)
Definition: PScalar.h:376
CPScalar & operator+=(const CPScalar &rhs)
Definition: PScalar.h:104
bool IsDimensionless() const
Definition: PScalar.h:304
bool operator!=(double lhs, const SEScalar &rhs)
Definition: SEScalar.h:129
CPScalar(double val)
Definition: PScalar.h:44
double ConvertValueInterval(const double &value, const CCompoundUnit &fromUnit, const CCompoundUnit &toUnit) const
Definition: UnitConversionEngine.cpp:469
SEScalar operator/(double lhs, const SEScalar &rhs)
Definition: SEScalar.h:122
Definition: CompoundUnit.h:59
SEScalar operator*(double lhs, const SEScalar &rhs)
Definition: SEScalar.h:123
std::ostream & operator<<(std::ostream &out, const SEConsciousRespirationCommand &c)
Definition: SEConsciousRespirationCommand.h:48
CCompoundUnit & Raise(CCompoundUnitElement::ExponentType)
Definition: CompoundUnit.cpp:599
const std::string unitless
Definition: SEScalar.cpp:30
CPScalar & operator/=(const CPScalar &rhs)
Definition: PScalar.h:82
CPScalar abs(const CPScalar &argref)
Definition: PScalar.h:340
CPScalar operator/(const CPScalar &rhs) const
Definition: PScalar.h:94
Definition: PScalar.h:29
CCompoundUnit m_CCU
Definition: PScalar.h:322
CPScalar operator()(const std::string &unitSpec) const
Definition: PScalar.h:239
bool operator==(double lhs, const SEScalar &rhs)
Definition: SEScalar.h:128
bool IsSameType(const CPScalar &target) const
Definition: PScalar.h:299
bool operator>(double lhs, const SEScalar &rhs)
Definition: SEScalar.h:126
bool operator<(const CPScalar &rhs) const
Definition: PScalar.h:141
CPScalar & operator-=(const CPScalar &rhs)
Definition: PScalar.h:112
CPScalar operator+() const
Definition: PScalar.h:179
bool operator<=(const CPScalar &rhs) const
Definition: PScalar.h:155
bool operator<(double lhs, const SEScalar &rhs)
Definition: SEScalar.h:124
double GetValue() const
Definition: PScalar.h:229
Definition: UnitConversionEngine.h:36
bool IsDecible() const
Definition: PScalar.h:310
CPScalar & operator/=(CPScalar &lhs, const T &rhs)
Definition: PScalar.h:396
SEScalar operator-(double lhs, const SEScalar &rhs)
Definition: SEScalar.h:121
CPScalar()
Definition: PScalar.h:32
CPScalar & Raise(double pwr)
Definition: PScalar.h:247
CPScalar & operator*=(const CPScalar &rhs)
Definition: PScalar.h:75
CCompoundUnit sqrt(const CCompoundUnit &argref)
Definition: CompoundUnit.h:280
double ConvertValue(const double &value, const CCompoundUnit &fromUnit, const CCompoundUnit &toUnit) const
Definition: UnitConversionEngine.cpp:369
Definition: SEElectricalCircuit.h:18
CPScalar operator*(const CPScalar &rhs) const
Definition: PScalar.h:89
CPScalar & Negate(void)
Definition: PScalar.h:184
bool operator>(const CPScalar &rhs) const
Definition: PScalar.h:148
CPScalar operator-() const
Definition: PScalar.h:190
bool operator==(const CPScalar &rhs) const
Definition: PScalar.h:122