// Private helpers for moon-humanize.
// See docs/specs/port-to-moonbit.md Phase 1 / util.mbt.
/// Minimal superscript map used by `scientific` to render "x 10ⁿ".
/// Mirrors Python's `str.maketrans` based `_SUPERSCRIPT_TRANS`.
pub let superscript : Map[Char, Char] = {
'0': '⁰', '1': '¹', '2': '²', '3': '³', '4': '⁴',
'5': '⁵', '6': '⁶', '7': '⁷', '8': '⁸', '9': '⁹',
'-': '⁻',
}
/// Translate a string into superscript form using `superscript`.
pub fn to_superscript(s : String) -> String {
s.to_array()
.map(fn(c : Char) -> String {
match superscript.get(c) {
Some(sc) => sc.to_string()
None => c.to_string()
}
})
.join("")
}
/// Format a Double with fixed `digits` after the decimal point, rounding
/// half-up — approximating Python's `"%.Nf"`. MoonBit's `Double::to_string`
/// does not support precision specifiers, so this is a self-implemented
/// helper (known porting gap R1). A trailing ".0" is kept (callers decide
/// whether to strip it).
pub fn format_fixed(value : Double, digits : Int) -> String {
let neg = value < 0.0
let abs = if neg { -value } else { value }
if digits <= 0 {
let r = abs + 0.5
let i = @math.floor(r).to_int()
return if neg && i != 0 { "-" + i.to_string() } else { i.to_string() }
}
let scale = pow10_double(digits)
let scaled = abs * scale + 0.5
let trunc = @math.floor(scaled).to_int()
let s = trunc.to_string()
let mut int_part : String = ""
let mut frac_part : String = ""
if s.length() <= digits {
int_part = "0"
frac_part = "0".repeat(digits - s.length()) + s
} else {
int_part = s[0:s.length() - digits].to_owned()
frac_part = s[s.length() - digits:].to_owned()
}
let body = int_part + "." + frac_part
if neg {
"-" + body
} else {
body
}
}
fn pow10_double(n : Int) -> Double {
let mut r = 1.0
let mut i = 0
if n >= 0 {
while i < n {
r = r * 10.0
i = i + 1
}
} else {
while i > n {
r = r / 10.0
i = i - 1
}
}
r
}