// // bigdecimal.h // bigdecimal // // Created by Sam Jaffe on 7/3/17. // #pragma once #include #include #include "number_format.h" namespace math { class bigdecimal { private: template using is_signed_t = typename std::enable_if::is_integer && std::numeric_limits::is_signed, void *>::type; template using is_unsigned_t = typename std::enable_if::is_integer && !std::numeric_limits::is_signed, void *>::type; public: using data_type = std::vector; static bigdecimal const ZERO, ONE, NEGATIVE_ONE; static constexpr int32_t const MAX_SEG{999999999}; static constexpr int32_t const OVER_SEG{1000000000}; static constexpr int32_t const SEG_DIGITS{9}; public: bigdecimal(); template bigdecimal(Value && value, int32_t scale) : bigdecimal(value) { rescale(scale); } template bigdecimal(Int value, is_signed_t = nullptr) : bigdecimal(value < 0, static_cast(value < 0 ? -value : value)) {} template bigdecimal(Int value, is_unsigned_t = nullptr) : bigdecimal(false, static_cast(value)) {} bigdecimal(long double); bigdecimal(char const *); int32_t scale() const { return scale_; } void rescale(int32_t); void set_value(bigdecimal const &); bigdecimal operator-() const; friend bigdecimal operator+(bigdecimal, bigdecimal const &); friend bigdecimal operator-(bigdecimal, bigdecimal const &); friend bigdecimal operator*(bigdecimal, bigdecimal const &); friend bigdecimal operator/(bigdecimal, bigdecimal const &); friend bigdecimal & operator+=(bigdecimal &, bigdecimal const &); friend bigdecimal & operator-=(bigdecimal &, bigdecimal const &); friend bigdecimal & operator*=(bigdecimal &, bigdecimal const &); friend bigdecimal & operator/=(bigdecimal &, bigdecimal const &); friend bool operator==(bigdecimal const &, bigdecimal const &); friend bool operator!=(bigdecimal const &, bigdecimal const &); friend bool operator<=(bigdecimal const &, bigdecimal const &); friend bool operator<(bigdecimal const &, bigdecimal const &); friend bool operator>=(bigdecimal const &, bigdecimal const &); friend bool operator>(bigdecimal const &, bigdecimal const &); std::string to_string(number_format const & fmt = default_fmt) const; private: bigdecimal(bool, uint64_t); void set_scale(int32_t); void subtract_impl(bigdecimal const &, bool); friend void swap(bigdecimal & rhs, bigdecimal & lhs) { using std::swap; swap(rhs.is_negative, lhs.is_negative); swap(rhs.scale_, lhs.scale_); swap(rhs.steps_, lhs.steps_); swap(rhs.data, lhs.data); } bool is_negative; int32_t scale_{0}, steps_{0}; data_type data{}; }; }