///|
/// Percentage formatting with viewport-aware automatic precision.
///|
fn format_percent_values(
values : Array[Double],
xmax : Double,
decimals : Int32,
symbol : String,
view : @core.Limits?,
) -> Array[String] {
let (minimum, maximum) = formatter_extent(values, view)
let display_range = maximum - minimum
values.map(value => {
format_percent(value, xmax, decimals, symbol, display_range)
})
}
///|
fn format_percent(
value : Double,
xmax : Double,
decimals : Int32,
symbol : String,
display_range : Double,
) -> String {
let percentage = 100.0 * value / xmax
let digits = if decimals >= 0 {
decimals
} else {
let scaled_range = 100.0 * Double::abs(display_range) / Double::abs(xmax)
if scaled_range <= 0.0 || scaled_range.is_nan() || scaled_range.is_inf() {
0
} else {
Int32::max(
0,
Int32::min(5, (2.0 - @math.log10(2.0 * scaled_range)).ceil().to_int()),
)
}
}
format_fixed(percentage, digits) + symbol
}