///|
// Evaluate the original ndarray complement before entering _format_value.
// The fresh inherited locations container is a Python list, not an ndarray.
fn logit_array_complement(
locations : FormatterLocations,
) -> FormatterLocations raise @core.DataError {
match locations {
Sequence(_) | Integers(_) =>
raise log_format_error(
"TypeError: unsupported operand type(s) for -: 'int' and 'list'",
)
NdArray(values) =>
if values.is_int64() {
let result : Array[Int64] = []
for index in 0..
match array.storage {
Boolean(values) =>
FormatterLocations::NdArray(
TickValues::from_int64_array(
values.map(value => if value { 0L } else { 1L }),
),
)
Unsigned64(values) =>
FormatterLocations::Typed({
storage: NumericArrayStorage::Unsigned64(
values.map(value => 1UL - value),
),
})
Objects(values) => {
let result : Array[ScalarNumber] = []
for value in values {
result.push(
scalar_numeric_op(
ScalarNumber::Integer(@bigint.BigInt::from_int(1)),
value,
1,
),
)
}
FormatterLocations::Typed({
storage: NumericArrayStorage::Objects(result),
})
}
}
}
}
///|
fn logit_array_second_distance(
locations : FormatterLocations,
value : ScalarNumber,
) -> Double raise @core.DataError {
let x = scalar_numeric_double(value)
let distances : Array[Double] = []
match locations {
Sequence(values) => {
if !scalar_numeric_numpy(value) {
raise log_format_error(
"TypeError: unsupported operand type(s) for -: 'list' and 'float'",
)
}
for other in values {
distances.push(Double::abs(other - x))
}
}
Integers(values) => {
if !scalar_numeric_numpy(value) {
let kind = if value is Integer(_) { "int" } else { "float" }
raise log_format_error(
"TypeError: unsupported operand type(s) for -: 'list' and '" +
kind +
"'",
)
}
let input = LogitInput::from_keys(
values.map(value => LogitKey::new(ScalarNumber::Integer(value))),
).snapshot()
for index in 0..
for index in 0..
match array.storage {
Boolean(values) =>
for other in values {
distances.push(Double::abs((if other { 1.0 } else { 0.0 }) - x))
}
Unsigned64(values) =>
for other in values {
distances.push(Double::abs(other.to_double() - x))
}
Objects(values) => {
// Object ufunc loops complete subtraction before the absolute pass.
// A floating ufunc scalar is boxed as a Python float in this loop.
let subtracted : Array[ScalarNumber] = []
for other in values {
subtracted.push(
scalar_numeric_op(other, ScalarNumber::Number(x), 1),
)
}
let absolute : Array[ScalarNumber] = subtracted.map(
scalar_numeric_abs,
)
// Object quicksort uses partial Python comparison, including NaNs.
// Its second rank is not the numeric NaN-last rank below.
let sorted = logit_object_sort(absolute)
return scalar_numeric_double(sorted[1])
}
}
}
// np.sort places NaNs after numeric values. Only the second rank is needed;
// consume every arithmetic result before this scan, preserving late errors.
let mut first = 0.0 / 0.0
let mut second = 0.0 / 0.0
for distance in distances {
if !distance.is_nan() {
if first.is_nan() || distance < first {
second = first
first = distance
} else if second.is_nan() || distance < second {
second = distance
}
}
}
second
}
///|
fn logit_array_logits(
locations : FormatterLocations,
) -> Array[Double] raise @core.DataError {
let values : Array[Double] = []
match locations {
Sequence(_) | Integers(_) =>
raise log_format_error(
"TypeError: unsupported operand type(s) for /: 'int' and 'list'",
)
NdArray(array) =>
for index in 0..
match array.storage {
Boolean(array) =>
for value in array {
values.push(if value { 1.0 } else { 0.0 })
}
Unsigned64(array) =>
for value in array {
values.push(value.to_double())
}
Objects(array) => {
let reciprocals : Array[ScalarNumber] = []
for value in array {
reciprocals.push(
scalar_numeric_op(
ScalarNumber::Integer(@bigint.BigInt::from_int(1)),
value,
3,
),
)
}
let arguments : Array[ScalarNumber] = []
for value in reciprocals {
arguments.push(
scalar_numeric_op(
value,
ScalarNumber::Integer(@bigint.BigInt::from_int(1)),
1,
),
)
}
if arguments.length() > 0 {
let name = if scalar_numeric_numpy(arguments[0]) {
"numpy.float64"
} else {
"float"
}
raise log_format_error(
"TypeError: loop of ufunc does not support argument 0 of type " +
name +
" which has no callable log method",
)
}
return []
}
}
}
// Preserve reciprocal, subtract, NumPy ln, unary negative as separate rounded
// operations. A stable analytic logit transform has different source behavior.
let reciprocals = values.map(value => 1.0 / value)
let arguments = reciprocals.map(value => value - 1.0)
let logs = arguments.map(log_grid_natural_log)
logs.map(value => -value)
}