///|
fn maxn_symmetric_bounds(lower : Double, upper : Double) -> (Double, Double) {
let first = Double::abs(lower)
let last = Double::abs(upper)
// Python max preserves the first NaN but ignores a later NaN.
let maximum = if last > first { last } else { first }
(-maximum, maximum)
}
///|
pub fn MaxNLocator::tick_values(
self : MaxNLocator,
lower : Double,
upper : Double,
) -> Array[Double] raise @core.DataError {
maxn_tick_values_with_context(self, lower, upper)
}
///|
fn maxn_tick_values_with_context(
locator : MaxNLocator,
lower : Double,
upper : Double,
raw_step_transform? : (Double) -> Double raise @core.DataError,
require_tick_space~ : Bool = false,
) -> Array[Double] raise @core.DataError {
let (lower, upper) = if locator.symmetric {
maxn_symmetric_bounds(lower, upper)
} else {
(lower, upper)
}
let (lower, upper) = locator_nonsingular(lower, upper, 1.0e-13, tiny=1.0e-14)
let grid = locator.grid(
lower,
upper,
raw_step_transform?,
require_tick_space~,
)
let first = if locator.prune == Some("lower") || locator.prune == Some("both") {
1L
} else {
0L
}
let last = if locator.prune == Some("upper") || locator.prune == Some("both") {
grid.length - 1L
} else {
grid.length
}
let length = Int64::max(0L, last - first)
let length = Int64::min(length, 100000L).to_int()
Array::makei(length, index => grid.value(first + Int64::from_int(index)))
}
///|
pub fn MaxNLocator::view_limits(
self : MaxNLocator,
lower : Double,
upper : Double,
) -> (Double, Double) raise @core.DataError {
maxn_view_limits_with_context(self, lower, upper)
}
///|
fn maxn_view_limits_with_context(
locator : MaxNLocator,
lower : Double,
upper : Double,
raw_step_transform? : (Double) -> Double raise @core.DataError,
require_tick_space~ : Bool = false,
) -> (Double, Double) raise @core.DataError {
let (lower, upper) = if locator.symmetric {
maxn_symmetric_bounds(lower, upper)
} else {
(lower, upper)
}
let (lower, upper) = locator_nonsingular(lower, upper, 1.0e-12, tiny=1.0e-13)
if @config.axes_autolimit_mode() == "round_numbers" {
let grid = locator.grid(
lower,
upper,
raw_step_transform?,
require_tick_space~,
)
if grid.length == 0L {
raise @core.DataError::InvalidTicks(
message="MaxN grid has no range endpoints",
)
}
(grid.value(0L), grid.value(grid.length - 1L))
} else {
(lower, upper)
}
}
///|
pub fn MaxNLocator::nonsingular(
_self : MaxNLocator,
lower : Double,
upper : Double,
) -> (Double, Double) {
locator_nonsingular(lower, upper, 0.05)
}
///|
pub fn MaxNLocator::call(
self : MaxNLocator,
) -> Array[Double] raise @core.DataError {
match self.view_interval_provider {
None =>
raise @core.DataError::InvalidTicks(
message="MaxN locator is not bound to a view interval",
)
Some(provider) => {
let (lower, upper) = provider()
self.tick_values(lower, upper)
}
}
}