///|
fn log_format_trim(value : String) -> String {
  let characters = value.to_array()
  let mut last = characters.length()
  while last > 0 && characters[last - 1] == '0' {
    last -= 1
  }
  if last > 0 && characters[last - 1] == '.' {
    last -= 1
  }
  String::from_array(characters[:last])
}

///|
fn log_format_pretty(
  value : ScalarNumber,
  delta : Double,
) -> String raise @core.DataError {
  if scalar_numeric_less(
      scalar_numeric_abs(value),
      ScalarNumber::Integer(@bigint.BigInt::from_int(10000)),
    ) {
    let integer = scalar_numeric_integer(value)
    if scalar_numeric_equal(value, ScalarNumber::Integer(integer)) {
      return scalar_percent_format("%d", value)
    }
  }
  let format = if delta < 1.0e-2 {
    "%1.3e"
  } else if delta <= 1.0 {
    "%1.3f"
  } else if delta <= 10.0 {
    "%1.2f"
  } else if delta <= 1.0e5 {
    "%1.1f"
  } else {
    "%1.1e"
  }
  let text = scalar_percent_format(format, value)
  let chars = text.to_array()
  let mut split = -1
  for index in 0..= 0 {
    let mantissa = log_format_trim(String::from_array(chars[:split]))
    let exponent = percent_precision_text_integer(
      String::from_array(chars[split + 1:]),
    )
    if exponent.is_zero() {
      mantissa
    } else {
      mantissa + "e" + scalar_percent_integer_str(exponent)
    }
  } else {
    log_format_trim(text)
  }
}

///|
fn log_format_view(
  base : BaseFormatter,
) -> (Double, Double) raise @core.DataError {
  let (lower, upper) = scalar_numeric_view(base)
  if !log_format_isfinite(lower, "isfinite") ||
    !log_format_isfinite(upper, "isfinite") {
    return (-0.05, 0.05)
  }
  locator_nonsingular(
    scalar_numeric_double(lower),
    scalar_numeric_double(upper),
    0.05,
  )
}

///|
fn log_named_call(
  base : BaseFormatter,
  state : LogFormatterState,
  value : ScalarNumber,
  _pos : Int32?,
) -> String raise @core.DataError {
  let mathtext = state.style is (Mathtext | SciNotation)
  let zero = ScalarNumber::Integer(@bigint.BigInt::from_int(0))
  if scalar_numeric_equal(value, zero) {
    return if mathtext { "$\\mathdefault{0}$" } else { "0" }
  }
  let sign = if mathtext && scalar_numeric_less(value, zero) { "-" } else { "" }
  let value = scalar_numeric_abs(value)
  let fx = log_format_log(value, state.base)
  let decade = log_format_close(fx)
  let exponent = if decade {
    ScalarNumber::Integer(log_format_round(fx))
  } else {
    ScalarNumber::NumpyFloat64(fx.floor())
  }
  let coefficient = log_format_round(
    log_format_power(
      state.base,
      scalar_numeric_op(ScalarNumber::Number(fx), exponent, 1),
    ),
  )
  if log_value_truth(state.label_only_base) && !decade {
    return ""
  }
  if state.sublabels is Some(cache) &&
    !log_cache_contains(cache, index_round_binary(coefficient, 0)) {
    return ""
  }
  if !mathtext {
    let (lower, upper) = log_format_view(base)
    let text = if state.style is Exponent {
      let fx = log_format_log(value, state.base)
      if Double::abs(fx) >= 1.0 && Double::abs(fx) <= 10000.0 {
        let delta = log_format_log(
          ScalarNumber::Number(upper - lower),
          state.base,
        )
        log_format_pretty(ScalarNumber::Number(fx), delta)
      } else {
        method_format_float(fx, method_parse_spec("1.0g", "float"))
      }
    } else if !scalar_numeric_less(
        value,
        ScalarNumber::Integer(@bigint.BigInt::from_int(1)),
      ) &&
      !scalar_numeric_less(
        ScalarNumber::Integer(@bigint.BigInt::from_int(10000)),
        value,
      ) {
      log_format_pretty(value, upper - lower)
    } else {
      method_format_float(
        scalar_numeric_double(value),
        method_parse_spec("1.0e", "float"),
      )
    }
    return BaseFormatter::fix_minus(text)
  }
  let phase = if decade {
    ScalarNumber::Integer(log_format_round(fx))
  } else {
    ScalarNumber::Number(fx)
  }
  let base_text = scalar_percent_format(
    if state.base % 1.0 == 0.0 {
      "%d"
    } else {
      "%s"
    },
    ScalarNumber::Number(state.base),
  )
  if scalar_numeric_less(
      scalar_numeric_abs(phase),
      ScalarNumber::Integer(@config.formatter_min_exponent()),
    ) {
    return "$\\mathdefault{" + sign + scalar_percent_format("%g", value) + "}$"
  }
  if decade {
    return "$\\mathdefault{" +
      sign +
      base_text +
      "^{" +
      scalar_percent_format("%d", phase) +
      "}}$"
  }
  // The source reads this live setting before the virtual non-decade method.
  ignore(@config.text_usetex())
  if state.style is Mathtext {
    return "$\\mathdefault{" +
      sign +
      base_text +
      "^{" +
      scalar_percent_format("%.2f", phase) +
      "}}$"
  }
  let exponent = scalar_numeric_floor(fx)
  let exponent_value = ScalarNumber::Integer(exponent)
  let b = log_text_float(base_text)
  let coeff = log_format_power(
    b,
    scalar_numeric_op(ScalarNumber::Number(fx), exponent_value, 1),
  )
  let coeff = if log_format_close(coeff) {
    ScalarNumber::Integer(log_format_round(coeff))
  } else {
    ScalarNumber::Number(coeff)
  }
  "$\\mathdefault{" +
  sign +
  scalar_percent_format("%g", coeff) +
  "\\times" +
  base_text +
  "^{" +
  scalar_percent_integer_str(exponent) +
  "}}$"
}

///|
fn log_format_replace(
  text : String,
  token : String,
  replacement : String,
) -> String {
  let chars = text.to_array()
  let find = token.to_array()
  let out = StringBuilder()
  let mut index = 0
  while index < chars.length() {
    let mut matches = index + find.length() <= chars.length()
    if matches {
      for offset in 0.. String raise @core.DataError {
  let previous = state.label_only_base
  state.label_only_base = LogValue::Numeric(ScalarNumber::Boolean(false))
  defer {
    state.label_only_base = previous
  }
  let text = log_named_call(base, state, value, None)
  let chars = text.to_array()
  if chars.length() < 2 || chars[0] != '$' || chars[chars.length() - 1] != '$' {
    return text
  }
  let mut text = String::from_array(chars[1:chars.length() - 1])
  for
    (token, replacement) in [
      ("\\times", "x"),
      ("\\mathdefault", ""),
      ("\\rm", ""),
      ("\\cal", ""),
      ("\\tt", ""),
      ("\\it", ""),
      ("\\", ""),
      ("{", ""),
      ("}", ""),
    ] {
    text = log_format_replace(text, token, replacement)
  }
  text
}

///|
fn log_named_short(value : ScalarNumber) -> String raise @core.DataError {
  let text = scalar_percent_format("%-12g", value)
  let chars = text.to_array()
  let mut last = chars.length()
  while last > 0 && chars[last - 1] == ' ' {
    last -= 1
  }
  String::from_array(chars[:last])
}