28 constexpr static int mantissa_bits = 56;
29 constexpr static int exponent_bits = 8;
30 constexpr static int exponent_max = 127;
31 constexpr static int exponent_min = -128;
33 constexpr decimal() noexcept : value(0) {}
36 constexpr decimal& operator=(
decimal const& other)
noexcept =
default;
39 constexpr decimal(
int exponent,
long long mantissa) noexcept : value(decimal::pack(exponent, mantissa)) {}
43 decimal(std::string_view str) :
decimal(to_exponent_mantissa(str)) {}
47 constexpr decimal(
signed long x) :
decimal(0,
static_cast<signed long long>(x)) {}
48 constexpr decimal(
signed int x) :
decimal(0,
static_cast<signed long long>(x)) {}
49 constexpr decimal(
signed short x) :
decimal(0,
static_cast<signed long long>(x)) {}
50 constexpr decimal(
signed char x) :
decimal(0,
static_cast<signed long long>(x)) {}
52 constexpr decimal(
unsigned long x) :
decimal(0,
static_cast<signed long long>(x)) {}
53 constexpr decimal(
unsigned int x) :
decimal(0,
static_cast<signed long long>(x)) {}
54 constexpr decimal(
unsigned short x) :
decimal(0,
static_cast<signed long long>(x)) {}
55 constexpr decimal(
unsigned char x) :
decimal(0,
static_cast<signed long long>(x)) {}
59 value = decimal::pack(other.first, other.second);
62 decimal& operator=(std::string_view str)
noexcept
64 return *
this = to_exponent_mantissa(str);
66 constexpr decimal& operator=(
double other)
noexcept
68 return *
this = to_exponent_mantissa(other);
70 constexpr decimal& operator=(
float other)
noexcept
72 return *
this = to_exponent_mantissa(other);
74 constexpr decimal& operator=(
signed long long other)
noexcept
76 value = decimal::pack(0, other);
79 constexpr decimal& operator=(
signed long other)
noexcept
81 return *
this = narrow_cast<signed long long>(other);
83 constexpr decimal& operator=(
signed int other)
noexcept
85 return *
this = narrow_cast<signed long long>(other);
87 constexpr decimal& operator=(
signed short other)
noexcept
89 return *
this = narrow_cast<signed long long>(other);
91 constexpr decimal& operator=(
signed char other)
noexcept
93 return *
this = narrow_cast<signed long long>(other);
95 constexpr decimal& operator=(
unsigned long long other)
noexcept
97 return *
this = narrow_cast<signed long long>(other);
99 constexpr decimal& operator=(
unsigned long other)
noexcept
101 return *
this = narrow_cast<signed long long>(other);
103 constexpr decimal& operator=(
unsigned int other)
noexcept
105 return *
this = narrow_cast<signed long long>(other);
107 constexpr decimal& operator=(
unsigned short other)
noexcept
109 return *
this = narrow_cast<signed long long>(other);
111 constexpr decimal& operator=(
unsigned char other)
noexcept
113 return *
this = narrow_cast<signed long long>(other);
116 explicit operator signed long long()
const noexcept
129 if (!is_valid_mantissa(m)) {
136 explicit operator signed long()
const noexcept
138 return narrow_cast<signed long>(
static_cast<signed long long>(*
this));
140 explicit operator signed int()
const noexcept
142 return narrow_cast<signed int>(
static_cast<signed long long>(*
this));
144 explicit operator signed short()
const noexcept
146 return narrow_cast<signed short>(
static_cast<signed long long>(*
this));
148 explicit operator signed char()
const noexcept
150 return narrow_cast<signed char>(
static_cast<signed long long>(*
this));
152 explicit operator unsigned long long()
const noexcept
154 return narrow_cast<unsigned int>(
static_cast<signed long long>(*
this));
156 explicit operator unsigned long()
const noexcept
158 return narrow_cast<unsigned long>(
static_cast<signed long long>(*
this));
160 explicit operator unsigned int()
const noexcept
162 return narrow_cast<unsigned int>(
static_cast<signed long long>(*
this));
164 explicit operator unsigned short()
const noexcept
166 return narrow_cast<unsigned short>(
static_cast<signed long long>(*
this));
168 explicit operator unsigned char()
const noexcept
170 return narrow_cast<unsigned char>(
static_cast<signed long long>(*
this));
172 explicit operator long double()
const noexcept
174 return static_cast<long double>(mantissa()) * powl(10.0, exponent());
176 explicit operator double()
const noexcept
178 return static_cast<double>(
static_cast<long double>(*this));
180 explicit operator float()
const noexcept
182 return static_cast<float>(
static_cast<long double>(*this));
185 explicit operator bool()
const noexcept
187 return mantissa() != 0;
192 auto const v = this->normalize();
200 [[nodiscard]]
constexpr int exponent() const noexcept
202 return truncate<int8_t>(value);
209 [[nodiscard]]
constexpr long long mantissa() const noexcept
211 return truncate<int64_t>(value) >> exponent_bits;
216 return {exponent(), mantissa()};
226 auto const[e, m] = exponent_mantissa();
227 auto const[e_, m_] = decimal::normalize(e, m);
233 auto const[e, lhs_m, rhs_m] = decimal::align(*
this, rhs);
234 value = decimal::pack(e, lhs_m + rhs_m);
238 decimal& operator-=(decimal rhs)
noexcept
240 auto const[e, lhs_m, rhs_m] = decimal::align(*
this, rhs);
241 value = decimal::pack(e, lhs_m - rhs_m);
247 return *
this = *
this * rhs;
250 decimal& operator/=(decimal rhs)
noexcept
252 return *
this = *
this / rhs;
256 [[nodiscard]]
friend bool operator==(decimal lhs, decimal rhs)
noexcept
258 auto const[e, lhs_m, rhs_m] = decimal::align(lhs, rhs);
259 return lhs_m == rhs_m;
262 [[nodiscard]]
friend auto operator<=>(decimal lhs, decimal rhs)
noexcept
264 auto const[e, lhs_m, rhs_m] = decimal::align(lhs, rhs);
265 return lhs_m <=> rhs_m;
268 [[nodiscard]]
friend constexpr decimal operator-(decimal rhs)
noexcept
270 return {rhs.exponent(), -rhs.mantissa()};
273 [[nodiscard]]
friend decimal operator+(decimal lhs, decimal rhs)
noexcept
275 auto const[e, lhs_m, rhs_m] = decimal::align(lhs, rhs);
276 return {e, lhs_m + rhs_m};
279 [[nodiscard]]
friend decimal operator-(decimal lhs, decimal rhs)
noexcept
281 auto const[e, lhs_m, rhs_m] = decimal::align(lhs, rhs);
282 return {e, lhs_m - rhs_m};
285 [[nodiscard]]
friend decimal
operator*(decimal lhs, decimal rhs)
noexcept
287 auto lhs_e = lhs.exponent();
288 auto lhs_m = lhs.mantissa();
289 auto rhs_e = rhs.exponent();
290 auto rhs_m = rhs.mantissa();
293 if (not mul_overflow(lhs_m, rhs_m, &m)) {
294 [[likely]]
return {lhs_e + rhs_e, m};
298 std::tie(lhs_e, lhs_m) = decimal::normalize(lhs_e, lhs_m);
299 std::tie(rhs_e, rhs_m) = decimal::normalize(rhs_e, rhs_m);
300 while (mul_overflow(lhs_m, rhs_m, &m)) {
312 return {lhs_e + rhs_e, m};
315 [[nodiscard]]
friend decimal operator/(decimal lhs, decimal rhs)
noexcept
317 auto const rhs_m = rhs.mantissa();
318 hi_axiom(rhs_m != 0);
319 auto const rhs_e = rhs.exponent();
320 auto lhs_m = lhs.mantissa();
321 auto lhs_e = lhs.exponent();
323 std::tie(lhs_e, lhs_m) = decimal::denormalize(lhs_e, lhs_m);
324 return {lhs_e - rhs_e, lhs_m / rhs_m};
327 [[nodiscard]]
friend decimal operator%(decimal lhs, decimal rhs)
noexcept
329 auto const rhs_m = rhs.mantissa();
330 hi_axiom(rhs_m != 0);
331 auto const rhs_e = rhs.exponent();
332 auto lhs_m = lhs.mantissa();
333 auto lhs_e = lhs.exponent();
335 std::tie(lhs_e, lhs_m) = decimal::denormalize(lhs_e, lhs_m);
336 return {lhs_e - rhs_e, lhs_m % rhs_m};
341 auto const[e, m] = x.exponent_mantissa();
344 auto const decimal_position = -e;
345 auto const leading_zeros = (decimal_position - ssize(s)) + 1;
346 if (leading_zeros > 0) {
347 s.insert(0, leading_zeros,
'0');
350 auto const trailing_zeros = e;
351 if (trailing_zeros > 0) {
352 s.append(trailing_zeros,
'0');
355 if (decimal_position > 0) {
356 s.insert(s.size() - decimal_position, 1,
'.');
377 while (m % 10 == 0) {
393 while (is_valid_mantissa(m)) {
404 [[nodiscard]]
constexpr static bool is_valid_mantissa(
long long m)
noexcept
406 m >>= (mantissa_bits - 1);
407 return m == 0 || m == -1;
413 [[nodiscard]]
constexpr static bool is_valid_exponent(
int e)
noexcept
415 e >>= (exponent_bits - 1);
416 return e == 0 || e == -1;
421 auto lhs_e = lhs.exponent();
422 auto lhs_m = lhs.mantissa();
423 auto rhs_e = rhs.exponent();
424 auto rhs_m = rhs.mantissa();
426 if (lhs_e == rhs_e) {
428 }
else if (lhs_e > rhs_e) {
432 if (!is_valid_mantissa(lhs_m)) {
433 while (lhs_e > rhs_e) {
439 }
while (lhs_e > rhs_e);
444 if (!is_valid_mantissa(lhs_m)) {
445 while (lhs_e < rhs_e) {
451 }
while (lhs_e < rhs_e);
453 return {lhs_e, lhs_m, rhs_m};
458 [[nodiscard]]
constexpr static uint64_t pack(
int e,
long long m)
noexcept
461 while (!is_valid_mantissa(m)) {
462 [[unlikely]] m /= 10;
464 hi_assert(e <= exponent_max);
467 while (e > exponent_max) {
468 [[unlikely]]
if ((m *= 10) == 0)
476 hi_assert(is_valid_mantissa(m));
479 while (e < exponent_min) {
480 [[unlikely]]
if ((m /= 10) == 0)
488 return std::bit_cast<uint64_t>(narrow_cast<int64_t>(m) << exponent_bits) | std::bit_cast<uint8_t>(narrow_cast<int8_t>(e));
496 auto e2 = narrow_cast<int>((x_ << 1) >> 53) - 1023 - 52;
497 auto m = narrow_cast<long long>((x_ << 12) >> 12);
498 if (e2 > (-1023 - 52)) {
503 if (narrow_cast<int64_t>(x_) < 0) {
513 while (is_valid_mantissa(m)) {
522 while (!is_valid_mantissa(m)) {
538 int nr_digits_in_front_of_point = -1;
539 for (
auto const c : str) {
540 if (c >=
'0' && c <=
'9') {
543 }
else if (c ==
'.') {
544 nr_digits_in_front_of_point = nr_digits;
545 }
else if (c ==
'\'' || c ==
',') {
547 }
else if (c ==
'-') {
550 throw parse_error(std::format(
"Unexpected character in decimal number '{}'", str));
554 int exponent = (nr_digits_in_front_of_point >= 0) ? (nr_digits_in_front_of_point - nr_digits) : 0;
556 auto first = mantissa_str.
data();
557 auto last = first + mantissa_str.
size();
559 auto const result = std::from_chars(first, last, mantissa, 10);
560 if (result.ptr == first) {
561 throw parse_error(std::format(
"Could not parse mantissa '{}'", mantissa_str));
562 }
else if (result.ec == std::errc::result_out_of_range) {
563 throw parse_error(std::format(
"Mantissa '{}' out of range ", mantissa_str));
565 return {exponent, mantissa};