///|
fn logit_is_decade(value : ScalarNumber) -> Bool raise @core.DataError {
  if !log_format_isfinite(value, "isfinite") {
    return false
  }
  if scalar_numeric_equal(
      value,
      ScalarNumber::Integer(@bigint.BigInt::from_int(0)),
    ) {
    return true
  }
  let magnitude = scalar_numeric_double(scalar_numeric_abs(value))
  let phase = log_grid_natural_log(magnitude) / log_grid_natural_log(10.0)
  let rounded = scalar_math_rint(phase)
  // np.isclose uses its default absolute tolerance1e-8 in addition to the
  // explicit rtol1e-7, and anchors relative tolerance on the rounded operand.
  Double::abs(phase - rounded) <= 1.0e-8 + 1.0e-7 * Double::abs(rounded)
}

///|
fn logit_is_half(
  value : ScalarNumber,
  numpy_round~ : Bool,
) -> Bool raise @core.DataError {
  let twice = scalar_numeric_op(
    ScalarNumber::Integer(@bigint.BigInt::from_int(2)),
    value,
    2,
  )
  if !log_format_close(scalar_numeric_double(twice)) {
    return false
  }
  if numpy_round {
    if twice is Integer(integer) {
      if integer < @bigint.BigInt::from_int64(-9223372036854775808L) ||
        integer > @bigint.BigInt::from_uint64(18446744073709551615UL) {
        raise log_format_error(
          "TypeError: loop of ufunc does not support argument 0 of type int which has no callable rint method",
        )
      }
      return integer == @bigint.BigInt::from_int(1)
    }
    if scalar_numeric_integral(twice) {
      return scalar_numeric_integer(twice) == @bigint.BigInt::from_int(1)
    }
    return scalar_math_rint(scalar_numeric_double(twice)) == 1.0
  }
  log_format_round(scalar_numeric_double(twice)) == @bigint.BigInt::from_int(1)
}

///|
fn logit_count_less(
  count : Int32,
  bound : LogValue,
) -> Bool raise @core.DataError {
  match bound {
    Numeric(bound) =>
      eng_prefix_less(
        ScalarNumber::Integer(@bigint.BigInt::from_int(count)),
        bound,
      )
    _ =>
      raise log_format_error(
        "TypeError: '<' not supported between instances of 'int' and '" +
        log_format_type(bound) +
        "'",
      )
  }
}

///|
fn logit_slice_start(
  number : LogValue,
  length : Int32,
) -> Int32 raise @core.DataError {
  // Unary negation precedes the index protocol. NPBool raises here; NPInt64.min
  // wraps, whereas a floating result survives negation and fails only slicing.
  let negative = log_format_negative(number)
  if !scalar_numeric_integral(negative) {
    raise log_format_error(
      "TypeError: slice indices must be integers or None or have an __index__ method",
    )
  }
  let start = scalar_numeric_integer(negative)
  let length_big = @bigint.BigInt::from_int(length)
  let start = if start < @bigint.BigInt::from_int(0) {
    length_big + start
  } else {
    start
  }
  if start <= @bigint.BigInt::from_int(0) {
    0
  } else if start >= length_big {
    length
  } else {
    start.to_int()
  }
}