aboutsummaryrefslogtreecommitdiff
path: root/src/stdlib/print.c
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2025-07-11 15:38:42 -0400
committerBruce Hill <bruce@bruce-hill.com>2025-07-11 15:38:42 -0400
commita51d48201b5245dc2cc2bfb00e0ac8e7b52203d9 (patch)
tree4fd950f4d9c6611aef3a48712857b004a7843c3c /src/stdlib/print.c
parent4c84fbdee185a63e60bc93798c0fc149bcd945fd (diff)
Use _Decimal64 instead of mpdecimal
Diffstat (limited to 'src/stdlib/print.c')
-rw-r--r--src/stdlib/print.c93
1 files changed, 91 insertions, 2 deletions
diff --git a/src/stdlib/print.c b/src/stdlib/print.c
index 3270c765..a2ef7d4e 100644
--- a/src/stdlib/print.c
+++ b/src/stdlib/print.c
@@ -22,7 +22,7 @@ public int _print_int(FILE *f, int64_t n)
if (negative)
*(p--) = '-';
- return fwrite(p + 1, sizeof(char), (size_t)(&buf[19] - p), f);
+ return (int)fwrite(p + 1, sizeof(char), (size_t)(&buf[19] - p), f);
}
public int _print_uint(FILE *f, uint64_t n)
@@ -35,7 +35,7 @@ public int _print_uint(FILE *f, uint64_t n)
n /= 10;
} while (n > 0);
- return fwrite(p + 1, sizeof(char), (size_t)(&buf[19] - p), f);
+ return (int)fwrite(p + 1, sizeof(char), (size_t)(&buf[19] - p), f);
}
public int _print_hex(FILE *f, hex_format_t hex)
@@ -178,6 +178,95 @@ public int _print_char(FILE *f, char c)
#undef ESC
}
+public int _print_decimal64(FILE *f , _Decimal64 x)
+{
+ union {
+ _Decimal64 decimal;
+ struct {
+ uint64_t mantissa:52;
+ uint64_t exponent:11;
+ bool negative:1;
+ };
+ uint64_t bits;
+ } info = {.decimal = x};
+
+ if ((info.bits >> 58 & 0x1F) == 0x1E)
+ return fputs(info.negative ? "-INF" : "INF", f);
+ else if ((info.bits >> 58 & 0x1F) == 0x1F)
+ return fputs("NAN", f);
+
+ // determine exponent e, and mantissa m
+ // where e and m are depend on the bits in m2
+ uint64_t e;
+ uint64_t m;
+ uint64_t m2 = info.bits >> 61 & 0x3;
+ if (m2 == 0x3) {
+ e = info.bits >> 51 & 0x3FF;
+ m = 0x20000000000000 | (info.bits & 0x7FFFFFFFFFFFF);
+ } else {
+ e = info.bits >> 53 & 0x3FF;
+ m = info.bits & 0x1FFFFFFFFFFFFF;
+ }
+
+ if (m == 0) return fputs("0", f);
+
+ char buf[64] = {[63]=0};
+ char *p = &buf[62];
+ int64_t exponent = (int64_t)e - 398;
+
+ uint64_t n = m;
+ do {
+ *(p--) = '0' + (n % 10);
+ n /= 10;
+ } while (n > 0);
+
+ const char *digit_str = p + 1;
+
+ int printed = 0;
+ int64_t digits = (int64_t)(&buf[63] - digit_str);
+
+ if (info.negative)
+ printed += fputc('-', f);
+
+ while (exponent < 0 && digits > 1 && digit_str[digits-1] == '0') {
+ digits -= 1;
+ exponent += 1;
+ }
+
+ if (exponent >= 0) {
+ printed += (int)fwrite(digit_str, sizeof(char), (size_t)digits, f);
+ for (int64_t i = 0; i < exponent; i++)
+ printed += (int)fwrite("0", sizeof(char), 1, f);
+ } else {
+ int64_t digits_above_zero = MAX(digits + exponent, 0);
+ if (digits_above_zero > 0) {
+ printed += (int)fwrite(digit_str, sizeof(char), (size_t)digits_above_zero, f);
+ for (int64_t i = -digits; i > exponent; i--)
+ printed += fputc('0', f);
+ } else {
+ printed += fputc('0', f);
+ }
+
+ int64_t digits_below_zero = digits - digits_above_zero;
+ if (digits_below_zero > 0) {
+ const char *rest = digit_str + digits_above_zero;
+ if (*rest) {
+ printed += fputc('.', f);
+ for (int64_t i = digits_below_zero; i < -exponent; i++)
+ printed += fputc('0', f);
+ printed += fputs(digit_str+digits_above_zero, f);
+ }
+ }
+ }
+
+ return printed;
+}
+
+public int _print_decimal32(FILE *f, _Decimal32 x)
+{
+ return _print_decimal64(f, (_Decimal64)x);
+}
+
public int _print_quoted(FILE *f, quoted_t quoted)
{
#define ESC(e) "\\" e