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;
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 =
static_cast<signed long long>(other);
81 constexpr decimal &operator=(
signed int other)
noexcept
83 return *
this =
static_cast<signed long long>(other);
85 constexpr decimal &operator=(
signed short other)
noexcept
87 return *
this =
static_cast<signed long long>(other);
89 constexpr decimal &operator=(
signed char other)
noexcept
91 return *
this =
static_cast<signed long long>(other);
93 constexpr decimal &operator=(
unsigned long long other)
noexcept
95 return *
this =
static_cast<signed long long>(other);
97 constexpr decimal &operator=(
unsigned long other)
noexcept
99 return *
this =
static_cast<signed long long>(other);
101 constexpr decimal &operator=(
unsigned int other)
noexcept
103 return *
this =
static_cast<signed long long>(other);
105 constexpr decimal &operator=(
unsigned short other)
noexcept
107 return *
this =
static_cast<signed long long>(other);
109 constexpr decimal &operator=(
unsigned char other)
noexcept
111 return *
this =
static_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
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 size_t hash()
const noexcept
193 [[nodiscard]]
constexpr int exponent() const noexcept
195 return static_cast<int8_t
>(value);
202 [[nodiscard]]
constexpr long long mantissa() const noexcept
204 return static_cast<int64_t
>(value) >> 8;
219 ttlet[e, m] = exponent_mantissa();
226 ttlet[e, lhs_m, rhs_m] = decimal::align(*
this, rhs);
227 value = decimal::pack(e, lhs_m + rhs_m);
231 decimal &operator-=(decimal rhs)
noexcept
233 ttlet[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 return *
this = *
this * rhs;
243 decimal &operator/=(decimal rhs)
noexcept
245 return *
this = *
this / rhs;
249 [[nodiscard]]
friend bool operator==(decimal lhs, decimal rhs)
noexcept
251 ttlet[e, lhs_m, rhs_m] = decimal::align(lhs, rhs);
252 return lhs_m == rhs_m;
255 [[nodiscard]]
friend auto operator<=>(decimal lhs, decimal rhs)
noexcept
257 ttlet[e, lhs_m, rhs_m] = decimal::align(lhs, rhs);
258 return lhs_m <=> rhs_m;
261 [[nodiscard]]
friend constexpr decimal operator-(decimal rhs)
noexcept
263 return {rhs.exponent(), -rhs.mantissa()};
266 [[nodiscard]]
friend decimal operator+(decimal lhs, decimal rhs)
noexcept
268 ttlet[e, lhs_m, rhs_m] = decimal::align(lhs, rhs);
269 return {e, lhs_m + rhs_m};
272 [[nodiscard]]
friend decimal operator-(decimal lhs, decimal rhs)
noexcept
274 ttlet[e, lhs_m, rhs_m] = decimal::align(lhs, rhs);
275 return {e, lhs_m - rhs_m};
278 [[nodiscard]]
friend decimal operator*(decimal lhs, decimal rhs)
noexcept
280 auto lhs_e = lhs.exponent();
281 auto lhs_m = lhs.mantissa();
282 auto rhs_e = rhs.exponent();
283 auto rhs_m = rhs.mantissa();
286 if (!mul_overflow(lhs_m, rhs_m, &m)) {
287 [[likely]]
return {lhs_e + rhs_e, m};
293 while (mul_overflow(lhs_m, rhs_m, &m)) {
305 return {lhs_e + rhs_e, m};
308 [[nodiscard]]
friend decimal operator/(decimal lhs, decimal rhs)
noexcept
310 auto rhs_m = rhs.mantissa();
311 tt_axiom(rhs_m != 0);
312 auto rhs_e = rhs.exponent();
313 auto lhs_m = lhs.mantissa();
314 auto lhs_e = lhs.exponent();
316 std::tie(lhs_e, lhs_m) = decimal::denormalize(lhs_e, lhs_m);
317 return {lhs_e - rhs_e, lhs_m / rhs_m};
320 [[nodiscard]]
friend decimal operator%(decimal lhs, decimal rhs)
noexcept
322 auto rhs_m = rhs.mantissa();
323 tt_axiom(rhs_m != 0);
324 auto rhs_e = rhs.exponent();
325 auto lhs_m = lhs.mantissa();
326 auto lhs_e = lhs.exponent();
328 std::tie(lhs_e, lhs_m) = decimal::denormalize(lhs_e, lhs_m);
329 return {lhs_e - rhs_e, lhs_m % rhs_m};
332 [[nodiscard]]
friend std::string to_string(decimal x)
noexcept
334 auto [e, m] = x.exponent_mantissa();
337 auto decimal_position = -e;
338 auto leading_zeros = (decimal_position - std::ssize(s)) + 1;
339 if (leading_zeros > 0) {
340 s.insert(0, leading_zeros,
'0');
343 auto trailing_zeros = e;
344 if (trailing_zeros > 0) {
345 s.append(trailing_zeros,
'0');
348 if (decimal_position > 0) {
349 s.insert(s.size() - decimal_position, 1,
'.');
361 return lhs << to_string(rhs);
370 while (m % 10 == 0) {
386 while (is_valid_mantissa(m)) {
397 [[nodiscard]]
constexpr static bool is_valid_mantissa(
long long m)
noexcept
399 m >>= (mantissa_bits - 1);
400 return m == 0 || m == -1;
406 [[nodiscard]]
constexpr static bool is_valid_exponent(
int e)
noexcept
408 e >>= (exponent_bits - 1);
409 return e == 0 || e == -1;
414 auto lhs_e = lhs.exponent();
415 auto lhs_m = lhs.mantissa();
416 auto rhs_e = rhs.exponent();
417 auto rhs_m = rhs.mantissa();
419 if (lhs_e == rhs_e) {
421 }
else if (lhs_e > rhs_e) {
425 if (!is_valid_mantissa(lhs_m)) {
426 while (lhs_e > rhs_e) {
432 }
while (lhs_e > rhs_e);
437 if (!is_valid_mantissa(lhs_m)) {
438 while (lhs_e < rhs_e) {
444 }
while (lhs_e < rhs_e);
446 return {lhs_e, lhs_m, rhs_m};
451 [[nodiscard]]
constexpr static uint64_t pack(
int e,
long long m)
noexcept
454 while (!is_valid_mantissa(m)) {
455 [[unlikely]] m /= 10;
457 tt_assert(e <= exponent_max);
460 while (e > exponent_max) {
461 [[unlikely]]
if ((m *= 10) == 0)
469 tt_assert(is_valid_mantissa(m));
472 while (e < exponent_min) {
473 [[unlikely]]
if ((m /= 10) == 0)
481 return static_cast<uint64_t
>(m) << exponent_bits |
static_cast<uint8_t
>(e);
489 auto e2 =
static_cast<int>((x_ << 1) >> 53) - 1023 - 52;
490 auto m =
static_cast<long long>((x_ << 12) >> 12);
491 if (e2 > (-1023 - 52)) {
496 if (
static_cast<int64_t
>(x_) < 0) {
506 while (is_valid_mantissa(m)) {
515 while (!is_valid_mantissa(m)) {
531 int nr_digits_in_front_of_point = -1;
532 for (ttlet c : str) {
533 if (c >=
'0' && c <=
'9') {
536 }
else if (c ==
'.') {
537 nr_digits_in_front_of_point = nr_digits;
538 }
else if (c ==
'\'' || c ==
',') {
540 }
else if (c ==
'-') {
543 throw parse_error(
"Unexpected character in decimal number '{}'", str);
547 int exponent = (nr_digits_in_front_of_point >= 0) ? (nr_digits_in_front_of_point - nr_digits) : 0;
549 auto first = mantissa_str.
data();
550 auto last = first + mantissa_str.
size();
552 auto result = std::from_chars(first, last,
mantissa, 10);
553 if (result.ptr == first) {
554 throw parse_error(
"Could not parse mantissa '{}'", mantissa_str);
555 }
else if (result.ec == std::errc::result_out_of_range) {
556 throw parse_error(
"Mantissa '{}' out of range ", mantissa_str);