lib/fmt: render i64::MIN via math.absi64, not in-i64 negate (#67)
i64dec computed the magnitude with `n = -n` inside i64, which wraps at i64::MIN (-MIN == MIN stays negative), so the `for (n > 0)` loop never ran and println(i64::MIN) emitted only the bare '-'. The whole print/ println/fprint family was affected at the single boundary value (and int MIN, since int is 8B). ref/hare/fmt/print.ha:124-129 takes the magnitude through math::absi64 into a u64; do the same (math.absi64 exists, lib/math/math.ww:12). ww's own printf path was already correct ((-v): u64), so print and printf now agree. fmttest gains fprinti64min + fprintintmin pinning the boundary.
This commit is contained in:
@@ -22,6 +22,7 @@
|
||||
package fmt;
|
||||
|
||||
import io;
|
||||
import math;
|
||||
import memio;
|
||||
import os;
|
||||
import strings;
|
||||
@@ -38,16 +39,18 @@ let i64dec_buf: [21]u8;
|
||||
// of strconv.i64tos for the pre-printf-family print path; the
|
||||
// printf-family path below dispatches through strconv directly.
|
||||
fn i64dec(v: i64) str = {
|
||||
let neg: bool = false;
|
||||
let n: i64 = v;
|
||||
if (n < 0) { neg = true; n = -n; };
|
||||
// ref/hare/fmt/print.ha:124-129: magnitude via math::absi64 into u64,
|
||||
// sign tested separately. `n = -n` on an i64 wraps at i64::MIN
|
||||
// (-MIN == MIN), so the old loop never ran and only the '-' printed.
|
||||
let neg: bool = v < 0;
|
||||
let n: u64 = math.absi64(v);
|
||||
let tmp: [20]u8;
|
||||
let i: i32 = 0;
|
||||
if (n == 0) { tmp[0] = '0'; i = 1; };
|
||||
for (n > 0) {
|
||||
let d: i64 = n % 10i64;
|
||||
tmp[i] = (d + 48i64): u8;
|
||||
n = n / 10i64;
|
||||
if (n == 0u64) { tmp[0] = '0'; i = 1; };
|
||||
for (n > 0u64) {
|
||||
let d: u64 = n % 10u64;
|
||||
tmp[i] = (d + 48u64): u8;
|
||||
n = n / 10u64;
|
||||
i += 1;
|
||||
};
|
||||
let out: i32 = 0;
|
||||
|
||||
Reference in New Issue
Block a user