///|
/// Raw standard scalar inputs retain their Python and NumPy origin.
pub(all) enum LogValue {
Numeric(ScalarNumber)
Text(String)
NoneValue
} derive(Debug, Eq)
///|
pub extend LogValue with @debug.Debug::{to_repr}
///|
pub extend LogValue with Eq::{equal, not_equal}
///|
/// An immutable numeric/text tuple. Construction and values() copy their arrays.
pub struct LogThresholdTuple {
priv items : Array[LogValue]
}
///|
pub impl @debug.Debug for LogThresholdTuple with fn to_repr(self) {
@debug.Repr::Repr(("LogThresholdTuple", self.items))
}
///|
pub extend LogThresholdTuple with @debug.Debug::{to_repr}
///|
pub impl Eq for LogThresholdTuple with fn equal(self, other) {
physical_equal(self, other)
}
///|
pub extend LogThresholdTuple with Eq::{equal, not_equal}
///|
pub fn LogThresholdTuple::new(values : Array[LogValue]) -> LogThresholdTuple {
{ items: values.copy(), }
}
///|
pub fn LogThresholdTuple::length(self : LogThresholdTuple) -> Int32 {
self.items.length()
}
///|
pub fn LogThresholdTuple::values(self : LogThresholdTuple) -> Array[LogValue] {
self.items.copy()
}
///|
pub fn LogThresholdTuple::get(
self : LogThresholdTuple,
index : Int32,
) -> LogValue raise @core.DataError {
let normalized = if index < 0 {
Int64::from_int(self.items.length()) + Int64::from_int(index)
} else {
Int64::from_int(index)
}
if normalized < 0L || normalized >= Int64::from_int(self.items.length()) {
raise @core.DataError::InvalidTicks(
message="IndexError: tuple index out of range",
)
}
self.items[normalized.to_int()]
}
///|
/// Preserve an immutable tuple, a borrowed list/view, or a raw scalar slot.
pub(all) enum LogMinorThresholds {
Tuple(LogThresholdTuple)
Sequence(Array[LogValue])
NdArray(TickValues)
Raw(LogValue)
}
///|
pub impl @debug.Debug for LogMinorThresholds with fn to_repr(self) {
match self {
Tuple(values) => @debug.Repr::Repr(("Tuple", values))
Sequence(values) => @debug.Repr::Repr(("Sequence", values))
NdArray(values) => @debug.Repr::Repr(("NdArray length", values.length()))
Raw(value) => @debug.Repr::Repr(("Raw", value))
}
}
///|
pub extend LogMinorThresholds with @debug.Debug::{to_repr}
///|
fn log_value_truth(value : LogValue) -> Bool {
match value {
NoneValue => false
Text(value) => !value.is_empty()
Numeric(value) => scalar_numeric_truth(Some(value))
}
}
///|
fn log_base_float(value : LogValue) -> Double raise @core.DataError {
match value {
Numeric(value) => scalar_numeric_double(value)
Text(value) => log_text_float(value)
NoneValue =>
raise @core.DataError::InvalidTicks(
message="TypeError: float() argument must be a string or a real number, not 'NoneType'",
)
}
}
///|
fn log_threshold_at(
thresholds : LogMinorThresholds?,
index : Int32,
) -> LogValue raise @core.DataError {
match thresholds {
None =>
raise @core.DataError::InvalidTicks(
message="TypeError: 'NoneType' object is not subscriptable",
)
Some(Tuple(values)) => values.get(index)
Some(Sequence(values)) => {
let normalized = if index < 0 {
Int64::from_int(values.length()) + Int64::from_int(index)
} else {
Int64::from_int(index)
}
if normalized < 0L || normalized >= Int64::from_int(values.length()) {
raise @core.DataError::InvalidTicks(
message="IndexError: list index out of range",
)
}
values[normalized.to_int()]
}
Some(NdArray(values)) => {
let length = values.length()
let normalized = if index < 0 {
Int64::from_int(length) + Int64::from_int(index)
} else {
Int64::from_int(index)
}
if normalized < 0L || normalized >= Int64::from_int(length) {
raise @core.DataError::InvalidTicks(
message="IndexError: index " +
index.to_string() +
" is out of bounds for axis 0 with size " +
length.to_string(),
)
}
Numeric(
if values.is_int64() {
ScalarNumber::NumpyInt64(values.get_int64(index))
} else {
ScalarNumber::NumpyFloat64(values.get(index))
},
)
}
Some(Raw(Text(text))) => {
let characters = text.to_array()
let normalized = if index < 0 {
Int64::from_int(characters.length()) + Int64::from_int(index)
} else {
Int64::from_int(index)
}
if normalized < 0L || normalized >= Int64::from_int(characters.length()) {
raise @core.DataError::InvalidTicks(
message="IndexError: string index out of range",
)
}
Text(characters[normalized.to_int()].to_string())
}
Some(Raw(NoneValue)) =>
raise @core.DataError::InvalidTicks(
message="TypeError: 'NoneType' object is not subscriptable",
)
Some(Raw(Numeric(NumpyFloat64(_) | NumpyInt64(_) | NumpyBool(_)))) =>
raise @core.DataError::InvalidTicks(
message="IndexError: invalid index to scalar variable.",
)
Some(Raw(Numeric(value))) => {
let kind = match value {
Number(_) => "float"
Boolean(_) => "bool"
_ => "int"
}
raise @core.DataError::InvalidTicks(
message="TypeError: '" + kind + "' object is not subscriptable",
)
}
}
}