26 constexpr static int mantissa_bits = 56;
27 constexpr static int exponent_bits = 8;
28 constexpr static int exponent_max = 127;
29 constexpr static int exponent_min = -128;
31 constexpr decimal() noexcept : value(0) {}
34 constexpr decimal& operator=(
decimal const& other)
noexcept =
default;
37 constexpr decimal(
int exponent,
long long mantissa) noexcept : value(decimal::pack(exponent, mantissa)) {}
41 decimal(std::string_view str) :
decimal(to_exponent_mantissa(str)) {}
45 constexpr decimal(
signed long x) :
decimal(0,
static_cast<signed long long>(x)) {}
46 constexpr decimal(
signed int x) :
decimal(0,
static_cast<signed long long>(x)) {}
47 constexpr decimal(
signed short x) :
decimal(0,
static_cast<signed long long>(x)) {}
48 constexpr decimal(
signed char x) :
decimal(0,
static_cast<signed long long>(x)) {}
50 constexpr decimal(
unsigned long x) :
decimal(0,
static_cast<signed long long>(x)) {}
51 constexpr decimal(
unsigned int x) :
decimal(0,
static_cast<signed long long>(x)) {}
52 constexpr decimal(
unsigned short x) :
decimal(0,
static_cast<signed long long>(x)) {}
53 constexpr decimal(
unsigned char x) :
decimal(0,
static_cast<signed long long>(x)) {}
57 value = decimal::pack(other.first, other.second);
60 decimal& operator=(std::string_view str)
noexcept
62 return *
this = to_exponent_mantissa(str);
64 constexpr decimal& operator=(
double other)
noexcept
66 return *
this = to_exponent_mantissa(other);
68 constexpr decimal& operator=(
float other)
noexcept
70 return *
this = to_exponent_mantissa(other);
72 constexpr decimal& operator=(
signed long long other)
noexcept
74 value = decimal::pack(0, other);
77 constexpr decimal& operator=(
signed long other)
noexcept
79 return *
this = narrow_cast<signed long long>(other);
81 constexpr decimal& operator=(
signed int other)
noexcept
83 return *
this = narrow_cast<signed long long>(other);
85 constexpr decimal& operator=(
signed short other)
noexcept
87 return *
this = narrow_cast<signed long long>(other);
89 constexpr decimal& operator=(
signed char other)
noexcept
91 return *
this = narrow_cast<signed long long>(other);
93 constexpr decimal& operator=(
unsigned long long other)
noexcept
95 return *
this = narrow_cast<signed long long>(other);
97 constexpr decimal& operator=(
unsigned long other)
noexcept
99 return *
this = narrow_cast<signed long long>(other);
101 constexpr decimal& operator=(
unsigned int other)
noexcept
103 return *
this = narrow_cast<signed long long>(other);
105 constexpr decimal& operator=(
unsigned short other)
noexcept
107 return *
this = narrow_cast<signed long long>(other);
109 constexpr decimal& operator=(
unsigned char other)
noexcept
111 return *
this = narrow_cast<signed long long>(other);
114 explicit operator signed long long()
const noexcept
127 if (!is_valid_mantissa(m)) {
134 explicit operator signed long()
const noexcept
136 return narrow_cast<signed long>(
static_cast<signed long long>(*
this));
138 explicit operator signed int()
const noexcept
140 return narrow_cast<signed int>(
static_cast<signed long long>(*
this));
142 explicit operator signed short()
const noexcept
144 return narrow_cast<signed short>(
static_cast<signed long long>(*
this));
146 explicit operator signed char()
const noexcept
148 return narrow_cast<signed char>(
static_cast<signed long long>(*
this));
150 explicit operator unsigned long long()
const noexcept
152 return narrow_cast<unsigned int>(
static_cast<signed long long>(*
this));
154 explicit operator unsigned long()
const noexcept
156 return narrow_cast<unsigned long>(
static_cast<signed long long>(*
this));
158 explicit operator unsigned int()
const noexcept
160 return narrow_cast<unsigned int>(
static_cast<signed long long>(*
this));
162 explicit operator unsigned short()
const noexcept
164 return narrow_cast<unsigned short>(
static_cast<signed long long>(*
this));
166 explicit operator unsigned char()
const noexcept
168 return narrow_cast<unsigned char>(
static_cast<signed long long>(*
this));
170 explicit operator long double()
const noexcept
172 return static_cast<long double>(mantissa()) * powl(10.0, exponent());
174 explicit operator double()
const noexcept
176 return static_cast<double>(
static_cast<long double>(*this));
178 explicit operator float()
const noexcept
180 return static_cast<float>(
static_cast<long double>(*this));
183 explicit operator bool()
const noexcept
185 return mantissa() != 0;
190 hilet v = this->normalize();
198 [[nodiscard]]
constexpr int exponent() const noexcept
200 return truncate<int8_t>(value);
207 [[nodiscard]]
constexpr long long mantissa() const noexcept
209 return truncate<int64_t>(value) >> exponent_bits;
214 return {exponent(), mantissa()};
224 hilet[e, m] = exponent_mantissa();
225 hilet[e_, m_] = decimal::normalize(e, m);
231 hilet[e, lhs_m, rhs_m] = decimal::align(*
this, rhs);
232 value = decimal::pack(e, lhs_m + rhs_m);
236 decimal& operator-=(decimal rhs)
noexcept
238 hilet[e, lhs_m, rhs_m] = decimal::align(*
this, rhs);
239 value = decimal::pack(e, lhs_m - rhs_m);
243 decimal& operator*=(decimal rhs)
noexcept
245 return *
this = *
this * rhs;
248 decimal& operator/=(decimal rhs)
noexcept
250 return *
this = *
this / rhs;
254 [[nodiscard]]
friend bool operator==(decimal lhs, decimal rhs)
noexcept
256 hilet[e, lhs_m, rhs_m] = decimal::align(lhs, rhs);
257 return lhs_m == rhs_m;
260 [[nodiscard]]
friend auto operator<=>(decimal lhs, decimal rhs)
noexcept
262 hilet[e, lhs_m, rhs_m] = decimal::align(lhs, rhs);
263 return lhs_m <=> rhs_m;
266 [[nodiscard]]
friend constexpr decimal operator-(decimal rhs)
noexcept
268 return {rhs.exponent(), -rhs.mantissa()};
271 [[nodiscard]]
friend decimal operator+(decimal lhs, decimal rhs)
noexcept
273 hilet[e, lhs_m, rhs_m] = decimal::align(lhs, rhs);
274 return {e, lhs_m + rhs_m};
277 [[nodiscard]]
friend decimal operator-(decimal lhs, decimal rhs)
noexcept
279 hilet[e, lhs_m, rhs_m] = decimal::align(lhs, rhs);
280 return {e, lhs_m - rhs_m};
283 [[nodiscard]]
friend decimal operator*(decimal lhs, decimal rhs)
noexcept
285 auto lhs_e = lhs.exponent();
286 auto lhs_m = lhs.mantissa();
287 auto rhs_e = rhs.exponent();
288 auto rhs_m = rhs.mantissa();
292 [[likely]]
return {lhs_e + rhs_e, m};
296 std::tie(lhs_e, lhs_m) = decimal::normalize(lhs_e, lhs_m);
297 std::tie(rhs_e, rhs_m) = decimal::normalize(rhs_e, rhs_m);
310 return {lhs_e + rhs_e, m};
313 [[nodiscard]]
friend decimal operator/(decimal lhs, decimal rhs)
noexcept
315 hilet rhs_m = rhs.mantissa();
317 hilet rhs_e = rhs.exponent();
318 auto lhs_m = lhs.mantissa();
319 auto lhs_e = lhs.exponent();
321 std::tie(lhs_e, lhs_m) = decimal::denormalize(lhs_e, lhs_m);
322 return {lhs_e - rhs_e, lhs_m / rhs_m};
325 [[nodiscard]]
friend decimal operator%(decimal lhs, decimal rhs)
noexcept
327 hilet rhs_m = rhs.mantissa();
329 hilet rhs_e = rhs.exponent();
330 auto lhs_m = lhs.mantissa();
331 auto lhs_e = lhs.exponent();
333 std::tie(lhs_e, lhs_m) = decimal::denormalize(lhs_e, lhs_m);
334 return {lhs_e - rhs_e, lhs_m % rhs_m};
339 hilet[e, m] = x.exponent_mantissa();
342 hilet decimal_position = -e;
343 hilet leading_zeros = (decimal_position - ssize(s)) + 1;
344 if (leading_zeros > 0) {
345 s.insert(0, leading_zeros,
'0');
348 hilet trailing_zeros = e;
349 if (trailing_zeros > 0) {
350 s.append(trailing_zeros,
'0');
353 if (decimal_position > 0) {
354 s.insert(s.size() - decimal_position, 1,
'.');
375 while (m % 10 == 0) {
391 while (is_valid_mantissa(m)) {
402 [[nodiscard]]
constexpr static bool is_valid_mantissa(
long long m)
noexcept
404 m >>= (mantissa_bits - 1);
405 return m == 0 || m == -1;
411 [[nodiscard]]
constexpr static bool is_valid_exponent(
int e)
noexcept
413 e >>= (exponent_bits - 1);
414 return e == 0 || e == -1;
419 auto lhs_e = lhs.exponent();
420 auto lhs_m = lhs.mantissa();
421 auto rhs_e = rhs.exponent();
422 auto rhs_m = rhs.mantissa();
424 if (lhs_e == rhs_e) {
426 }
else if (lhs_e > rhs_e) {
430 if (!is_valid_mantissa(lhs_m)) {
431 while (lhs_e > rhs_e) {
437 }
while (lhs_e > rhs_e);
442 if (!is_valid_mantissa(lhs_m)) {
443 while (lhs_e < rhs_e) {
449 }
while (lhs_e < rhs_e);
451 return {lhs_e, lhs_m, rhs_m};
456 [[nodiscard]]
constexpr static uint64_t pack(
int e,
long long m)
noexcept
459 while (!is_valid_mantissa(m)) {
460 [[unlikely]] m /= 10;
465 while (e > exponent_max) {
466 [[unlikely]]
if ((m *= 10) == 0)
477 while (e < exponent_min) {
478 [[unlikely]]
if ((m /= 10) == 0)
486 return std::bit_cast<uint64_t>(narrow_cast<int64_t>(m) << exponent_bits) | std::bit_cast<uint8_t>(narrow_cast<int8_t>(e));
494 auto e2 = narrow_cast<int>((x_ << 1) >> 53) - 1023 - 52;
495 auto m = narrow_cast<long long>((x_ << 12) >> 12);
496 if (e2 > (-1023 - 52)) {
501 if (narrow_cast<int64_t>(x_) < 0) {
511 while (is_valid_mantissa(m)) {
520 while (!is_valid_mantissa(m)) {
536 int nr_digits_in_front_of_point = -1;
537 for (
hilet c : str) {
538 if (c >=
'0' && c <=
'9') {
541 }
else if (c ==
'.') {
542 nr_digits_in_front_of_point = nr_digits;
543 }
else if (c ==
'\'' || c ==
',') {
545 }
else if (c ==
'-') {
548 throw parse_error(std::format(
"Unexpected character in decimal number '{}'", str));
552 int exponent = (nr_digits_in_front_of_point >= 0) ? (nr_digits_in_front_of_point - nr_digits) : 0;
554 auto first = mantissa_str.
data();
555 auto last = first + mantissa_str.
size();
557 hilet result = std::from_chars(first, last, mantissa, 10);
558 if (result.ptr == first) {
559 throw parse_error(std::format(
"Could not parse mantissa '{}'", mantissa_str));
560 }
else if (result.ec == std::errc::result_out_of_range) {
561 throw parse_error(std::format(
"Mantissa '{}' out of range ", mantissa_str));
563 return {exponent, mantissa};