bigdecimal.h 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. //
  2. // bigdecimal.h
  3. // bigdecimal
  4. //
  5. // Created by Sam Jaffe on 7/3/17.
  6. //
  7. #pragma once
  8. #include <string>
  9. #include <vector>
  10. #include "number_format.h"
  11. namespace math {
  12. class bigdecimal {
  13. private:
  14. template <typename Int>
  15. using is_signed_t =
  16. typename std::enable_if<std::numeric_limits<Int>::is_integer &&
  17. std::numeric_limits<Int>::is_signed,
  18. void *>::type;
  19. template <typename Int>
  20. using is_unsigned_t =
  21. typename std::enable_if<std::numeric_limits<Int>::is_integer &&
  22. !std::numeric_limits<Int>::is_signed,
  23. void *>::type;
  24. public:
  25. using data_type = std::vector<int32_t>;
  26. static bigdecimal const ZERO, ONE, NEGATIVE_ONE;
  27. static constexpr int32_t const MAX_SEG{999999999};
  28. static constexpr int32_t const OVER_SEG{1000000000};
  29. static constexpr int32_t const SEG_DIGITS{9};
  30. public:
  31. bigdecimal();
  32. template <typename Value>
  33. bigdecimal(Value && value, int32_t scale) : bigdecimal(value) {
  34. rescale(scale);
  35. }
  36. template <typename Int>
  37. bigdecimal(Int value, is_signed_t<Int> = nullptr)
  38. : bigdecimal(value < 0,
  39. static_cast<uint64_t>(value < 0 ? -value : value)) {}
  40. template <typename Int>
  41. bigdecimal(Int value, is_unsigned_t<Int> = nullptr)
  42. : bigdecimal(false, static_cast<uint64_t>(value)) {}
  43. bigdecimal(long double);
  44. bigdecimal(char const *);
  45. int32_t scale() const { return scale_; }
  46. void rescale(int32_t);
  47. void set_value(bigdecimal const &);
  48. bigdecimal operator-() const;
  49. friend bigdecimal operator+(bigdecimal, bigdecimal const &);
  50. friend bigdecimal operator-(bigdecimal, bigdecimal const &);
  51. friend bigdecimal operator*(bigdecimal, bigdecimal const &);
  52. friend bigdecimal operator/(bigdecimal, bigdecimal const &);
  53. friend bigdecimal & operator+=(bigdecimal &, bigdecimal const &);
  54. friend bigdecimal & operator-=(bigdecimal &, bigdecimal const &);
  55. friend bigdecimal & operator*=(bigdecimal &, bigdecimal const &);
  56. friend bigdecimal & operator/=(bigdecimal &, bigdecimal const &);
  57. friend bool operator==(bigdecimal const &, bigdecimal const &);
  58. friend bool operator!=(bigdecimal const &, bigdecimal const &);
  59. friend bool operator<=(bigdecimal const &, bigdecimal const &);
  60. friend bool operator<(bigdecimal const &, bigdecimal const &);
  61. friend bool operator>=(bigdecimal const &, bigdecimal const &);
  62. friend bool operator>(bigdecimal const &, bigdecimal const &);
  63. std::string to_string(number_format const & fmt = default_fmt) const;
  64. private:
  65. bigdecimal(bool, uint64_t);
  66. void set_scale(int32_t);
  67. void subtract_impl(bigdecimal const &, bool);
  68. friend void swap(bigdecimal & rhs, bigdecimal & lhs) {
  69. using std::swap;
  70. swap(rhs.is_negative, lhs.is_negative);
  71. swap(rhs.scale_, lhs.scale_);
  72. swap(rhs.steps_, lhs.steps_);
  73. swap(rhs.data, lhs.data);
  74. }
  75. bool is_negative;
  76. int32_t scale_{0}, steps_{0};
  77. data_type data{};
  78. };
  79. }