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

Distributed under the Apache License, Version 2.0.

See accompanying NOTICE file for details.