OnixS CME Drop Copy Handler C++ library  5.6.0
API documentation
Numeric.h
Go to the documentation of this file.
1 // Copyright Onix Solutions Limited [OnixS]. All rights reserved.
2 //
3 // This software owned by Onix Solutions Limited [OnixS] and is protected by copyright law
4 // and international copyright treaties.
5 //
6 // Access to and use of the software is governed by the terms of the applicable OnixS Software
7 // Services Agreement (the Agreement) and Customer end user license agreements granting
8 // a non-assignable, non-transferable and non-exclusive license to use the software
9 // for it's own data processing purposes under the terms defined in the Agreement.
10 //
11 // Except as otherwise granted within the terms of the Agreement, copying or reproduction of any part
12 // of this source code or associated reference material to any other location for further reproduction
13 // or redistribution, and any amendments to this copyright notice, are expressly prohibited.
14 //
15 // Any reproduction or redistribution for sale or hiring of the Software not in accordance with
16 // the terms of the Agreement is a violation of copyright law.
17 //
18 
19 #pragma once
20 
21 #include "OnixS/CME/DropCopy/Export.h"
22 
23 #include <cassert>
24 #include <cmath>
25 #include <ostream>
26 #include <string>
27 #include <stdexcept>
28 
29 namespace OnixS { namespace CME { namespace DropCopy {
30 
31 typedef int Int32;
32 typedef unsigned int UInt32;
33 
34 typedef long long Int64;
35 typedef unsigned long long UInt64;
36 
37 typedef double Double;
38 
39 typedef Int64 DecimalMantissa;
40 typedef Int32 DecimalExponent;
41 
42 /// Decimal type for better precision.
43 class ONIXS_CME_DROP_COPY_EXPORT Decimal
44 {
45 public:
46  /// Initializes instance from compound components.
47  Decimal (DecimalMantissa mantissa = 0, DecimalExponent exponent = 0);
48 
49  /// Converts Double value to decimal.
50  /// \param value double precision floating-point value.
51  /// \param precision defines conversion precision.
52  Decimal (Double value, size_t precision);
53 
54  /// Initializes as copy of given value.
55  Decimal (const Decimal& other);
56 
57  /// Returns mantissa part of decimal.
58  DecimalMantissa mantissa() const;
59 
60  /// Updates mantissa part of decimal.
61  void mantissa (DecimalMantissa);
62 
63  /// Returns exponent part of decimal.
64  DecimalExponent exponent() const;
65 
66  /// Updates exponent part of decimal.
67  void exponent (DecimalExponent);
68 
69  /// Compares two numbers.
70  bool operator == (const Decimal&) const;
71 
72  /// Compares two numbers.
73  bool operator != (const Decimal&) const;
74 
75  /// Establishes order between two values.
76  bool operator <(const Decimal&) const;
77 
78  /// Establishes order between two values.
79  bool operator >(const Decimal&) const;
80 
81  /// Casts to whole integer number as regular
82  /// floating point value is casted.
83  /// \throw domain_error exception on failure.
84  operator Int32() const;
85 
86  /// Casts to whole integer number as regular
87  /// floating point value is casted.
88  /// \throw domain_error exception on failure.
89  operator UInt32() const;
90 
91  /// Casts to whole integer number as regular
92  /// floating point value is casted.
93  /// \throw domain_error exception on failure.
94  operator Int64() const;
95 
96  /// Casts to whole integer number as regular
97  /// floating point value is casted.
98  /// \throw domain_error exception on failure.
99  operator UInt64() const;
100 
101  /// Casts to whole floating point as regular
102  /// value is casted to a smaller precision.
103  /// \throw domain_error exception on failure.
104  operator Double() const;
105 
106  /// Casts to whole integer number as regular
107  /// floating point value is casted.
108  /// \return false if conversion fails.
109  bool toNumber (Int32&) const;
110 
111  /// Casts to whole integer number as regular
112  /// floating point value is casted.
113  /// \return false if conversion fails.
114  bool toNumber (UInt32&) const;
115 
116  /// Casts to whole integer number as regular
117  /// floating point value is casted.
118  /// \return false if conversion fails.
119  bool toNumber (Int64&) const;
120 
121  /// Casts to whole integer number as regular
122  /// floating point value is casted.
123  /// \return false if conversion fails.
124  bool toNumber (UInt64&) const;
125 
126  /// Casts to double floating point number.
127  /// \return false if conversion fails.
128  bool toNumber (Double&) const;
129 
130  /// Fast cast to double floating point number.
131  /// \note For the sake of performance no range checks are done.
132  /// Result may be invalid if decimal cannot be represented as double value.
133  /// Warning: result may be different (less precise) from toNumber(Double&)
134  /// result due to performance vs precision trade-off.
135  Double toDoubleUnchecked() const;
136 
137  /// Fast cast from double floating point number.
138  /// \note For the sake of performance no range checks are done.
139  /// Result may be invalid if decimal cannot be represented as double value.
140  /// Warning: result may be different (less precise) from Decimal(Double, size_t)
141  /// result due to performance vs precision trade-off.
142  static Decimal fromDoubleUnchecked(Double value, size_t precision);
143 
144  /// Appends text presentation to given string.
145  void toString(std::string&) const;
146 
147  /// Returns text presentation of decimal.
148  std::string toString() const;
149 
150  /// Reinitializes instance from another one.
151  Decimal& operator=(const Decimal& other);
152 
153  /// Attempts to parse decimal value
154  /// from its string/text presentation.
155  /// \return false on parsing failure.
156  static bool tryParse(const char* buffer, size_t bufferSize, Decimal&);
157 
158  /// Parses decimal from string presentation.
159  /// \throw std::exception on failure.
160  static Decimal parse(const char* buffer, size_t bufferSize);
161 
162 private:
163  /// Mantissa.
164  DecimalMantissa mantissa_;
165 
166  /// Exponent.
167  DecimalExponent exponent_;
168 };
169 
170 inline Decimal::Decimal(DecimalMantissa mantissa, DecimalExponent exponent)
171  : mantissa_(mantissa)
172  , exponent_(exponent)
173 {
174 }
175 
176 inline Decimal::Decimal(const Decimal& other)
177  : mantissa_(other.mantissa_)
178  , exponent_(other.exponent_)
179 {
180 }
181 
182 inline DecimalMantissa Decimal::mantissa() const
183 {
184  return mantissa_;
185 }
186 
187 inline void Decimal::mantissa(DecimalMantissa value)
188 {
189  mantissa_ = value;
190 }
191 
192 inline DecimalExponent Decimal::exponent() const
193 {
194  return exponent_;
195 }
196 
197 inline void Decimal::exponent(DecimalExponent value)
198 {
199  exponent_ = value;
200 }
201 
202 inline Decimal& Decimal::operator=(const Decimal& other)
203 {
204  mantissa_ = other.mantissa_;
205  exponent_ = other.exponent_;
206 
207  return *this;
208 }
209 
210 inline Decimal::operator Int32() const
211 {
212  Int32 number;
213 
214  if (toNumber(number))
215  return number;
216 
217  throw std::domain_error("Cannot cast value to target type. ");
218 }
219 
220 inline Decimal::operator UInt32() const
221 {
222  UInt32 number;
223 
224  if (toNumber(number))
225  return number;
226 
227  throw std::domain_error("Cannot cast value to target type. ");
228 }
229 
230 inline Decimal::operator Int64() const
231 {
232  Int64 number;
233 
234  if (toNumber(number))
235  return number;
236 
237  throw std::domain_error("Cannot cast value to target type. ");
238 }
239 
240 inline Decimal::operator UInt64() const
241 {
242  UInt64 number;
243 
244  if (toNumber(number))
245  return number;
246 
247  throw std::domain_error("Cannot cast value to target type. ");
248 }
249 
250 inline Decimal::operator Double() const
251 {
252  Double number;
253 
254  if (toNumber (number))
255  return number;
256 
257  throw std::domain_error("Cannot cast value to target type. ");
258 }
259 
260 inline std::string Decimal::toString() const
261 {
262  std::string presentation;
263  toString (presentation);
264  return presentation;
265 }
266 
267 namespace NumericDetails {
268 static const int maxAbsPower10 = 20;
269 static const int powers10Size = maxAbsPower10 * 2 + 1; // Negative, positive and zero powers
270 
271 static const double powers10[] =
272 {
273  1E-20, 1E-19, 1E-18, 1E-17, 1E-16, 1E-15, 1E-14, 1E-13, 1E-12, 1E-11,
274  1E-10, 1E-9, 1E-8, 1E-7, 1E-6, 1E-5, 1E-4, 1E-3, 1E-2, 1E-1,
275  1E0,
276  1E1, 1E2, 1E3, 1E4, 1E5, 1E6, 1E7, 1E8, 1E9, 1E10,
277  1E11, 1E12, 1E13, 1E14, 1E15, 1E16, 1E17, 1E18, 1E19, 1E20
278 };
279 
281 {
282  const int offset = power + maxAbsPower10;
283  if(offset >= 0 && offset < powers10Size)
284  {
285  return powers10[offset];
286  }
287 
288  throw std::invalid_argument("Invalid power argument, must be in range [-20, 20]");
289 }
290 }
291 
292 inline Double Decimal::toDoubleUnchecked() const
293 {
294  using namespace NumericDetails;
295  return mantissa_ * fastPower10(exponent_);
296 }
297 
298 inline Decimal Decimal::fromDoubleUnchecked(Double value, size_t precision)
299 {
300  using namespace NumericDetails;
301  DecimalExponent convertedExponent = 0;
302 
303  Double dummy;
304  if(fabs(modf(value, &dummy)) != 0.0)
305  {
306  const DecimalExponent exp = static_cast<DecimalExponent>(precision);
307 
308  // Apply last digit rounding
309  const Double rounding = 0.5 * fastPower10(-exp);
310  value += (value > 0) ? rounding : -rounding;
311 
312  value *= fastPower10(exp);
313  convertedExponent = -exp;
314  }
315 
316  return Decimal(static_cast<DecimalMantissa>(value), convertedExponent);
317 }
318 
319 /// Helper class for conversion from string to number.
320 struct ONIXS_CME_DROP_COPY_EXPORT Number
321 {
322  static bool tryParse(const char* buffer, size_t bufferSize, Int32& number);
323  static bool tryParse(const char* buffer, size_t bufferSize, UInt32& number);
324  static bool tryParse(const char* buffer, size_t bufferSize, Int64& number);
325  static bool tryParse(const char* buffer, size_t bufferSize, UInt64& number);
326  static bool tryParse(const char* buffer, size_t bufferSize, Double& number);
327  static bool tryParse(const char* buffer, size_t bufferSize, Decimal& number);
328 };
329 
330 /// Comparator aggregate providing compare functions.
331 /// Such functions can be generic (slower, but able to deal
332 /// with any decimal) or fixed point based (faster, but assuming that
333 /// all compating values have the same exponent).
334 struct ONIXS_CME_DROP_COPY_EXPORT DecimalComparator
335 {
336  /// Comparing function signature.
337  typedef bool(*CompareFunction)(const Decimal&, const Decimal&);
338 
339  /// Comparing functions.
340  const CompareFunction equal;
341  const CompareFunction nonEqual;
342  const CompareFunction less;
343  const CompareFunction greater;
344 
345  /// Constructor.
347  const CompareFunction equalFunc
348  , const CompareFunction nonEqualFunc
349  , const CompareFunction lessFunc
350  , const CompareFunction greaterFunc
351  )
352  : equal(equalFunc)
353  , nonEqual(nonEqualFunc)
354  , less(lessFunc)
355  , greater(greaterFunc)
356  {}
357 
358  // Assignment operator: not defined.
360 
361  /// Returns true if this instance is fixed point decimal comparator.
362  bool fixedPoint() const;
363 
364  /// Returns true if this instance is generic decimal comparator.
365  bool genericDecimal() const;
366 };
367 
368 /// Helper functions for generic decimal case.
369 namespace GenericDecimal {
370 inline bool equal(const Decimal& lhs, const Decimal& rhs)
371 {
372  return lhs == rhs;
373 }
374 
375 inline bool nonEqual(const Decimal& lhs, const Decimal& rhs)
376 {
377  return lhs != rhs;
378 }
379 
380 inline bool less(const Decimal& lhs, const Decimal& rhs)
381 {
382  return lhs < rhs;
383 }
384 
385 inline bool greater(const Decimal& lhs, const Decimal& rhs)
386 {
387  return lhs > rhs;
388 }
389 
390 ONIXS_CME_DROP_COPY_EXPORT extern const DecimalComparator Comparator;
391 }
392 
393 /// Helper functions for CME fixed point decimal case.
394 namespace FixedPointDecimal {
395 inline bool equal(const Decimal& lhs, const Decimal& rhs)
396 {
397  assert(lhs.exponent() == rhs.exponent());
398  return lhs.mantissa() == rhs.mantissa();
399 }
400 
401 inline bool nonEqual(const Decimal& lhs, const Decimal& rhs)
402 {
403  assert(lhs.exponent() == rhs.exponent());
404  return lhs.mantissa() != rhs.mantissa();
405 }
406 
407 inline bool less(const Decimal& lhs, const Decimal& rhs)
408 {
409  assert(lhs.exponent() == rhs.exponent());
410  return lhs.mantissa() < rhs.mantissa();
411 }
412 
413 inline bool greater(const Decimal& lhs, const Decimal& rhs)
414 {
415  assert(lhs.exponent() == rhs.exponent());
416  return lhs.mantissa() > rhs.mantissa();
417 }
418 
419 ONIXS_CME_DROP_COPY_EXPORT extern const DecimalComparator Comparator;
420 }
421 
422 inline bool DecimalComparator::fixedPoint() const
423 {
424  return this == &FixedPointDecimal::Comparator;
425 }
426 
428 {
429  return this == &GenericDecimal::Comparator;
430 }
431 
432 static const DecimalComparator& defaultDecimalComparator = GenericDecimal::Comparator;
433 
434 }}}
435 
436 namespace std {
437 
438 // Outputs decimal into standard stream.
439 ONIXS_CME_DROP_COPY_EXPORT std::ostream& operator<<(std::ostream&, const OnixS::CME::DropCopy::Decimal&);
440 
441 }
const CompareFunction greater
Definition: Numeric.h:343
Double toDoubleUnchecked() const
Definition: Numeric.h:292
static bool tryParse(const char *buffer, size_t bufferSize, Decimal &)
DecimalComparator(const CompareFunction equalFunc, const CompareFunction nonEqualFunc, const CompareFunction lessFunc, const CompareFunction greaterFunc)
Constructor.
Definition: Numeric.h:346
bool nonEqual(const Decimal &lhs, const Decimal &rhs)
Definition: Numeric.h:401
long long Int64
Definition: Numeric.h:34
Decimal & operator=(const Decimal &other)
Reinitializes instance from another one.
Definition: Numeric.h:202
bool greater(const Decimal &lhs, const Decimal &rhs)
Definition: Numeric.h:413
bool operator==(const FieldValueRef &ref, const std::string &str)
Definition: Messaging.h:187
STL namespace.
DecimalMantissa mantissa() const
Returns mantissa part of decimal.
Definition: Numeric.h:182
bool operator!=(const FieldValueRef &ref, const std::string &str)
Definition: Messaging.h:192
unsigned long long UInt64
Definition: Numeric.h:35
OnixS::CME::DropCopy::Double fastPower10(int power)
Definition: Numeric.h:280
bool fixedPoint() const
Returns true if this instance is fixed point decimal comparator.
Definition: Numeric.h:422
const DecimalComparator Comparator
const CompareFunction equal
Comparing functions.
Definition: Numeric.h:340
Helper class for conversion from string to number.
Definition: Numeric.h:320
bool toNumber(Int32 &) const
static Decimal fromDoubleUnchecked(Double value, size_t precision)
Definition: Numeric.h:298
std::string toString() const
Returns text presentation of decimal.
Definition: Numeric.h:260
DecimalExponent exponent() const
Returns exponent part of decimal.
Definition: Numeric.h:192
bool equal(const Decimal &lhs, const Decimal &rhs)
Definition: Numeric.h:395
unsigned int UInt32
Definition: Numeric.h:32
const CompareFunction nonEqual
Definition: Numeric.h:341
const DecimalComparator Comparator
Int32 DecimalExponent
Definition: Numeric.h:40
Decimal type for better precision.
Definition: Numeric.h:43
bool less(const Decimal &lhs, const Decimal &rhs)
Definition: Numeric.h:407
Decimal(DecimalMantissa mantissa=0, DecimalExponent exponent=0)
Initializes instance from compound components.
Definition: Numeric.h:170
Int64 DecimalMantissa
Definition: Numeric.h:39
bool genericDecimal() const
Returns true if this instance is generic decimal comparator.
Definition: Numeric.h:427