OnixS C++ CME iLink 3 Binary Order Entry Handler  1.18.0
API Documentation
Decimal.Operations.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
4 // protected by copyright law and international copyright treaties.
5 //
6 // Access to and use of the software is governed by the terms of the applicable
7 // OnixS Software Services Agreement (the Agreement) and Customer end user license
8 // agreements granting a non-assignable, non-transferable and non-exclusive license
9 // to use the software for it's own data processing purposes under the terms defined
10 // in the Agreement.
11 //
12 // Except as otherwise granted within the terms of the Agreement, copying or
13 // reproduction of any part of this source code or associated reference material
14 // to any other location for further reproduction or redistribution, and any
15 // amendments to this copyright notice, are expressly prohibited.
16 //
17 // Any reproduction or redistribution for sale or hiring of the Software not in
18 // accordance with the terms of the Agreement is a violation of copyright law.
19 //
20 
21 #pragma once
22 
23 #include <OnixS/CME/iLink3/ABI.h>
24 
27 
29 
30 /// \private
34 void throwCannotQuantizeOrConvert();
35 
36 /// Universal decimal type.
38 //
39 
40 /// \private
42 inline bool isNull(const Decimal&) ONIXS_ILINK3_NOTHROW
43 {
44  return false;
45 }
46 
47 /// Quantize so its exponent is the same as that of provided value.
48 ///
49 /// \return `false` if the value cannot be quantized.
51 bool
52 quantize(
53  const Decimal& operand,
54  Int32 exponent,
55  Decimal& quantized);
56 
57 /// Quantize so its exponent is the same as that of provided value.
58 ///
59 /// \throw std::exception if the value cannot be quantized.
60 ///
61 /// \return resulting decimal.
65 Decimal quantize(const Decimal& operand, Int32 exponent);
66 
67 /// Quantize so its exponent is the same as that of provided value.
68 ///
69 /// \throw std::exception if the value cannot be quantized
70 ///
71 /// \return resulting decimal mantissa
72 template <class MantissaType>
74 MantissaType quantizedMantissa(const Decimal& operand, Int32 exponent)
75 {
76  const Decimal::Mantissa res =
77  quantize(
78  operand, exponent)
79  .mantissa();
80 
81  if(static_cast<MantissaType>(
82  (std::numeric_limits<MantissaType>::max)()) >= res)
83  {
84  return static_cast<MantissaType>(res);
85  }
86 
87  throwCannotQuantizeOrConvert();
88 }
89 
90 template
91 <
92  class MantissaType,
93  class ExponentType
94 >
95 void convert(
97  const Decimal& number)
98 {
99  res =
101  quantizedMantissa<MantissaType>(number, ExponentType()));
102 }
103 
104 template
105  <
106  class MantissaType,
107  class ExponentType
108  >
109 void convert(
111  const Decimal& number)
112 {
113  if(static_cast<MantissaType>(
114  (std::numeric_limits<MantissaType>::max)()) < number.mantissa())
115  {
116  throwCannotQuantizeOrConvert();
117  }
118 
119  res =
121  static_cast<MantissaType>(number.mantissa()),
122  number.exponent());
123 }
124 
125 /// Convert the decimal in to a different one.
126 ///
127 /// \throw std::exception if the value cannot be converted
128 ///
129 /// \return resulting decimal
130 template
131 <
132  class DecimalT
133 >
136 typename EnableIf<details::IsDecimal<DecimalT>::value, DecimalT>::type
137  convert(const Decimal& number)
138 {
139  DecimalT res;
140  convert(res, number);
141  return res;
142 }
143 
144 /// \private
147 bool decimalEqual(
148  const Decimal& left, const Decimal& right) ONIXS_ILINK3_NOTHROW;
149 
150 /// \private
151 inline bool operator ==(const Decimal& left, const Decimal& right) ONIXS_ILINK3_NOTHROW
152 {
153  return ((left.exponent() == right.exponent()) ? (left.mantissa() == right.mantissa()) : decimalEqual(left, right));
154 }
155 
156 /// \private
157 inline bool operator!=(
158  const Decimal& left, const Decimal& right)
159 {
160  return ((left.exponent() == right.exponent()) ? (left.mantissa() != right.mantissa()) : !decimalEqual(left, right));
161 }
162 
163 /// \private
166 bool decimalLess(
167  const Decimal& left, const Decimal& right) ONIXS_ILINK3_NOTHROW;
168 
169 /// \private
170 inline bool operator <(
171  const Decimal& left, const Decimal& right) ONIXS_ILINK3_NOTHROW
172 {
173  return ((left.exponent() == right.exponent()) ? (left.mantissa() < right.mantissa()) : decimalLess(left, right));
174 }
175 
176 /// \private
177 inline bool operator<=(
178  const Decimal& left, const Decimal& right)
179 {
180  return !(right < left);
181 }
182 
183 /// \private
184 inline
186 bool
187 operator >(
188  const Decimal& left,
189  const Decimal& right)
190 {
191  return (right < left);
192 }
193 
194 /// \private
195 inline
197 bool
199  const Decimal& left,
200  const Decimal& right)
201 {
202  return (right <= left);
203 }
204 
205 /// \private.
207 void
208 decimalToStr(
209  std::string&,
210  Int64,
211  Int32);
212 
213 /// \private.
215 size_t
216 toStr(
217  const Decimal&,
218  Char* buf,
219  size_t size);
220 
221 /// Deserializes a decimal number
222 /// from the given text presentation.
224 bool
225 fromStr(
226  Decimal&,
227  const Char*,
228  size_t) ONIXS_ILINK3_NOTHROW;
229 
230 
231 /// Deserializes a decimal number
232 /// from the given text presentation.
233 inline
234 bool
236  Decimal& value,
237  const std::string& str) ONIXS_ILINK3_NOTHROW
238 {
239  return
240  fromStr(
241  value,
242  str.c_str(),
243  str.size());
244 }
245 
246 /// \private
247 inline
248 void
249 toStr(
250  std::string& str,
251  const Decimal& number)
252 {
253  decimalToStr
254  (
255  str,
256  number.mantissa(),
257  number.exponent()
258  );
259 }
260 
261 /// Serializes floating-point decimal into a string.
262 template
263 <
264  class Mantissa,
265  class Exponent
266 >
267 inline
268 void
270  std::string& str,
271  const
273  <Mantissa, Exponent>& number)
274 {
275  if(isNull(number))
276  {
277  str += "[]";
278  return;
279  }
280 
281  toStr(str, Decimal(number));
282 }
283 
284 /// Serializes into a stream.
285 template
286 <
287  class Mantissa,
288  class Exponent
289 >
290 inline
291 std::ostream&
293  std::ostream& stream,
294  const
296  <Mantissa, Exponent>& value)
297 {
298  std::string str;
299 
300  toStr(str, value);
301 
302  return stream << str;
303 }
304 
305 /// Serializes a fixed-point decimal into a string.
306 template
307 <
308  class Mantissa,
309  class Exponent
310 >
311 inline
312 void
314  std::string& str,
315  const
317  <Mantissa, Exponent>& number)
318 {
319  if(isNull(number))
320  {
321  str += "[]";
322  return;
323  }
324 
325  toStr(str, Decimal(number));
326 }
327 
328 /// Serializes a floating-point decimal into a string.
329 template
330 <
331  class Mantissa,
332  class Exponent
333 >
336 {
337  std::string str;
338 
339  toStr(str, number);
340 
341  return str;
342 }
343 
344 /// Serializes a fixed-point decimal into a string.
345 template
346 <
347  class Mantissa,
348  class Exponent
349 >
350 inline
352 std::string
354  const
356  <
357  Mantissa,
358  Exponent
359  >& number)
360 {
361  std::string str;
362 
363  toStr(str, number);
364 
365  return str;
366 }
367 
368 /// Serializes into a stream.
369 inline
370 std::ostream& operator << (std::ostream& stream, const Decimal& value)
371 {
372  std::string str;
373 
374  toStr(str, value);
375 
376  return stream << str;
377 }
378 
379 /// Serializes into a stream.
380 template
381  <
382  class Mantissa,
383  class Exponent
384  >
385 inline
386 std::ostream&
388  std::ostream& stream,
389  const
391  <Mantissa, Exponent>& value)
392 {
393  std::string str;
394 
395  toStr(str, value);
396 
397  return stream << str;
398 }
399 
400 ///\private
401 template
402 <
403  class Decimal1,
404  class Decimal2
405 >
406 void checkAgsValid(
407  const Decimal1& arg1, const Decimal2& arg2)
408 {
409  if(isNull(arg1) || isNull(arg2))
410  throw std::invalid_argument("Provided argument is Null.");
411 }
412 
413 /// Compares two fixed-point decimals.
414 template
415 <
416  class Mantissa,
417  class Exponent
418 >
421 bool
423  const
425  <Mantissa, Exponent>& left,
426  const
428  <Mantissa, Exponent>& right)
429 {
430  if(isNull(left) && isNull(right))
431  return true;
432 
433  return left.mantissa() == right.mantissa();
434 }
435 
436 /// Compares two fixed-point decimals.
437 template
438 <
439  class Mantissa,
440  class Exponent
441 >
444 bool
446  const
448  <Mantissa, Exponent>& left,
449  const
451  <Mantissa, Exponent>& right)
452 {
453  return !(left == right);
454 }
455 
456 /// Compares two fixed-point decimals.
457 template
458 <
459  class Mantissa,
460  class Exponent
461 >
464 bool
466  const
468  <Mantissa, Exponent>& left,
469  const
471  <Mantissa, Exponent>& right)
472 {
473  checkAgsValid(left, right);
474 
475  return left.mantissa() < right.mantissa();
476 }
477 
478 /// Compares two fixed-point decimals.
479 template
480 <
481  class Mantissa,
482  class Exponent
483 >
486 bool
488  const
490  <Mantissa, Exponent>& left,
491  const
493  <Mantissa, Exponent>& right)
494 {
495  checkAgsValid(left, right);
496 
497  return left.mantissa() > right.mantissa();
498 }
499 
500 /// Compares two fixed-point decimals.
501 template
502 <
503  class Mantissa,
504  class Exponent
505 >
508 bool
510  const
512  <Mantissa, Exponent>& left,
513  const
515  <Mantissa, Exponent>& right)
516 {
517  checkAgsValid(left, right);
518 
519  return left.mantissa() <= right.mantissa();
520 }
521 
522 /// Compares two fixed-point decimals.
523 template
524 <
525  class Mantissa,
526  class Exponent
527 >
530 bool
532  const
534  <Mantissa, Exponent>& left,
535  const
537  <Mantissa, Exponent>& right)
538 {
539  checkAgsValid(left, right);
540 
541  return left.mantissa() >= right.mantissa();
542 }
543 
544 /// Compares two decimals.
545 template
546 <
547  class Decimal1,
548  class Decimal2
549 >
552 typename EnableIf<details::AreBothDecimals<Decimal1, Decimal2>::value, bool>::type
554  const Decimal1& left, const Decimal2& right)
555 {
556  if(isNull(left) && isNull(right))
557  return true;
558 
559  return Decimal(left) == Decimal(right);
560 }
561 
562 /// Compares two decimals.
563 template
564 <
565  class Decimal1,
566  class Decimal2
567 >
570 typename EnableIf<details::AreBothDecimals<Decimal1, Decimal2>::value, bool>::type
572  const Decimal1& left, const Decimal2& right)
573 {
574  return !(left == right);
575 }
576 
577 /// Compares two decimals.
578 template
579 <
580  class Decimal1,
581  class Decimal2
582 >
585 typename EnableIf<details::AreBothDecimals<Decimal1, Decimal2>::value, bool>::type
587  const Decimal1& left, const Decimal2& right)
588 {
589  checkAgsValid(left, right);
590 
591  return Decimal(left) > Decimal(right);
592 }
593 
594 /// Compares two decimals.
595 template
596 <
597  class Decimal1,
598  class Decimal2
599 >
602 typename EnableIf<details::AreBothDecimals<Decimal1, Decimal2>::value, bool>::type
604  const Decimal1& left, const Decimal2& right)
605 {
606  checkAgsValid(left, right);
607 
608  return Decimal(left) >= Decimal(right);
609 }
610 
611 /// Compares two decimals.
612 template
613 <
614  class Decimal1,
615  class Decimal2
616 >
619 typename EnableIf<details::AreBothDecimals<Decimal1, Decimal2>::value, bool>::type
621  const Decimal1& left, const Decimal2& right)
622 {
623  checkAgsValid(left, right);
624 
625  return Decimal(left) < Decimal(right);
626 }
627 
628 /// Compares two decimals.
629 template
630 <
631  class Decimal1,
632  class Decimal2
633 >
636 typename EnableIf<details::AreBothDecimals<Decimal1, Decimal2>::value, bool>::type
638  const Decimal1& left, const Decimal2& right)
639 {
640  checkAgsValid(left, right);
641 
642  return Decimal(left) <= Decimal(right);
643 }
644 
#define ONIXS_ILINK3_CONSTEXPR
Definition: Compiler.h:179
EnableIf< details::AreBothDecimals< Decimal1, Decimal2 >::value, bool >::type operator>=(const Decimal1 &left, const Decimal2 &right)
Compares two decimals.
EnableIf< details::AreBothDecimals< Decimal1, Decimal2 >::value, bool >::type operator!=(const Decimal1 &left, const Decimal2 &right)
Compares two decimals.
char Char
Character type alias.
Definition: String.h:30
FloatingPointDecimal< Int64, Int32 > Decimal
Universal decimal type.
MantissaType quantizedMantissa(const Decimal &operand, Int32 exponent)
Quantize so its exponent is the same as that of provided value.
A real number with a floating exponent.
Definition: Decimal.h:32
#define ONIXS_ILINK3_PURE
Definition: Compiler.h:189
#define ONIXS_ILINK3_NORETURN
Definition: Compiler.h:184
std::ostream & operator<<(std::ostream &stream, const FixedPointDecimal< Mantissa, Exponent > &value)
Serializes into a stream.
MantissaType Mantissa
Mantissa component type.
Definition: Decimal.h:56
bool isNull(const Decimal32NULL &value) noexcept
Definition: Composites.h:363
EnableIf< details::AreBothDecimals< Decimal1, Decimal2 >::value, bool >::type operator==(const Decimal1 &left, const Decimal2 &right)
Compares two decimals.
EnableIf< details::AreBothDecimals< Decimal1, Decimal2 >::value, bool >::type operator<(const Decimal1 &left, const Decimal2 &right)
Compares two decimals.
Decimal quantize(const Decimal &operand, Int32 exponent)
Quantize so its exponent is the same as that of provided value.
bool fromStr(Decimal &value, const std::string &str) noexcept
Deserializes a decimal number from the given text presentation.
#define ONIXS_ILINK3_MESSAGING_NAMESPACE_END
Definition: ABI.h:144
#define ONIXS_ILINK3_EXPORTED
Definition: Compiler.h:175
#define ONIXS_ILINK3_COLDPATH
Definition: Compiler.h:188
EnableIf< details::IsDecimal< DecimalT >::value, DecimalT >::type convert(const Decimal &number)
Convert the decimal in to a different one.
#define ONIXS_ILINK3_MESSAGING_NAMESPACE_BEGIN
Definition: ABI.h:140
void toStr(std::string &str, const FixedPointDecimal< Mantissa, Exponent > &number)
Serializes a fixed-point decimal into a string.
EnableIf< details::AreBothDecimals< Decimal1, Decimal2 >::value, bool >::type operator<=(const Decimal1 &left, const Decimal2 &right)
Compares two decimals.
#define ONIXS_ILINK3_NODISCARD
Definition: Compiler.h:185
#define ONIXS_ILINK3_NOTHROW
Definition: Compiler.h:176
EnableIf< details::AreBothDecimals< Decimal1, Decimal2 >::value, bool >::type operator>(const Decimal1 &left, const Decimal2 &right)
Compares two decimals.