1#ifndef SOURCEMETA_CORE_NUMERIC_DECIMAL_H_
2#define SOURCEMETA_CORE_NUMERIC_DECIMAL_H_
4#ifndef SOURCEMETA_CORE_NUMERIC_EXPORT
5#include <sourcemeta/core/numeric_export.h>
8#include <sourcemeta/core/preprocessor.h>
17namespace sourcemeta::core {
21class SOURCEMETA_CORE_NUMERIC_EXPORT
Decimal {
37 requires std::integral<T> && std::is_signed_v<T> &&
38 (!std::same_as<T, std::int64_t>)
46 requires std::integral<T> && std::is_unsigned_v<T> &&
47 (!std::same_as<T, std::uint64_t>)
60 explicit Decimal(
const char *
const value);
63 explicit Decimal(
const std::string &value);
66 explicit Decimal(
const std::string_view value);
75 [[nodiscard]]
static auto nan(std::uint64_t payload = 0) ->
Decimal;
78 [[nodiscard]]
static auto snan(std::uint64_t payload = 0) ->
Decimal;
98 [[nodiscard]] auto
to_string() const -> std::
string;
101 [[nodiscard]] auto
to_int64() const -> std::int64_t;
104 [[nodiscard]] auto
to_int32() const -> std::int32_t;
134 [[nodiscard]] SOURCEMETA_FORCEINLINE auto
is_integer() const ->
bool {
135 return (this->flags_ & FLAG_INTEGER_LITERAL) != 0;
139 [[nodiscard]] SOURCEMETA_FORCEINLINE
auto is_finite() const ->
bool {
140 return (this->flags_ & (FLAG_NAN | FLAG_SNAN | FLAG_INFINITE)) == 0;
144 [[nodiscard]] SOURCEMETA_FORCEINLINE
auto is_real() const ->
bool {
170 [[nodiscard]] SOURCEMETA_FORCEINLINE auto
is_nan() const ->
bool {
171 return (this->flags_ & FLAG_NAN) != 0;
175 [[nodiscard]] SOURCEMETA_FORCEINLINE
auto is_snan() const ->
bool {
176 return (this->flags_ & FLAG_SNAN) != 0;
180 [[nodiscard]] SOURCEMETA_FORCEINLINE
auto is_qnan() const ->
bool {
181 return (this->flags_ & FLAG_NAN) != 0 && ((this->flags_ & FLAG_SNAN) == 0);
188 return static_cast<std::uint64_t
>(this->coefficient_);
192 [[nodiscard]] SOURCEMETA_FORCEINLINE
auto is_infinite() const ->
bool {
193 return (this->flags_ & FLAG_INFINITE) != 0;
197 [[nodiscard]] SOURCEMETA_FORCEINLINE
auto is_signed() const ->
bool {
198 return (this->flags_ & FLAG_SIGN) != 0;
245 [[nodiscard]] auto operator+(const
Decimal &other) const ->
Decimal;
248 [[nodiscard]] auto operator-(const
Decimal &other) const ->
Decimal;
251 [[nodiscard]] auto operator*(const
Decimal &other) const ->
Decimal;
254 [[nodiscard]] auto operator/(const
Decimal &other) const ->
Decimal;
257 [[nodiscard]] auto operator%(const
Decimal &other) const ->
Decimal;
260 [[nodiscard]] auto operator-() const ->
Decimal;
263 [[nodiscard]] auto operator+() const ->
Decimal;
266 auto operator++() ->
Decimal &;
269 auto operator++(
int) ->
Decimal;
272 auto operator--() ->
Decimal &;
275 auto operator--(
int) ->
Decimal;
278 [[nodiscard]] auto operator==(const
Decimal &other) const ->
bool;
281 [[nodiscard]] auto operator!=(const
Decimal &other) const ->
bool;
284 [[nodiscard]] auto operator<(const
Decimal &other) const ->
bool;
287 [[nodiscard]] auto operator<=(const
Decimal &other) const ->
bool;
290 [[nodiscard]] auto operator>(const
Decimal &other) const ->
bool;
293 [[nodiscard]] auto operator>=(const
Decimal &other) const ->
bool;
296 static constexpr std::uint8_t FLAG_SIGN = 0x01;
297 static constexpr std::uint8_t FLAG_NAN = 0x02;
298 static constexpr std::uint8_t FLAG_SNAN = 0x04;
299 static constexpr std::uint8_t FLAG_INFINITE = 0x08;
300 static constexpr std::uint8_t FLAG_INTEGER_LITERAL = 0x40;
304 [[nodiscard]] auto remove_trailing_zeros(std::int32_t allowance) const
307 std::int64_t coefficient_{0};
308 std::uint64_t coefficient_high_{0};
309 std::int32_t exponent_{0};
310 std::uint8_t flags_{0};
314 requires std::integral<T>
315inline auto operator+(
const T left,
const Decimal &right) ->
Decimal {
320 requires std::integral<T>
321inline auto operator-(
const T left,
const Decimal &right) ->
Decimal {
326 requires std::integral<T>
327inline auto operator*(
const T left,
const Decimal &right) ->
Decimal {
332 requires std::integral<T>
333inline auto operator/(
const T left,
const Decimal &right) ->
Decimal {
338 requires std::integral<T>
339inline auto operator%(
const T left,
const Decimal &right) ->
Decimal {
344 requires std::integral<T>
345inline auto operator==(
const T left,
const Decimal &right) ->
bool {
350 requires std::integral<T>
351inline auto operator!=(
const T left,
const Decimal &right) ->
bool {
356 requires std::integral<T>
357inline auto operator<(
const T left,
const Decimal &right) ->
bool {
362 requires std::integral<T>
363inline auto operator<=(
const T left,
const Decimal &right) ->
bool {
368 requires std::integral<T>
369inline auto operator>(
const T left,
const Decimal &right) ->
bool {
374 requires std::integral<T>
375inline auto operator>=(
const T left,
const Decimal &right) ->
bool {
auto is_double() const -> bool
Decimal(const T value)
Construct a decimal number from an unsigned integral type.
Definition numeric_decimal.h:48
SOURCEMETA_FORCEINLINE auto is_snan() const -> bool
Check if the decimal number is a signaling NaN.
Definition numeric_decimal.h:175
auto to_double() const -> double
Convert the decimal number to a 64-bit double.
Decimal(const std::string &value)
Construct a decimal number from a C++ string.
Decimal(const char *const value)
Construct a decimal number from a C-string.
auto divide_integer(const Decimal &other) const -> Decimal
Integer division (truncate toward zero).
Decimal(float value)
Construct a decimal number from a 32-bit float.
auto to_uint32() const -> std::uint32_t
Convert the decimal number to a 32-bit unsigned integer.
auto is_uint64() const -> bool
Check if the decimal number fits in a 64-bit unsigned integer.
auto is_uint32() const -> bool
Check if the decimal number fits in a 32-bit unsigned integer.
auto to_string() const -> std::string
Convert the decimal number to a plain string representation.
auto reduce() const -> Decimal
Strip trailing zeros from the coefficient.
SOURCEMETA_FORCEINLINE auto is_signed() const -> bool
Check if the decimal number is signed (negative, including -0).
Definition numeric_decimal.h:197
auto is_int32() const -> bool
Check if the decimal number fits in a 32-bit signed integer.
SOURCEMETA_FORCEINLINE auto is_finite() const -> bool
Check if the decimal number is finite.
Definition numeric_decimal.h:139
SOURCEMETA_FORCEINLINE auto is_real() const -> bool
Check if the decimal number is a real number (finite and not NaN).
Definition numeric_decimal.h:144
SOURCEMETA_FORCEINLINE auto is_qnan() const -> bool
Check if the decimal number is a quiet NaN.
Definition numeric_decimal.h:180
auto is_integral() const -> bool
auto is_zero() const -> bool
Check if the decimal number is zero.
SOURCEMETA_FORCEINLINE auto is_integer() const -> bool
Definition numeric_decimal.h:134
auto to_scientific_string() const -> std::string
Convert the decimal number to scientific notation string.
auto is_float() const -> bool
Decimal(const std::string_view value)
Construct a decimal number from a string view.
auto logb() const -> Decimal
Return the adjusted exponent (floor of base-10 logarithm).
static auto exact_from(double value) -> Decimal
auto divisible_by(const Decimal &divisor) const -> bool
Check if this decimal number is divisible by another.
Decimal() noexcept
Construct a decimal number initialized to zero.
static auto nan(std::uint64_t payload=0) -> Decimal
Create a quiet NaN (Not a Number) value with an optional payload.
auto to_uint64() const -> std::uint64_t
Convert the decimal number to a 64-bit unsigned integer.
static auto strict_from(double value) -> Decimal
auto same_quantum(const Decimal &other) const -> bool
Check if two numbers have the same quantum (exponent).
SOURCEMETA_FORCEINLINE auto is_nan() const -> bool
Definition numeric_decimal.h:170
SOURCEMETA_FORCEINLINE auto nan_payload() const -> std::uint64_t
Get the payload of a NaN value (0 if no payload).
Definition numeric_decimal.h:185
Decimal(std::int64_t value)
Construct a decimal number from a 64-bit signed integer.
Decimal(double value)
Construct a decimal number from a 64-bit double.
auto to_integral() const -> Decimal
Round the decimal number to an integral value.
auto to_int32() const -> std::int32_t
Convert the decimal number to a 32-bit signed integer.
Decimal(std::uint64_t value)
Construct a decimal number from a 64-bit unsigned integer.
auto compare_total(const Decimal &other) const -> Decimal
IEEE 754 total ordering comparison returning -1, 0, or 1.
static auto negative_infinity() -> Decimal
Create a negative infinity value.
SOURCEMETA_FORCEINLINE auto is_infinite() const -> bool
Check if the decimal number is infinite.
Definition numeric_decimal.h:192
auto trim() const -> Decimal
auto scale_by(const Decimal &scale) const -> Decimal
Scale the number by a power of 10.
static auto infinity() -> Decimal
Create a positive infinity value.
auto to_int64() const -> std::int64_t
Convert the decimal number to a 64-bit signed integer.
static auto snan(std::uint64_t payload=0) -> Decimal
Create a signaling NaN value with an optional payload.
auto to_float() const -> float
Convert the decimal number to a 32-bit float.
auto is_int64() const -> bool
Check if the decimal number fits in a 64-bit signed integer.