29 constexpr static int mantissa_bits = 56;
30 constexpr static int exponent_bits = 8;
31 constexpr static int exponent_max = 127;
32 constexpr static int exponent_min = -128;
34 constexpr decimal() noexcept : value(0) {}
37 constexpr decimal& operator=(
decimal const& other)
noexcept =
default;
40 constexpr decimal(
int exponent,
long long mantissa) noexcept : value(decimal::pack(exponent, mantissa)) {}
44 decimal(std::string_view str) :
decimal(to_exponent_mantissa(str)) {}
48 constexpr decimal(
signed long x) :
decimal(0,
static_cast<signed long long>(x)) {}
49 constexpr decimal(
signed int x) :
decimal(0,
static_cast<signed long long>(x)) {}
50 constexpr decimal(
signed short x) :
decimal(0,
static_cast<signed long long>(x)) {}
51 constexpr decimal(
signed char x) :
decimal(0,
static_cast<signed long long>(x)) {}
53 constexpr decimal(
unsigned long x) :
decimal(0,
static_cast<signed long long>(x)) {}
54 constexpr decimal(
unsigned int x) :
decimal(0,
static_cast<signed long long>(x)) {}
55 constexpr decimal(
unsigned short x) :
decimal(0,
static_cast<signed long long>(x)) {}
56 constexpr decimal(
unsigned char x) :
decimal(0,
static_cast<signed long long>(x)) {}
60 value = decimal::pack(other.first, other.second);
63 decimal& operator=(std::string_view str)
noexcept
65 return *
this = to_exponent_mantissa(str);
67 constexpr decimal& operator=(
double other)
noexcept
69 return *
this = to_exponent_mantissa(other);
71 constexpr decimal& operator=(
float other)
noexcept
73 return *
this = to_exponent_mantissa(other);
75 constexpr decimal& operator=(
signed long long other)
noexcept
77 value = decimal::pack(0, other);
80 constexpr decimal& operator=(
signed long other)
noexcept
82 return *
this = narrow_cast<signed long long>(other);
84 constexpr decimal& operator=(
signed int other)
noexcept
86 return *
this = narrow_cast<signed long long>(other);
88 constexpr decimal& operator=(
signed short other)
noexcept
90 return *
this = narrow_cast<signed long long>(other);
92 constexpr decimal& operator=(
signed char other)
noexcept
94 return *
this = narrow_cast<signed long long>(other);
96 constexpr decimal& operator=(
unsigned long long other)
noexcept
98 return *
this = narrow_cast<signed long long>(other);
100 constexpr decimal& operator=(
unsigned long other)
noexcept
102 return *
this = narrow_cast<signed long long>(other);
104 constexpr decimal& operator=(
unsigned int other)
noexcept
106 return *
this = narrow_cast<signed long long>(other);
108 constexpr decimal& operator=(
unsigned short other)
noexcept
110 return *
this = narrow_cast<signed long long>(other);
112 constexpr decimal& operator=(
unsigned char other)
noexcept
114 return *
this = narrow_cast<signed long long>(other);
117 explicit operator signed long long()
const noexcept
130 if (!is_valid_mantissa(m)) {
137 explicit operator signed long()
const noexcept
139 return narrow_cast<signed long>(
static_cast<signed long long>(*
this));
141 explicit operator signed int()
const noexcept
143 return narrow_cast<signed int>(
static_cast<signed long long>(*
this));
145 explicit operator signed short()
const noexcept
147 return narrow_cast<signed short>(
static_cast<signed long long>(*
this));
149 explicit operator signed char()
const noexcept
151 return narrow_cast<signed char>(
static_cast<signed long long>(*
this));
153 explicit operator unsigned long long()
const noexcept
155 return narrow_cast<unsigned int>(
static_cast<signed long long>(*
this));
157 explicit operator unsigned long()
const noexcept
159 return narrow_cast<unsigned long>(
static_cast<signed long long>(*
this));
161 explicit operator unsigned int()
const noexcept
163 return narrow_cast<unsigned int>(
static_cast<signed long long>(*
this));
165 explicit operator unsigned short()
const noexcept
167 return narrow_cast<unsigned short>(
static_cast<signed long long>(*
this));
169 explicit operator unsigned char()
const noexcept
171 return narrow_cast<unsigned char>(
static_cast<signed long long>(*
this));
173 explicit operator long double()
const noexcept
175 return static_cast<long double>(mantissa()) * powl(10.0, exponent());
177 explicit operator double()
const noexcept
179 return static_cast<double>(
static_cast<long double>(*this));
181 explicit operator float()
const noexcept
183 return static_cast<float>(
static_cast<long double>(*this));
186 explicit operator bool()
const noexcept
188 return mantissa() != 0;
193 hilet v = this->normalize();
201 [[nodiscard]]
constexpr int exponent() const noexcept
203 return truncate<int8_t>(value);
210 [[nodiscard]]
constexpr long long mantissa() const noexcept
212 return truncate<int64_t>(value) >> exponent_bits;
217 return {exponent(), mantissa()};
227 hilet[e, m] = exponent_mantissa();
228 hilet[e_, m_] = decimal::normalize(e, m);
234 hilet[e, lhs_m, rhs_m] = decimal::align(*
this, rhs);
235 value = decimal::pack(e, lhs_m + rhs_m);
239 decimal& operator-=(decimal rhs)
noexcept
241 hilet[e, lhs_m, rhs_m] = decimal::align(*
this, rhs);
242 value = decimal::pack(e, lhs_m - rhs_m);
248 return *
this = *
this * rhs;
251 decimal& operator/=(decimal rhs)
noexcept
253 return *
this = *
this / rhs;
257 [[nodiscard]]
friend bool operator==(decimal lhs, decimal rhs)
noexcept
259 hilet[e, lhs_m, rhs_m] = decimal::align(lhs, rhs);
260 return lhs_m == rhs_m;
263 [[nodiscard]]
friend auto operator<=>(decimal lhs, decimal rhs)
noexcept
265 hilet[e, lhs_m, rhs_m] = decimal::align(lhs, rhs);
266 return lhs_m <=> rhs_m;
269 [[nodiscard]]
friend constexpr decimal operator-(decimal rhs)
noexcept
271 return {rhs.exponent(), -rhs.mantissa()};
274 [[nodiscard]]
friend decimal operator+(decimal lhs, decimal rhs)
noexcept
276 hilet[e, lhs_m, rhs_m] = decimal::align(lhs, rhs);
277 return {e, lhs_m + rhs_m};
280 [[nodiscard]]
friend decimal operator-(decimal lhs, decimal rhs)
noexcept
282 hilet[e, lhs_m, rhs_m] = decimal::align(lhs, rhs);
283 return {e, lhs_m - rhs_m};
286 [[nodiscard]]
friend decimal operator*(decimal lhs, decimal rhs)
noexcept
288 auto lhs_e = lhs.exponent();
289 auto lhs_m = lhs.mantissa();
290 auto rhs_e = rhs.exponent();
291 auto rhs_m = rhs.mantissa();
295 [[likely]]
return {lhs_e + rhs_e, m};
299 std::tie(lhs_e, lhs_m) = decimal::normalize(lhs_e, lhs_m);
300 std::tie(rhs_e, rhs_m) = decimal::normalize(rhs_e, rhs_m);
313 return {lhs_e + rhs_e, m};
316 [[nodiscard]]
friend decimal operator/(decimal lhs, decimal rhs)
noexcept
318 hilet rhs_m = rhs.mantissa();
319 hi_axiom(rhs_m != 0);
320 hilet rhs_e = rhs.exponent();
321 auto lhs_m = lhs.mantissa();
322 auto lhs_e = lhs.exponent();
324 std::tie(lhs_e, lhs_m) = decimal::denormalize(lhs_e, lhs_m);
325 return {lhs_e - rhs_e, lhs_m / rhs_m};
328 [[nodiscard]]
friend decimal operator%(decimal lhs, decimal rhs)
noexcept
330 hilet rhs_m = rhs.mantissa();
331 hi_axiom(rhs_m != 0);
332 hilet rhs_e = rhs.exponent();
333 auto lhs_m = lhs.mantissa();
334 auto lhs_e = lhs.exponent();
336 std::tie(lhs_e, lhs_m) = decimal::denormalize(lhs_e, lhs_m);
337 return {lhs_e - rhs_e, lhs_m % rhs_m};
342 hilet[e, m] = x.exponent_mantissa();
345 hilet decimal_position = -e;
346 hilet leading_zeros = (decimal_position - ssize(s)) + 1;
347 if (leading_zeros > 0) {
348 s.insert(0, leading_zeros,
'0');
351 hilet trailing_zeros = e;
352 if (trailing_zeros > 0) {
353 s.append(trailing_zeros,
'0');
356 if (decimal_position > 0) {
357 s.insert(s.size() - decimal_position, 1,
'.');
378 while (m % 10 == 0) {
394 while (is_valid_mantissa(m)) {
405 [[nodiscard]]
constexpr static bool is_valid_mantissa(
long long m)
noexcept
407 m >>= (mantissa_bits - 1);
408 return m == 0 || m == -1;
414 [[nodiscard]]
constexpr static bool is_valid_exponent(
int e)
noexcept
416 e >>= (exponent_bits - 1);
417 return e == 0 || e == -1;
422 auto lhs_e = lhs.exponent();
423 auto lhs_m = lhs.mantissa();
424 auto rhs_e = rhs.exponent();
425 auto rhs_m = rhs.mantissa();
427 if (lhs_e == rhs_e) {
429 }
else if (lhs_e > rhs_e) {
433 if (!is_valid_mantissa(lhs_m)) {
434 while (lhs_e > rhs_e) {
440 }
while (lhs_e > rhs_e);
445 if (!is_valid_mantissa(lhs_m)) {
446 while (lhs_e < rhs_e) {
452 }
while (lhs_e < rhs_e);
454 return {lhs_e, lhs_m, rhs_m};
459 [[nodiscard]]
constexpr static uint64_t pack(
int e,
long long m)
noexcept
462 while (!is_valid_mantissa(m)) {
463 [[unlikely]] m /= 10;
465 hi_assert(e <= exponent_max);
468 while (e > exponent_max) {
469 [[unlikely]]
if ((m *= 10) == 0)
477 hi_assert(is_valid_mantissa(m));
480 while (e < exponent_min) {
481 [[unlikely]]
if ((m /= 10) == 0)
489 return std::bit_cast<uint64_t>(narrow_cast<int64_t>(m) << exponent_bits) | std::bit_cast<uint8_t>(narrow_cast<int8_t>(e));
497 auto e2 = narrow_cast<int>((x_ << 1) >> 53) - 1023 - 52;
498 auto m = narrow_cast<long long>((x_ << 12) >> 12);
499 if (e2 > (-1023 - 52)) {
504 if (narrow_cast<int64_t>(x_) < 0) {
514 while (is_valid_mantissa(m)) {
523 while (!is_valid_mantissa(m)) {
539 int nr_digits_in_front_of_point = -1;
540 for (hilet c : str) {
541 if (c >=
'0' && c <=
'9') {
544 }
else if (c ==
'.') {
545 nr_digits_in_front_of_point = nr_digits;
546 }
else if (c ==
'\'' || c ==
',') {
548 }
else if (c ==
'-') {
551 throw parse_error(std::format(
"Unexpected character in decimal number '{}'", str));
555 int exponent = (nr_digits_in_front_of_point >= 0) ? (nr_digits_in_front_of_point - nr_digits) : 0;
557 auto first = mantissa_str.
data();
558 auto last = first + mantissa_str.
size();
560 hilet result = std::from_chars(first, last, mantissa, 10);
561 if (result.ptr == first) {
562 throw parse_error(std::format(
"Could not parse mantissa '{}'", mantissa_str));
563 }
else if (result.ec == std::errc::result_out_of_range) {
564 throw parse_error(std::format(
"Mantissa '{}' out of range ", mantissa_str));
566 return {exponent, mantissa};