aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2023-01-20 11:23:15 +0000
committergingerBill <bill@gingerbill.org>2023-01-20 11:23:15 +0000
commit8f4ffbe1da084561ea8add9c7cd911ab729f7eb3 (patch)
tree52208a722070aa8916bbb2d6104143a5f430f7d4 /src
parent8f3b6738ff5756f923c7d403eb17cf7cc76e62fe (diff)
Fix #2299 by handling very large value cases correctly
Diffstat (limited to 'src')
-rw-r--r--src/big_int.cpp73
-rw-r--r--src/llvm_backend_stmt.cpp2
2 files changed, 49 insertions, 26 deletions
diff --git a/src/big_int.cpp b/src/big_int.cpp
index 36652005e..e350687b4 100644
--- a/src/big_int.cpp
+++ b/src/big_int.cpp
@@ -561,40 +561,63 @@ gb_internal String big_int_to_string(gbAllocator allocator, BigInt const *x, u64
Array<char> buf = {};
array_init(&buf, allocator, 0, 32);
- BigInt v = {};
- mp_init_copy(&v, x);
+ if (x->used >= 498) { // 2^498 ~ 10^150
+ mp_int val = {};
+ mp_abs(x, &val);
+ int exp = 0;
+ mp_err err = mp_log_n(&val, 10, &exp);
+ GB_ASSERT(err == MP_OKAY);
+ GB_ASSERT(exp >= 100);
+
+ mp_int thousand_below = {};
+ mp_int thousand_above = {};
+ mp_init_i32(&thousand_below, 10);
+
+ mp_expt_n(&thousand_below, exp-3, &thousand_below);
+ mp_div(&val, &thousand_below, &thousand_above, nullptr);
+
+ double mant = 1.0e-3 * mp_get_double(&thousand_above);
+
+ char val_buf[256] = {};
+ isize n = gb_snprintf(val_buf, gb_size_of(val_buf)-1, "~ %s%.fe%u", (x->sign ? "-" : ""), mant, exp);
+
+ array_add_elems(&buf, val_buf, n-1);
+ } else {
+ BigInt v = {};
+ mp_init_copy(&v, x);
+
+ if (v.sign) {
+ array_add(&buf, '-');
+ mp_abs(&v, &v);
+ }
- if (v.sign) {
- array_add(&buf, '-');
- mp_abs(&v, &v);
- }
+ isize first_word_idx = buf.count;
- isize first_word_idx = buf.count;
+ BigInt r = {};
+ BigInt b = {};
+ big_int_from_u64(&b, base);
- BigInt r = {};
- BigInt b = {};
- big_int_from_u64(&b, base);
+ u8 digit = 0;
+ while (big_int_cmp(&v, &b) >= 0) {
+ big_int_quo_rem(&v, &b, &v, &r);
+ digit = cast(u8)big_int_to_u64(&r);
+ array_add(&buf, digit_to_char(digit));
+ }
- u8 digit = 0;
- while (big_int_cmp(&v, &b) >= 0) {
- big_int_quo_rem(&v, &b, &v, &r);
+ big_int_rem(&r, &v, &b);
digit = cast(u8)big_int_to_u64(&r);
array_add(&buf, digit_to_char(digit));
- }
- big_int_rem(&r, &v, &b);
- digit = cast(u8)big_int_to_u64(&r);
- array_add(&buf, digit_to_char(digit));
+ big_int_dealloc(&r);
+ big_int_dealloc(&b);
- big_int_dealloc(&r);
- big_int_dealloc(&b);
+ for (isize i = first_word_idx; i < buf.count/2; i++) {
+ isize j = buf.count + first_word_idx - i - 1;
+ char tmp = buf[i];
+ buf[i] = buf[j];
+ buf[j] = tmp;
+ }
- for (isize i = first_word_idx; i < buf.count/2; i++) {
- isize j = buf.count + first_word_idx - i - 1;
- char tmp = buf[i];
- buf[i] = buf[j];
- buf[j] = tmp;
}
-
return make_string(cast(u8 *)buf.data, buf.count);
}
diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp
index 73b4e251f..c268ab09a 100644
--- a/src/llvm_backend_stmt.cpp
+++ b/src/llvm_backend_stmt.cpp
@@ -2321,7 +2321,7 @@ gb_internal void lb_emit_defer_stmts(lbProcedure *p, lbDeferExitKind kind, lbBlo
if (kind == lbDeferExit_Default) {
if (p->scope_index == d.scope_index &&
- d.scope_index > 0) { // TODO(bill): Which is correct: > 0 or > 1?
+ d.scope_index > 0) {
lb_build_defer_stmt(p, d);
array_pop(&p->defer_stmts);
continue;