use std::fmt::Display;
#[allow(dead_code)]
pub fn dimension_mismatch(operation: &str, expected: impl Display, actual: impl Display) -> String {
format!("{operation}: dimension mismatch (expected: {expected}, actual: {actual})")
}
#[allow(dead_code)]
pub fn shape_mismatch(operation: &str, shape1: &[usize], shape2: &[usize]) -> String {
format!("{operation}: incompatible shapes ({shape1:?} vs {shape2:?})")
}
#[allow(dead_code)]
pub fn value(param_name: &str, constraint: &str, actualvalue: impl Display) -> String {
format!("Parameter '{param_name}': {constraint} (got: {actualvalue})")
}
#[allow(dead_code)]
pub fn index(index: usize, length: usize) -> String {
format!("Index out of bounds: index {index} is invalid for length {length}")
}
#[allow(dead_code)]
pub fn empty_input(operation: &str) -> String {
format!("{operation}: input array/collection is empty")
}
#[allow(dead_code)]
pub fn numericalerror(operation: &str, issue: &str) -> String {
format!("{operation}: {issue} - check input values for numerical issues")
}
#[allow(dead_code)]
pub fn algorithm(algorithm: &str, iterations: usize, tolerance: impl Display) -> String {
format!(
"{algorithm}: failed to converge after {iterations} iterations (tolerance: {tolerance})"
)
}
#[allow(dead_code)]
pub fn feature(feature: &str) -> String {
format!("Feature not implemented: {feature}")
}
#[allow(dead_code)]
pub fn dims(operation: &str, requirement: &str, actualdims: &[usize]) -> String {
format!("{operation}: {requirement} (got: {actualdims:?})")
}
#[allow(dead_code)]
pub fn desc(valuedesc: &str, constraint: &str, value: impl Display) -> String {
format!("{valuedesc} must be {constraint} (got: {value})")
}
#[allow(dead_code)]
pub fn allocationerror(size: usize, elementtype: &str) -> String {
format!("Failed to allocate memory for {size} elements of type {elementtype}")
}
#[allow(dead_code)]
pub fn ioerror(operation: &str, path: &str, details: &str) -> String {
format!("{operation} failed for '{path}': {details}")
}
#[allow(dead_code)]
pub fn parseerror(typename: &str, input: &str, reason: &str) -> String {
format!("Failed to parse '{input}' as {typename}: {reason}")
}
#[allow(dead_code)]
pub fn state(object: &str, expected_state: &str, actualstate: &str) -> String {
format!("{object} is in invalid state: expected {expected_state}, but was {actualstate}")
}
#[allow(dead_code)]
pub fn msg(errormsg: &str, suggestion: &str) -> String {
format!("{errormsg}\nSuggestion: {suggestion}")
}
pub mod constraints {
pub fn positive() -> &'static str {
"must be positive (> 0)"
}
pub fn non_negative() -> &'static str {
"must be non-negative (>= 0)"
}
pub fn probability() -> &'static str {
"must be a valid probability in [0, 1]"
}
pub fn finite() -> &'static str {
"must be finite (not NaN or infinite)"
}
pub fn non_empty() -> &'static str {
"must not be empty"
}
pub fn squarematrix() -> &'static str {
"must be a square matrix"
}
pub fn positive_definite() -> &'static str {
"must be a positive definite matrix"
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_dimension_mismatch() {
let msg = dimension_mismatch("matrix multiplication", "3x4", "5x3");
assert_eq!(
msg,
"matrix multiplication: dimension mismatch (expected: 3x4, actual: 5x3)"
);
}
#[test]
fn testshape_mismatch() {
let msg = shape_mismatch("element-wise operation", &[3, 4], &[3, 5]);
assert_eq!(
msg,
"element-wise operation: incompatible shapes ([3, 4] vs [3, 5])"
);
}
}