Advertisement
osipyonok

decimal.h

Feb 22nd, 2017
175
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 41.93 KB | None | 0 0
  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:        decimal.h
  3. // Purpose:     Decimal data type support, for COBOL-like fixed-point
  4. //              operations on currency values.
  5. // Author:      Piotr Likus
  6. // Created:     03/01/2011
  7. // Last change: 18/02/2017
  8. // Version:     1.15
  9. // Licence:     BSD
  10. /////////////////////////////////////////////////////////////////////////////
  11.  
  12. #ifndef _DECIMAL_H__
  13. #define _DECIMAL_H__
  14.  
  15. // ----------------------------------------------------------------------------
  16. // Description
  17. // ----------------------------------------------------------------------------
  18. /// \file decimal.h
  19. ///
  20. /// Decimal value type. Use for capital calculations.
  21. /// Note: maximum handled value is: +9,223,372,036,854,775,807 (divided by prec)
  22. ///
  23. /// Sample usage:
  24. ///   using namespace dec;
  25. ///   decimal<2> value(143125);
  26. ///   value = value / decimal_cast<2>(333);
  27. ///   cout << "Result is: " << value << endl;
  28.  
  29. // ----------------------------------------------------------------------------
  30. // Config section
  31. // ----------------------------------------------------------------------------
  32. // - define DEC_EXTERNAL_INT64 if you do not want internal definition of "int64" data type
  33. //   in this case define "DEC_INT64" somewhere
  34. // - define DEC_EXTERNAL_ROUND if you do not want internal "round()" function
  35. // - define DEC_CROSS_DOUBLE if you want to use double (instead of xdouble) for cross-conversions
  36. // - define DEC_EXTERNAL_LIMITS to define by yourself DEC_MAX_INT32
  37. // - define DEC_NO_CPP11 if your compiler does not support C++11
  38.  
  39. #include <iosfwd>
  40. #include <iomanip>
  41. #include <sstream>
  42. #include <locale>
  43.  
  44. // --> include headers for limits and int64_t
  45.  
  46. #ifndef DEC_NO_CPP11
  47. #include <cstdint>
  48. #include <limits>
  49.  
  50. #else
  51.  
  52. #ifndef __STDC_LIMIT_MACROS
  53. #define __STDC_LIMIT_MACROS
  54. #endif
  55.  
  56. #if defined(__GXX_EXPERIMENTAL_CXX0X) || (__cplusplus >= 201103L)
  57. #include <cstdint>
  58. #else
  59. #include <stdint.h>
  60. #endif // defined
  61. #endif // DEC_NO_CPP11
  62.  
  63. // <--
  64.  
  65. // --> define DEC_MAX_INTxx, DEC_MIN_INTxx if required
  66.  
  67. #ifndef DEC_NAMESPACE
  68. #define DEC_NAMESPACE dec
  69. #endif // DEC_NAMESPACE
  70.  
  71. #ifndef DEC_EXTERNAL_LIMITS
  72. #ifndef DEC_NO_CPP11
  73. //#define DEC_MAX_INT32 ((std::numeric_limits<int32_t>::max)())
  74. #define DEC_MAX_INT64 ((std::numeric_limits<int64_t>::max)())
  75. #define DEC_MIN_INT64 ((std::numeric_limits<int64_t>::min)())
  76. #else
  77. //#define DEC_MAX_INT32 INT32_MAX
  78. #define DEC_MAX_INT64 INT64_MAX
  79. #define DEC_MIN_INT64 INT64_MIN
  80. #endif // DEC_NO_CPP11
  81. #endif // DEC_EXTERNAL_LIMITS
  82.  
  83. // <--
  84.  
  85. namespace DEC_NAMESPACE {
  86.  
  87. // ----------------------------------------------------------------------------
  88. // Simple type definitions
  89. // ----------------------------------------------------------------------------
  90.  
  91. // --> define DEC_INT64 if required
  92. #ifndef DEC_EXTERNAL_INT64
  93. #ifndef DEC_NO_CPP11
  94. typedef int64_t DEC_INT64;
  95. #else
  96. #if defined(_MSC_VER) || defined(__BORLANDC__)
  97. typedef signed __int64 DEC_INT64;
  98. #else
  99. typedef signed long long DEC_INT64;
  100. #endif
  101. #endif
  102. #endif // DEC_EXTERNAL_INT64
  103. // <--
  104.  
  105. #ifdef DEC_NO_CPP11
  106. #define static_assert(a,b)
  107. #endif
  108.  
  109. typedef DEC_INT64 int64;
  110. // type for storing currency value internally
  111. typedef int64 dec_storage_t;
  112. typedef unsigned int uint;
  113. // xdouble is an "extended double" - can be long double, __float128, _Quad - as you wish
  114. typedef long double xdouble;
  115.  
  116. #ifdef DEC_CROSS_DOUBLE
  117. typedef double cross_float;
  118. #else
  119. typedef xdouble cross_float;
  120. #endif
  121.  
  122. // ----------------------------------------------------------------------------
  123. // Forward class definitions
  124. // ----------------------------------------------------------------------------
  125.  
  126. // ----------------------------------------------------------------------------
  127. // Constants
  128. // ----------------------------------------------------------------------------
  129. enum {
  130.     max_decimal_points = 18
  131. };
  132.  
  133. // ----------------------------------------------------------------------------
  134. // Class definitions
  135. // ----------------------------------------------------------------------------
  136. template<int Prec> struct DecimalFactor {
  137.     static const int64 value = 10 * DecimalFactor<Prec - 1>::value;
  138. };
  139.  
  140. template<> struct DecimalFactor<0> {
  141.     static const int64 value = 1;
  142. };
  143.  
  144. template<> struct DecimalFactor<1> {
  145.     static const int64 value = 10;
  146. };
  147.  
  148. #ifndef DEC_EXTERNAL_ROUND
  149.  
  150. // round floating point value and convert to int64
  151. template<class T>
  152. inline int64 round(T value) {
  153.     T val1;
  154.  
  155.     if (value < 0.0) {
  156.         val1 = value - 0.5;
  157.     } else {
  158.         val1 = value + 0.5;
  159.     }
  160.     int64 intPart = static_cast<int64>(val1);
  161.  
  162.     return intPart;
  163. }
  164.  
  165. // calculate output = round(a / b), where output, a, b are int64
  166. inline bool div_rounded(int64 &output, int64 a, int64 b) {
  167.     int64 divisorCorr = std::abs(b) / 2;
  168.     if (a >= 0) {
  169.         if (DEC_MAX_INT64 - a >= divisorCorr) {
  170.             output = (a + divisorCorr) / b;
  171.             return true;
  172.         }
  173.     } else {
  174.         if (-(DEC_MIN_INT64 - a) >= divisorCorr) {
  175.             output = (a - divisorCorr) / b;
  176.             return true;
  177.         }
  178.     }
  179.  
  180.     output = 0;
  181.     return false;
  182. }
  183.  
  184. #endif // DEC_EXTERNAL_ROUND
  185.  
  186. template<class RoundPolicy>
  187. class dec_utils {
  188. private:
  189.     int64 pow10(int n) {
  190.         static const int64 decimalFactorTable[] = { 1, 10, 100, 1000, 10000,
  191.                 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000,
  192.                 100000000000, 1000000000000, 10000000000000, 100000000000000,
  193.                 1000000000000000, 10000000000000000, 100000000000000000,
  194.                 1000000000000000000 };
  195.  
  196.         if (n >= 0 && n <= max_decimal_points) {
  197.             return decimalFactorTable[n];
  198.         } else {
  199.             return 0;
  200.         }
  201.     }
  202.  
  203.     // calculate greatest common divisor
  204.     static int64 gcd(int64 a, int64 b) {
  205.         int64 c;
  206.         while (a != 0) {
  207.             c = a;
  208.             a = b % a;
  209.             b = c;
  210.         }
  211.         return b;
  212.     }
  213.  
  214.     // count number of bits required to store given value
  215.     static int bitcnt(int64 value) {
  216.         int res = 0;
  217.         while (value != 0) {
  218.             value = value >> 1;
  219.             ++res;
  220.         }
  221.         return res;
  222.     }
  223.  
  224. public:
  225.     // result = (value1 * value2) / divisor
  226.     inline static int64 multDiv(const int64 value1, const int64 value2,
  227.             int64 divisor) {
  228.         // we don't check for division by zero, the caller should - the next line will throw.
  229.         const int64 value1int = value1 / divisor;
  230.         int64 value1dec = value1 % divisor;
  231.         const int64 value2int = value2 / divisor;
  232.         int64 value2dec = value2 % divisor;
  233.  
  234.         int64 result = value1 * value2int + value1int * value2dec;
  235.  
  236.         if (value1dec == 0 || value2dec == 0) {
  237.             return result;
  238.         }
  239.  
  240.         int64 resDecPart = value1dec * value2dec;
  241.         if (resDecPart / value1dec == value2dec) { // no overflow
  242.             if (!RoundPolicy::div_rounded(resDecPart, resDecPart, divisor))
  243.                 resDecPart = 0;
  244.             result += resDecPart;
  245.             return result;
  246.         }
  247.  
  248.         // minimalize value1 & divisor
  249.         {
  250.             int64 c = gcd(value1dec, divisor);
  251.             if (c != 1) {
  252.                 value1dec /= c;
  253.                 divisor /= c;
  254.             }
  255.  
  256.             // minimalize value2 & divisor
  257.             c = gcd(value2dec, divisor);
  258.             if (c != 1) {
  259.                 value2dec /= c;
  260.                 divisor /= c;
  261.             }
  262.         }
  263.  
  264.         resDecPart = value1dec * value2dec;
  265.         if (resDecPart / value1dec == value2dec) { // no overflow
  266.             if (RoundPolicy::div_rounded(resDecPart, resDecPart, divisor)) {
  267.                 result += resDecPart;
  268.                 return result;
  269.             }
  270.         }
  271.  
  272.         // overflow can occur - use less precise version
  273.         result += RoundPolicy::round(
  274.                 static_cast<cross_float>(value1dec)
  275.                         * static_cast<cross_float>(value2dec)
  276.                         / static_cast<cross_float>(divisor));
  277.         return result;
  278.     }
  279.  
  280. };
  281.  
  282. // no-rounding policy (decimal places stripped)
  283. class null_round_policy {
  284. public:
  285.     template<class T>
  286.     static int64 round(T value) {
  287.         return static_cast<int64>(value);
  288.     }
  289.  
  290.     static bool div_rounded(int64 &output, int64 a, int64 b) {
  291.         output = a / b;
  292.         return true;
  293.     }
  294. };
  295.  
  296. // default rounding policy - arithmetic, to nearest integer
  297. class def_round_policy {
  298. public:
  299.     template<class T>
  300.     static int64 round(T value) {
  301.         return DEC_NAMESPACE::round(value);
  302.     }
  303.  
  304.     static bool div_rounded(int64 &output, int64 a, int64 b) {
  305.         return DEC_NAMESPACE::div_rounded(output, a, b);
  306.     }
  307. };
  308.  
  309. class half_down_round_policy {
  310. public:
  311.     template<class T>
  312.     static int64 round(T value) {
  313.         T val1;
  314.         T decimals;
  315.  
  316.         if (value >= 0.0) {
  317.             decimals = value - floor(value);
  318.             if (decimals > 0.5) {
  319.                 val1 = ceil(value);
  320.             } else {
  321.                 val1 = value;
  322.             }
  323.         } else {
  324.             decimals = std::abs(value + floor(std::abs(value)));
  325.             if (decimals < 0.5) {
  326.                 val1 = ceil(value);
  327.             } else {
  328.                 val1 = value;
  329.             }
  330.         }
  331.  
  332.         return static_cast<int64>(floor(val1));
  333.     }
  334.  
  335.     static bool div_rounded(int64 &output, int64 a, int64 b) {
  336.         int64 divisorCorr = std::abs(b) / 2;
  337.         int64 remainder = std::abs(a) % std::abs(b);
  338.  
  339.         if (a >= 0) {
  340.             if (DEC_MAX_INT64 - a >= divisorCorr) {
  341.                 if (remainder > divisorCorr) {
  342.                     output = (a + divisorCorr) / b;
  343.                 } else {
  344.                     output = a / b;
  345.                 }
  346.                 return true;
  347.             }
  348.         } else {
  349.             if (-(DEC_MIN_INT64 - a) >= divisorCorr) {
  350.                 output = (a - divisorCorr) / b;
  351.                 return true;
  352.             }
  353.         }
  354.  
  355.         output = 0;
  356.         return false;
  357.     }
  358. };
  359.  
  360. class half_up_round_policy {
  361. public:
  362.     template<class T>
  363.     static int64 round(T value) {
  364.         T val1;
  365.         T decimals;
  366.  
  367.         if (value >= 0.0) {
  368.             decimals = value - floor(value);
  369.             if (decimals >= 0.5) {
  370.                 val1 = ceil(value);
  371.             } else {
  372.                 val1 = value;
  373.             }
  374.         } else {
  375.             decimals = std::abs(value + floor(std::abs(value)));
  376.             if (decimals <= 0.5) {
  377.                 val1 = ceil(value);
  378.             } else {
  379.                 val1 = value;
  380.             }
  381.         }
  382.  
  383.         return static_cast<int64>(floor(val1));
  384.     }
  385.  
  386.     static bool div_rounded(int64 &output, int64 a, int64 b) {
  387.         int64 divisorCorr = std::abs(b) / 2;
  388.         int64 remainder = std::abs(a) % std::abs(b);
  389.  
  390.         if (a >= 0) {
  391.             if (DEC_MAX_INT64 - a >= divisorCorr) {
  392.                 if (remainder >= divisorCorr) {
  393.                     output = (a + divisorCorr) / b;
  394.                 } else {
  395.                     output = a / b;
  396.                 }
  397.                 return true;
  398.             }
  399.         } else {
  400.             if (-(DEC_MIN_INT64 - a) >= divisorCorr) {
  401.                 if (remainder < divisorCorr) {
  402.                     output = (a - remainder) / b;
  403.                 } else if (remainder == divisorCorr) {
  404.                     output = (a + divisorCorr) / b;
  405.                 } else {
  406.                     output = (a + remainder - std::abs(b)) / b;
  407.                 }
  408.                 return true;
  409.             }
  410.         }
  411.  
  412.         output = 0;
  413.         return false;
  414.     }
  415. };
  416.  
  417. // bankers' rounding
  418. class half_even_round_policy {
  419. public:
  420.     template<class T>
  421.     static int64 round(T value) {
  422.         T val1;
  423.         T decimals;
  424.  
  425.         if (value >= 0.0) {
  426.             decimals = value - floor(value);
  427.             if (decimals > 0.5) {
  428.                 val1 = ceil(value);
  429.             } else if (decimals < 0.5) {
  430.                 val1 = floor(value);
  431.             } else {
  432.                 bool is_even = (static_cast<int64>(value - decimals) % 2 == 0);
  433.                 if (is_even) {
  434.                     val1 = floor(value);
  435.                 } else {
  436.                     val1 = ceil(value);
  437.                 }
  438.             }
  439.         } else {
  440.             decimals = std::abs(value + floor(std::abs(value)));
  441.             if (decimals > 0.5) {
  442.                 val1 = floor(value);
  443.             } else if (decimals < 0.5) {
  444.                 val1 = ceil(value);
  445.             } else {
  446.                 bool is_even = (static_cast<int64>(value + decimals) % 2 == 0);
  447.                 if (is_even) {
  448.                     val1 = ceil(value);
  449.                 } else {
  450.                     val1 = floor(value);
  451.                 }
  452.             }
  453.         }
  454.  
  455.         return static_cast<int64>(val1);
  456.     }
  457.  
  458.     static bool div_rounded(int64 &output, int64 a, int64 b) {
  459.         int64 divisorDiv2 = std::abs(b) / 2;
  460.         int64 remainder = std::abs(a) % std::abs(b);
  461.  
  462.         if (remainder == 0) {
  463.             output = a / b;
  464.         } else {
  465.             if (a >= 0) {
  466.  
  467.                 if (remainder > divisorDiv2) {
  468.                     output = (a - remainder + std::abs(b)) / b;
  469.                 } else if (remainder < divisorDiv2) {
  470.                     output = (a - remainder) / b;
  471.                 } else {
  472.                     bool is_even = std::abs(a / b) % 2 == 0;
  473.                     if (is_even) {
  474.                         output = a / b;
  475.                     } else {
  476.                         output = (a - remainder + std::abs(b)) / b;
  477.                     }
  478.                 }
  479.             } else {
  480.                 // negative value
  481.                 if (remainder > divisorDiv2) {
  482.                     output = (a + remainder - std::abs(b)) / b;
  483.                 } else if (remainder < divisorDiv2) {
  484.                     output = (a + remainder) / b;
  485.                 } else {
  486.                     bool is_even = std::abs(a / b) % 2 == 0;
  487.                     if (is_even) {
  488.                         output = a / b;
  489.                     } else {
  490.                         output = (a + remainder - std::abs(b)) / b;
  491.                     }
  492.                 }
  493.             }
  494.         }
  495.  
  496.         return true;
  497.     }
  498. };
  499.  
  500. // round towards +infinity
  501. class ceiling_round_policy {
  502. public:
  503.     template<class T>
  504.     static int64 round(T value) {
  505.         return static_cast<int64>(ceil(value));
  506.     }
  507.  
  508.     static bool div_rounded(int64 &output, int64 a, int64 b) {
  509.         int64 remainder = std::abs(a) % std::abs(b);
  510.         if (remainder == 0) {
  511.             output = a / b;
  512.         } else {
  513.             if (a >= 0) {
  514.                 output = (a + std::abs(b)) / b;
  515.             } else {
  516.                 output = a / b;
  517.             }
  518.         }
  519.         return true;
  520.     }
  521. };
  522.  
  523. // round towards -infinity
  524. class floor_round_policy {
  525. public:
  526.     template<class T>
  527.     static int64 round(T value) {
  528.         return static_cast<int64>(floor(value));
  529.     }
  530.  
  531.     static bool div_rounded(int64 &output, int64 a, int64 b) {
  532.         int64 remainder = std::abs(a) % std::abs(b);
  533.         if (remainder == 0) {
  534.             output = a / b;
  535.         } else {
  536.             if (a >= 0) {
  537.                 output = (a - remainder) / b;
  538.             } else {
  539.                 output = (a + remainder - std::abs(b)) / b;
  540.             }
  541.         }
  542.         return true;
  543.     }
  544. };
  545.  
  546. // round towards zero = truncate
  547. class round_down_round_policy: public null_round_policy {
  548. };
  549.  
  550. // round away from zero
  551. class round_up_round_policy {
  552. public:
  553.     template<class T>
  554.     static int64 round(T value) {
  555.         if (value >= 0.0) {
  556.             return static_cast<int64>(ceil(value));
  557.         } else {
  558.             return static_cast<int64>(floor(value));
  559.         }
  560.     }
  561.  
  562.     static bool div_rounded(int64 &output, int64 a, int64 b) {
  563.         int64 remainder = std::abs(a) % std::abs(b);
  564.         if (remainder == 0) {
  565.             output = a / b;
  566.         } else {
  567.             if (a >= 0) {
  568.                 output = (a + std::abs(b)) / b;
  569.             } else {
  570.                 output = (a - std::abs(b)) / b;
  571.             }
  572.         }
  573.         return true;
  574.     }
  575. };
  576.  
  577. template<int Prec, class RoundPolicy = def_round_policy>
  578. class decimal {
  579. public:
  580.     typedef dec_storage_t raw_data_t;
  581.     enum {
  582.         decimal_points = Prec
  583.     };
  584.  
  585.     decimal() {
  586.         init(0);
  587.     }
  588.     decimal(const decimal &src) {
  589.         init(src);
  590.     }
  591.     explicit decimal(uint value) {
  592.         init(value);
  593.     }
  594.     explicit decimal(int value) {
  595.         init(value);
  596.     }
  597.     explicit decimal(int64 value) {
  598.         init(value);
  599.     }
  600.     explicit decimal(xdouble value) {
  601.         init(value);
  602.     }
  603.     explicit decimal(double value) {
  604.         init(value);
  605.     }
  606.     explicit decimal(float value) {
  607.         init(value);
  608.     }
  609.     explicit decimal(int64 value, int64 precFactor) {
  610.         initWithPrec(value, precFactor);
  611.     }
  612.     explicit decimal(const std::string &value) {
  613.         fromString(value, *this);
  614.     }
  615.  
  616.     ~decimal() {
  617.     }
  618.  
  619.     static int64 getPrecFactor() {
  620.         return DecimalFactor<Prec>::value;
  621.     }
  622.     static int getDecimalPoints() {
  623.         return Prec;
  624.     }
  625.  
  626.     decimal & operator=(const decimal &rhs) {
  627.         if (&rhs != this)
  628.             m_value = rhs.m_value;
  629.         return *this;
  630.     }
  631.  
  632.     template<int Prec2>
  633.     decimal & operator=(const decimal<Prec2> &rhs) {
  634.         if (Prec2 > Prec) {
  635.             static_assert(Prec2 > Prec, "Invalid path");
  636.             RoundPolicy::div_rounded(m_value, rhs.m_value,
  637.                     DecimalFactor<Prec2 - Prec>::value);
  638.         } else {
  639.             static_assert((Prec2 <= Prec), "Invalid path");
  640.             m_value = rhs.m_value * DecimalFactor<Prec - Prec2>::value;
  641.         }
  642.         return *this;
  643.     }
  644.  
  645.     decimal & operator=(int64 rhs) {
  646.         m_value = DecimalFactor<Prec>::value * rhs;
  647.         return *this;
  648.     }
  649.  
  650.     decimal & operator=(int rhs) {
  651.         m_value = DecimalFactor<Prec>::value * rhs;
  652.         return *this;
  653.     }
  654.  
  655.     decimal & operator=(double rhs) {
  656.         m_value = RoundPolicy::round(
  657.                 static_cast<double>(DecimalFactor<Prec>::value) * rhs);
  658.         return *this;
  659.     }
  660.  
  661.     bool operator==(const decimal &rhs) const {
  662.         return (m_value == rhs.m_value);
  663.     }
  664.  
  665.     bool operator<(const decimal &rhs) const {
  666.         return (m_value < rhs.m_value);
  667.     }
  668.  
  669.     bool operator<=(const decimal &rhs) const {
  670.         return (m_value <= rhs.m_value);
  671.     }
  672.  
  673.     bool operator>(const decimal &rhs) const {
  674.         return (m_value > rhs.m_value);
  675.     }
  676.  
  677.     bool operator>=(const decimal &rhs) const {
  678.         return (m_value >= rhs.m_value);
  679.     }
  680.  
  681.     bool operator!=(const decimal &rhs) const {
  682.         return !(*this == rhs);
  683.     }
  684.  
  685.     const decimal operator+(const decimal &rhs) const {
  686.         decimal result = *this;
  687.         result.m_value += rhs.m_value;
  688.         return result;
  689.     }
  690.  
  691.     template<int Prec2>
  692.     const decimal operator+(const decimal<Prec2> &rhs) const {
  693.         decimal result = *this;
  694.         if (Prec2 > Prec) {
  695.             int64 val;
  696.             static_assert((Prec2 > Prec), "Invalid path");
  697.             RoundPolicy::div_rounded(val, rhs.m_value,
  698.                     DecimalFactor<Prec2 - Prec>::value);
  699.             result.m_value += val;
  700.         } else {
  701.             static_assert((Prec2 <= Prec), "Invalid path");
  702.             result.m_value += rhs.m_value * DecimalFactor<Prec - Prec2>::value;
  703.         }
  704.  
  705.         return result;
  706.     }
  707.  
  708.     decimal & operator+=(const decimal &rhs) {
  709.         m_value += rhs.m_value;
  710.         return *this;
  711.     }
  712.  
  713.     template<int Prec2>
  714.     decimal & operator+=(const decimal<Prec2> &rhs) {
  715.         if (Prec2 > Prec) {
  716.             int64 val;
  717.             static_assert((Prec2 > Prec), "Invalid path");
  718.             RoundPolicy::div_rounded(val, rhs.m_value,
  719.                     DecimalFactor<Prec2 - Prec>::value);
  720.             m_value += val;
  721.         } else {
  722.             static_assert((Prec2 <= Prec), "Invalid path");
  723.             m_value += rhs.m_value * DecimalFactor<Prec - Prec2>::value;
  724.         }
  725.  
  726.         return *this;
  727.     }
  728.  
  729.     const decimal operator+() const {
  730.         return *this;
  731.     }
  732.  
  733.     const decimal operator-() const {
  734.         decimal result = *this;
  735.         result.m_value = -result.m_value;
  736.         return result;
  737.     }
  738.  
  739.     const decimal operator-(const decimal &rhs) const {
  740.         decimal result = *this;
  741.         result.m_value -= rhs.m_value;
  742.         return result;
  743.     }
  744.  
  745.     template<int Prec2>
  746.     const decimal operator-(const decimal<Prec2> &rhs) const {
  747.         decimal result = *this;
  748.         if (Prec2 > Prec) {
  749.             int64 val;
  750.             static_assert((Prec2 > Prec), "Invalid path");
  751.             RoundPolicy::div_rounded(val, rhs.m_value,
  752.                     DecimalFactor<Prec2 - Prec>::value);
  753.             result.m_value -= val;
  754.         } else {
  755.             static_assert((Prec2 <= Prec), "Invalid path");
  756.             result.m_value -= rhs.m_value * DecimalFactor<Prec - Prec2>::value;
  757.         }
  758.  
  759.         return result;
  760.     }
  761.  
  762.     decimal & operator-=(const decimal &rhs) {
  763.         m_value -= rhs.m_value;
  764.         return *this;
  765.     }
  766.  
  767.     template<int Prec2>
  768.     decimal & operator-=(const decimal<Prec2> &rhs) {
  769.         if (Prec2 > Prec) {
  770.             int64 val;
  771.             static_assert((Prec2 > Prec), "Invalid path");
  772.             RoundPolicy::div_rounded(val, rhs.m_value,
  773.                     DecimalFactor<Prec2 - Prec>::value);
  774.             m_value -= val;
  775.         } else {
  776.             static_assert((Prec2 <= Prec), "Invalid path");
  777.             m_value -= rhs.m_value * DecimalFactor<Prec - Prec2>::value;
  778.         }
  779.  
  780.         return *this;
  781.     }
  782.  
  783.     const decimal operator*(int rhs) const {
  784.         decimal result = *this;
  785.         result.m_value *= rhs;
  786.         return result;
  787.     }
  788.  
  789.     const decimal operator*(int64 rhs) const {
  790.         decimal result = *this;
  791.         result.m_value *= rhs;
  792.         return result;
  793.     }
  794.  
  795.     const decimal operator*(const decimal &rhs) const {
  796.         decimal result = *this;
  797.         result.m_value = dec_utils<RoundPolicy>::multDiv(result.m_value,
  798.                 rhs.m_value, DecimalFactor<Prec>::value);
  799.         return result;
  800.     }
  801.  
  802.     template<int Prec2>
  803.     const decimal operator*(const decimal<Prec2>& rhs) const {
  804.         decimal result = *this;
  805.         result.m_value = dec_utils<RoundPolicy>::multDiv(result.m_value,
  806.                 rhs.getUnbiased(), DecimalFactor<Prec2>::value);
  807.         return result;
  808.     }
  809.  
  810.     decimal & operator*=(int rhs) {
  811.         m_value *= rhs;
  812.         return *this;
  813.     }
  814.  
  815.     decimal & operator*=(int64 rhs) {
  816.         m_value *= rhs;
  817.         return *this;
  818.     }
  819.  
  820.     decimal & operator*=(const decimal &rhs) {
  821.         m_value = dec_utils<RoundPolicy>::multDiv(m_value, rhs.m_value,
  822.                 DecimalFactor<Prec>::value);
  823.         return *this;
  824.     }
  825.  
  826.     template<int Prec2>
  827.     decimal & operator*=(const decimal<Prec2>& rhs) {
  828.         m_value = dec_utils<RoundPolicy>::multDiv(m_value, rhs.m_value,
  829.                 DecimalFactor<Prec2>::value);
  830.         return *this;
  831.     }
  832.  
  833.     const decimal operator/(int rhs) const {
  834.         decimal result = *this;
  835.  
  836.         if (!RoundPolicy::div_rounded(result.m_value, this->m_value, rhs)) {
  837.             result.m_value = dec_utils<RoundPolicy>::multDiv(result.m_value, 1,
  838.                     rhs);
  839.         }
  840.  
  841.         return result;
  842.     }
  843.  
  844.     const decimal operator/(int64 rhs) const {
  845.         decimal result = *this;
  846.  
  847.         if (!RoundPolicy::div_rounded(result.m_value, this->m_value, rhs)) {
  848.             result.m_value = dec_utils<RoundPolicy>::multDiv(result.m_value, 1,
  849.                     rhs);
  850.         }
  851.  
  852.         return result;
  853.     }
  854.  
  855.     const decimal operator/(const decimal &rhs) const {
  856.         decimal result = *this;
  857.         //result.m_value = (result.m_value * DecimalFactor<Prec>::value) / rhs.m_value;
  858.         result.m_value = dec_utils<RoundPolicy>::multDiv(result.m_value,
  859.                 DecimalFactor<Prec>::value, rhs.m_value);
  860.  
  861.         return result;
  862.     }
  863.  
  864.     template<int Prec2>
  865.     const decimal operator/(const decimal<Prec2>& rhs) const {
  866.         decimal result = *this;
  867.         result.m_value = dec_utils<RoundPolicy>::multDiv(result.m_value,
  868.                 DecimalFactor<Prec2>::value, rhs.getUnbiased());
  869.         return result;
  870.     }
  871.  
  872.     decimal & operator/=(int rhs) {
  873.         if (!RoundPolicy::div_rounded(this->m_value, this->m_value, rhs)) {
  874.             this->m_value = dec_utils<RoundPolicy>::multDiv(this->m_value, 1,
  875.                     rhs);
  876.         }
  877.         return *this;
  878.     }
  879.  
  880.     decimal & operator/=(int64 rhs) {
  881.         if (!RoundPolicy::div_rounded(this->m_value, this->m_value, rhs)) {
  882.             this->m_value = dec_utils<RoundPolicy>::multDiv(this->m_value, 1,
  883.                     rhs);
  884.         }
  885.         return *this;
  886.     }
  887.  
  888.     decimal & operator/=(const decimal &rhs) {
  889.         //m_value = (m_value * DecimalFactor<Prec>::value) / rhs.m_value;
  890.         m_value = dec_utils<RoundPolicy>::multDiv(m_value,
  891.                 DecimalFactor<Prec>::value, rhs.m_value);
  892.  
  893.         return *this;
  894.     }
  895.  
  896.     /// Returns integer indicating sign of value
  897.     /// -1 if value is < 0
  898.     /// +1 if value is > 0
  899.     /// 0  if value is 0
  900.     int sign() const {
  901.         return (m_value > 0) ? 1 : ((m_value < 0) ? -1 : 0);
  902.     }
  903.  
  904.     template<int Prec2>
  905.     decimal & operator/=(const decimal<Prec2> &rhs) {
  906.         m_value = dec_utils<RoundPolicy>::multDiv(m_value,
  907.                 DecimalFactor<Prec2>::value, rhs.m_value);
  908.  
  909.         return *this;
  910.     }
  911.  
  912.     double getAsDouble() const {
  913.         return static_cast<double>(m_value) / getPrecFactorDouble();
  914.     }
  915.  
  916.     void setAsDouble(double value) {
  917.         double nval = value * getPrecFactorDouble();
  918.         m_value = RoundPolicy::round(nval);
  919.     }
  920.  
  921.     xdouble getAsXDouble() const {
  922.         return static_cast<xdouble>(m_value) / getPrecFactorXDouble();
  923.     }
  924.  
  925.     void setAsXDouble(xdouble value) {
  926.         xdouble nval = value * getPrecFactorXDouble();
  927.         m_value = RoundPolicy::round(nval);
  928.     }
  929.  
  930.     // returns integer value = real_value * (10 ^ precision)
  931.     // use to load/store decimal value in external memory
  932.     int64 getUnbiased() const {
  933.         return m_value;
  934.     }
  935.     void setUnbiased(int64 value) {
  936.         m_value = value;
  937.     }
  938.  
  939.     decimal<Prec> abs() const {
  940.         if (m_value >= 0)
  941.             return *this;
  942.         else
  943.             return (decimal<Prec>(0) - *this);
  944.     }
  945.  
  946.     /// returns value rounded to integer using active rounding policy
  947.     int64 getAsInteger() const {
  948.         int64 result;
  949.         RoundPolicy::div_rounded(result, m_value, DecimalFactor<Prec>::value);
  950.         return result;
  951.     }
  952.  
  953.     /// overwrites internal value with integer
  954.     void setAsInteger(int64 value) {
  955.         m_value = DecimalFactor<Prec>::value * value;
  956.     }
  957.  
  958.     /// Returns two parts: before and after decimal point
  959.     /// For negative values both numbers are negative or zero.
  960.     void unpack(int64 &beforeValue, int64 &afterValue) const {
  961.         afterValue = m_value % DecimalFactor<Prec>::value;
  962.         beforeValue = (m_value - afterValue) / DecimalFactor<Prec>::value;
  963.     }
  964.  
  965.     /// Combines two parts (before and after decimal point) into decimal value.
  966.     /// Both input values have to have the same sign for correct results.
  967.     /// Does not perform any rounding or input validation - afterValue must be less than 10^prec.
  968.     /// \param[in] beforeValue value before decimal point
  969.     /// \param[in] afterValue value after decimal point multiplied by 10^prec
  970.     /// \result Returns *this
  971.     decimal &pack(int64 beforeValue, int64 afterValue) {
  972.         if (Prec > 0) {
  973.             m_value = beforeValue * DecimalFactor<Prec>::value;
  974.             m_value += (afterValue % DecimalFactor<Prec>::value);
  975.         } else
  976.             m_value = beforeValue * DecimalFactor<Prec>::value;
  977.         return *this;
  978.     }
  979.  
  980.     /// Version of pack() with rounding, sourcePrec specifies precision of source values.
  981.     /// See also @pack.
  982.     template<int sourcePrec>
  983.     decimal &pack_rounded(int64 beforeValue, int64 afterValue) {
  984.         decimal<sourcePrec> temp;
  985.         temp.pack(beforeValue, afterValue);
  986.         decimal<Prec> result(temp.getUnbiased(), temp.getPrecFactor());
  987.  
  988.         *this = result;
  989.         return *this;
  990.     }
  991.  
  992.     static decimal buildWithExponent(int64 mantissa, int exponent) {
  993.         decimal result;
  994.         result.setWithExponent(mantissa, exponent);
  995.         return result;
  996.     }
  997.  
  998.     static decimal &buildWithExponent(decimal &output, int64 mantissa,
  999.             int exponent) {
  1000.         output.setWithExponent(mantissa, exponent);
  1001.         return output;
  1002.     }
  1003.  
  1004.     void setWithExponent(int64 mantissa, int exponent) {
  1005.  
  1006.         int exponentForPack = exponent + Prec;
  1007.  
  1008.         if (exponentForPack < 0) {
  1009.             int64 newValue;
  1010.             if (!RoundPolicy::div_rounded(newValue, mantissa,
  1011.                     pow10(-exponentForPack))) {
  1012.                 newValue = 0;
  1013.             }
  1014.  
  1015.             m_value = newValue;
  1016.         } else {
  1017.             m_value = mantissa * pow10(exponentForPack);
  1018.         }
  1019.     }
  1020.  
  1021.     void getWithExponent(int64 &mantissa, int &exponent) const {
  1022.         int64 value = m_value;
  1023.         int exp = -Prec;
  1024.  
  1025.         // normalize
  1026.         while (value % 10 == 0) {
  1027.             value /= 10;
  1028.             exp++;
  1029.         }
  1030.  
  1031.         mantissa = value;
  1032.         exponent = exp;
  1033.     }
  1034.  
  1035. protected:
  1036.     inline xdouble getPrecFactorXDouble() const {
  1037.         return static_cast<xdouble>(DecimalFactor<Prec>::value);
  1038.     }
  1039.     inline double getPrecFactorDouble() const {
  1040.         return static_cast<double>(DecimalFactor<Prec>::value);
  1041.     }
  1042.  
  1043.     void init(const decimal &src) {
  1044.         m_value = src.m_value;
  1045.     }
  1046.     void init(uint value) {
  1047.         m_value = DecimalFactor<Prec>::value * value;
  1048.     }
  1049.     void init(int value) {
  1050.         m_value = DecimalFactor<Prec>::value * value;
  1051.     }
  1052.     void init(int64 value) {
  1053.         m_value = DecimalFactor<Prec>::value * value;
  1054.     }
  1055.     void init(xdouble value) {
  1056.         m_value = RoundPolicy::round(
  1057.                 static_cast<xdouble>(DecimalFactor<Prec>::value) * value);
  1058.     }
  1059.     void init(double value) {
  1060.         m_value = RoundPolicy::round(
  1061.                 static_cast<double>(DecimalFactor<Prec>::value) * value);
  1062.     }
  1063.  
  1064.     void init(float value) {
  1065.         m_value = RoundPolicy::round(
  1066.                 static_cast<double>(DecimalFactor<Prec>::value)
  1067.                         * static_cast<double>(value));
  1068.     }
  1069.     void initWithPrec(int64 value, int64 precFactor) {
  1070.         int64 ownFactor = DecimalFactor<Prec>::value;
  1071.  
  1072.         if (ownFactor == precFactor) {
  1073.             // no conversion required
  1074.             m_value = value;
  1075.         } else {
  1076.             // conversion
  1077.             m_value = RoundPolicy::round(
  1078.                     static_cast<cross_float>(value)
  1079.                             * (static_cast<cross_float>(ownFactor)
  1080.                                     / static_cast<cross_float>(precFactor)));
  1081.         }
  1082.     }
  1083.  
  1084.     template<typename T>
  1085.     static T abs(T value) {
  1086.         if (value < 0)
  1087.             return -value;
  1088.         else
  1089.             return value;
  1090.     }
  1091. protected:
  1092.     dec_storage_t m_value;
  1093. };
  1094.  
  1095. // ----------------------------------------------------------------------------
  1096. // Pre-defined types
  1097. // ----------------------------------------------------------------------------
  1098. typedef decimal<2> decimal2;
  1099. typedef decimal<4> decimal4;
  1100. typedef decimal<6> decimal6;
  1101.  
  1102. // ----------------------------------------------------------------------------
  1103. // global functions
  1104. // ----------------------------------------------------------------------------
  1105. template<int Prec, class T>
  1106. decimal<Prec> decimal_cast(const T &arg) {
  1107.     return decimal<Prec>(arg.getUnbiased(), arg.getPrecFactor());
  1108. }
  1109.  
  1110. // Example of use:
  1111. //   c = dec::decimal_cast<6>(a * b);
  1112. template<int Prec>
  1113. decimal<Prec> decimal_cast(uint arg) {
  1114.     decimal<Prec> result(arg);
  1115.     return result;
  1116. }
  1117.  
  1118. template<int Prec>
  1119. decimal<Prec> decimal_cast(int arg) {
  1120.     decimal<Prec> result(arg);
  1121.     return result;
  1122. }
  1123.  
  1124. template<int Prec>
  1125. decimal<Prec> decimal_cast(int64 arg) {
  1126.     decimal<Prec> result(arg);
  1127.     return result;
  1128. }
  1129.  
  1130. template<int Prec>
  1131. decimal<Prec> decimal_cast(double arg) {
  1132.     decimal<Prec> result(arg);
  1133.     return result;
  1134. }
  1135.  
  1136. template<int Prec>
  1137. decimal<Prec> decimal_cast(const std::string &arg) {
  1138.     decimal<Prec> result(arg);
  1139.     return result;
  1140. }
  1141.  
  1142. template<int Prec, int N>
  1143. decimal<Prec> decimal_cast(const char (&arg)[N]) {
  1144.     decimal<Prec> result(arg);
  1145.     return result;
  1146. }
  1147.  
  1148. // with rounding policy
  1149. template<int Prec, typename RoundPolicy>
  1150. decimal<Prec, RoundPolicy> decimal_cast(uint arg) {
  1151.     decimal<Prec, RoundPolicy> result(arg);
  1152.     return result;
  1153. }
  1154.  
  1155. template<int Prec, typename RoundPolicy>
  1156. decimal<Prec, RoundPolicy> decimal_cast(int arg) {
  1157.     decimal<Prec, RoundPolicy> result(arg);
  1158.     return result;
  1159. }
  1160.  
  1161. template<int Prec, typename RoundPolicy>
  1162. decimal<Prec, RoundPolicy> decimal_cast(int64 arg) {
  1163.     decimal<Prec, RoundPolicy> result(arg);
  1164.     return result;
  1165. }
  1166.  
  1167. template<int Prec, typename RoundPolicy>
  1168. decimal<Prec, RoundPolicy> decimal_cast(double arg) {
  1169.     decimal<Prec, RoundPolicy> result(arg);
  1170.     return result;
  1171. }
  1172.  
  1173. template<int Prec, typename RoundPolicy>
  1174. decimal<Prec, RoundPolicy> decimal_cast(const std::string &arg) {
  1175.     decimal<Prec, RoundPolicy> result(arg);
  1176.     return result;
  1177. }
  1178.  
  1179. template<int Prec, typename RoundPolicy, int N>
  1180. decimal<Prec, RoundPolicy> decimal_cast(const char (&arg)[N]) {
  1181.     decimal<Prec, RoundPolicy> result(arg);
  1182.     return result;
  1183. }
  1184.  
  1185. /// Exports decimal to stream
  1186. /// Used format: {-}bbbb.aaaa where
  1187. /// {-} is optional '-' sign character
  1188. /// '.' is locale-dependent decimal point character
  1189. /// bbbb is stream of digits before decimal point
  1190. /// aaaa is stream of digits after decimal point
  1191. template<class decimal_type, typename StreamType>
  1192. void toStream(const decimal_type &arg, StreamType &output) {
  1193.     using namespace std;
  1194.  
  1195.     int64 before, after;
  1196.     int sign;
  1197.  
  1198.     arg.unpack(before, after);
  1199.     sign = 1;
  1200.  
  1201.     if (before < 0) {
  1202.         sign = -1;
  1203.         before = -before;
  1204.     }
  1205.  
  1206.     if (after < 0) {
  1207.         sign = -1;
  1208.         after = -after;
  1209.     }
  1210.  
  1211.     if (sign < 0)
  1212.         output << "-";
  1213.  
  1214.     const char dec_point =
  1215.             use_facet<numpunct<char> >(output.getloc()).decimal_point();
  1216.     output << before;
  1217.     if (arg.getDecimalPoints() > 0) {
  1218.         output << dec_point;
  1219.         output << setw(arg.getDecimalPoints()) << setfill('0') << right
  1220.                 << after;
  1221.     }
  1222. }
  1223.  
  1224. namespace details {
  1225.  
  1226. /// Extract values from stream ready to be packed to decimal
  1227. template<typename StreamType>
  1228. bool parse_unpacked(StreamType &input, int &sign, int64 &before, int64 &after,
  1229.         int &decimalDigits) {
  1230.     using namespace std;
  1231.  
  1232.     enum StateEnum {
  1233.         IN_SIGN, IN_BEFORE_FIRST_DIG, IN_BEFORE_DEC, IN_AFTER_DEC, IN_END
  1234.     } state = IN_SIGN;
  1235.     const numpunct<char> *facet =
  1236.             has_facet<numpunct<char> >(input.getloc()) ?
  1237.                     &use_facet<numpunct<char> >(input.getloc()) : NULL;
  1238.     const char dec_point = (facet != NULL) ? facet->decimal_point() : '.';
  1239.     const bool thousands_grouping =
  1240.             (facet != NULL) ? (!facet->grouping().empty()) : false;
  1241.     const char thousands_sep = (facet != NULL) ? facet->thousands_sep() : ',';
  1242.     enum ErrorCodes {
  1243.         ERR_WRONG_CHAR = -1,
  1244.         ERR_NO_DIGITS = -2,
  1245.         ERR_WRONG_STATE = -3,
  1246.         ERR_STREAM_GET_ERROR = -4
  1247.     };
  1248.  
  1249.     before = after = 0;
  1250.     sign = 1;
  1251.  
  1252.     int error = 0;
  1253.     int digitsCount = 0;
  1254.     int afterDigitCount = 0;
  1255.     char c;
  1256.  
  1257.     while ((input) && (state != IN_END)) // loop while extraction from file is possible
  1258.     {
  1259.         c = static_cast<char>(input.get());
  1260.  
  1261.         switch (state) {
  1262.         case IN_SIGN:
  1263.             if (c == '-') {
  1264.                 sign = -1;
  1265.                 state = IN_BEFORE_FIRST_DIG;
  1266.             } else if (c == '+') {
  1267.                 state = IN_BEFORE_FIRST_DIG;
  1268.             } else if ((c >= '0') && (c <= '9')) {
  1269.                 state = IN_BEFORE_DEC;
  1270.                 before = static_cast<int>(c - '0');
  1271.                 digitsCount++;
  1272.             } else if (c == dec_point) {
  1273.                 state = IN_AFTER_DEC;
  1274.             } else if ((c != ' ') && (c != '\t')) {
  1275.                 state = IN_END;
  1276.                 error = ERR_WRONG_CHAR;
  1277.             }
  1278.             // else ignore char
  1279.             break;
  1280.         case IN_BEFORE_FIRST_DIG:
  1281.             if ((c >= '0') && (c <= '9')) {
  1282.                 before = 10 * before + static_cast<int>(c - '0');
  1283.                 state = IN_BEFORE_DEC;
  1284.                 digitsCount++;
  1285.             } else if (c == dec_point) {
  1286.                 state = IN_AFTER_DEC;
  1287.             } else {
  1288.                 state = IN_END;
  1289.                 error = ERR_WRONG_CHAR;
  1290.             }
  1291.             break;
  1292.         case IN_BEFORE_DEC:
  1293.             if ((c >= '0') && (c <= '9')) {
  1294.                 before = 10 * before + static_cast<int>(c - '0');
  1295.                 digitsCount++;
  1296.             } else if (c == dec_point) {
  1297.                 state = IN_AFTER_DEC;
  1298.             } else if (thousands_grouping && c == thousands_sep) {
  1299.                 ; // ignore the char
  1300.             } else {
  1301.                 state = IN_END;
  1302.             }
  1303.             break;
  1304.         case IN_AFTER_DEC:
  1305.             if ((c >= '0') && (c <= '9')) {
  1306.                 after = 10 * after + static_cast<int>(c - '0');
  1307.                 afterDigitCount++;
  1308.                 if (afterDigitCount >= DEC_NAMESPACE::max_decimal_points)
  1309.                     state = IN_END;
  1310.             } else {
  1311.                 state = IN_END;
  1312.                 if (digitsCount == 0) {
  1313.                     error = ERR_NO_DIGITS;
  1314.                 }
  1315.             }
  1316.             break;
  1317.         default:
  1318.             error = ERR_WRONG_STATE;
  1319.             state = IN_END;
  1320.             break;
  1321.         } // switch state
  1322.     } // while stream good & not end
  1323.  
  1324.     decimalDigits = afterDigitCount;
  1325.  
  1326.     if (error >= 0) {
  1327.  
  1328.         if (sign < 0) {
  1329.             before = -before;
  1330.             after = -after;
  1331.         }
  1332.  
  1333.     } else {
  1334.         before = after = 0;
  1335.     }
  1336.  
  1337.     return (error >= 0);
  1338. } // function
  1339.  
  1340. }
  1341. ;
  1342. // namespace
  1343.  
  1344. /// Converts stream of chars to decimal
  1345. /// Handles the following formats ('.' is selected from locale info):
  1346. /// \code
  1347. /// 123
  1348. /// -123
  1349. /// 123.0
  1350. /// -123.0
  1351. /// 123.
  1352. /// .123
  1353. /// 0.
  1354. /// -.123
  1355. /// \endcode
  1356. /// Spaces and tabs on the front are ignored.
  1357. /// Performs rounding when provided value has higher precision than in output type.
  1358. /// \param[in] input input stream
  1359. /// \param[out] output decimal value, 0 on error
  1360. /// \result Returns true if conversion succeeded
  1361. template<typename decimal_type, typename StreamType>
  1362. bool fromStream(StreamType &input, decimal_type &output) {
  1363.     int sign, afterDigits;
  1364.     int64 before, after;
  1365.     bool result = details::parse_unpacked(input, sign, before, after,
  1366.             afterDigits);
  1367.     if (result) {
  1368.         if (afterDigits <= decimal_type::decimal_points) {
  1369.             // direct mode
  1370.             int corrCnt = decimal_type::decimal_points - afterDigits;
  1371.             while (corrCnt > 0) {
  1372.                 after *= 10;
  1373.                 --corrCnt;
  1374.             }
  1375.             output.pack(before, after);
  1376.         } else {
  1377.             // rounding mode
  1378.             int corrCnt = afterDigits;
  1379.             int64 decimalFactor = 1;
  1380.             while (corrCnt > 0) {
  1381.                 before *= 10;
  1382.                 decimalFactor *= 10;
  1383.                 --corrCnt;
  1384.             }
  1385.             decimal_type temp(before + after, decimalFactor);
  1386.             output = temp;
  1387.         }
  1388.     } else {
  1389.         output = decimal_type(0);
  1390.     }
  1391.     return result;
  1392. }
  1393.  
  1394. /// Exports decimal to string
  1395. /// Used format: {-}bbbb.aaaa where
  1396. /// {-} is optional '-' sign character
  1397. /// '.' is locale-dependent decimal point character
  1398. /// bbbb is stream of digits before decimal point
  1399. /// aaaa is stream of digits after decimal point
  1400. template<int prec, typename roundPolicy>
  1401. std::string &toString(const decimal<prec, roundPolicy> &arg,
  1402.         std::string &output) {
  1403.     using namespace std;
  1404.  
  1405.     ostringstream out;
  1406.     toStream(arg, out);
  1407.     output = out.str();
  1408.     return output;
  1409. }
  1410.  
  1411. /// Exports decimal to string
  1412. /// Used format: {-}bbbb.aaaa where
  1413. /// {-} is optional '-' sign character
  1414. /// '.' is locale-dependent decimal point character
  1415. /// bbbb is stream of digits before decimal point
  1416. /// aaaa is stream of digits after decimal point
  1417. template<int prec, typename roundPolicy>
  1418. std::string toString(const decimal<prec, roundPolicy> &arg) {
  1419.     std::string res;
  1420.     toString(arg, res);
  1421.     return res;
  1422. }
  1423.  
  1424. // input
  1425. template<class charT, class traits, int prec, typename roundPolicy>
  1426. std::basic_istream<charT, traits> &
  1427. operator>>(std::basic_istream<charT, traits> & is,
  1428.         decimal<prec, roundPolicy> & d) {
  1429.     if (!fromStream(is, d))
  1430.         d.setUnbiased(0);
  1431.     return is;
  1432. }
  1433.  
  1434. // output
  1435. template<class charT, class traits, int prec, typename roundPolicy>
  1436. std::basic_ostream<charT, traits> &
  1437. operator<<(std::basic_ostream<charT, traits> & os,
  1438.         const decimal<prec, roundPolicy> & d) {
  1439.     toStream(d, os);
  1440.     return os;
  1441. }
  1442.  
  1443. /// Imports decimal from string
  1444. /// Used format: {-}bbbb.aaaa where
  1445. /// {-} is optional '-' sign character
  1446. /// '.' is locale-dependent decimal point character
  1447. /// bbbb is stream of digits before decimal point
  1448. /// aaaa is stream of digits after decimal point
  1449. template<typename T>
  1450. T fromString(const std::string &str) {
  1451.     std::istringstream is(str);
  1452.     T t;
  1453.     is >> t;
  1454.     return t;
  1455. }
  1456.  
  1457. template<typename T>
  1458. void fromString(const std::string &str, T &out) {
  1459.     std::istringstream is(str);
  1460.     is >> out;
  1461. }
  1462.  
  1463. } // namespace
  1464. #endif // _DECIMAL_H__
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement