axonml_core/error.rs
1//! Error types for the AxonML core crate.
2//!
3//! `Error` enum covers ShapeMismatch, DTypeMismatch, DeviceMismatch,
4//! InvalidDimension, IndexOutOfBounds, AllocationFailed, DeviceNotAvailable,
5//! InvalidOperation, BroadcastError, EmptyTensor, NotContiguous,
6//! GradientError, SerializationError, and InternalError. `Result<T>` alias
7//! is the standard return type for fallible tensor/device operations.
8//!
9//! # File
10//! `crates/axonml-core/src/error.rs`
11//!
12//! # Author
13//! Andrew Jewell Sr. — AutomataNexus LLC
14//! ORCID: 0009-0005-2158-7060
15//!
16//! # Updated
17//! April 14, 2026 11:15 PM EST
18//!
19//! # Disclaimer
20//! Use at own risk. This software is provided "as is", without warranty of any
21//! kind, express or implied. The author and AutomataNexus shall not be held
22//! liable for any damages arising from the use of this software.
23
24use thiserror::Error;
25
26use crate::device::Device;
27use crate::dtype::DType;
28
29// =============================================================================
30// Error Types
31// =============================================================================
32
33/// The main error type for Axonml operations.
34#[derive(Error, Debug, Clone, PartialEq)]
35pub enum Error {
36 /// Shape mismatch between tensors.
37 #[error("Shape mismatch: expected {expected:?}, got {actual:?}")]
38 ShapeMismatch {
39 /// The expected shape.
40 expected: Vec<usize>,
41 /// The actual shape.
42 actual: Vec<usize>,
43 },
44
45 /// Data type mismatch between tensors.
46 #[error("DType mismatch: expected {expected:?}, got {actual:?}")]
47 DTypeMismatch {
48 /// The expected data type.
49 expected: DType,
50 /// The actual data type.
51 actual: DType,
52 },
53
54 /// Device mismatch between tensors.
55 #[error("Device mismatch: expected {expected:?}, got {actual:?}")]
56 DeviceMismatch {
57 /// The expected device.
58 expected: Device,
59 /// The actual device.
60 actual: Device,
61 },
62
63 /// Invalid dimension index.
64 #[error("Invalid dimension: index {index} for tensor with {ndim} dimensions")]
65 InvalidDimension {
66 /// The invalid dimension index.
67 index: i64,
68 /// Number of dimensions in the tensor.
69 ndim: usize,
70 },
71
72 /// Index out of bounds.
73 #[error("Index out of bounds: index {index} for dimension of size {size}")]
74 IndexOutOfBounds {
75 /// The invalid index.
76 index: usize,
77 /// The size of the dimension.
78 size: usize,
79 },
80
81 /// Memory allocation failed.
82 #[error("Memory allocation failed: requested {size} bytes on {device:?}")]
83 AllocationFailed {
84 /// The requested size in bytes.
85 size: usize,
86 /// The device on which allocation failed.
87 device: Device,
88 },
89
90 /// Device not available.
91 #[error("Device not available: {device:?}")]
92 DeviceNotAvailable {
93 /// The unavailable device.
94 device: Device,
95 },
96
97 /// Invalid operation for the given tensor.
98 #[error("Invalid operation: {message}")]
99 InvalidOperation {
100 /// Description of why the operation is invalid.
101 message: String,
102 },
103
104 /// Broadcasting failed between shapes.
105 #[error("Cannot broadcast shapes {shape1:?} and {shape2:?}")]
106 BroadcastError {
107 /// The first shape.
108 shape1: Vec<usize>,
109 /// The second shape.
110 shape2: Vec<usize>,
111 },
112
113 /// Empty tensor error.
114 #[error("Operation not supported on empty tensor")]
115 EmptyTensor,
116
117 /// Contiguous tensor required.
118 #[error("Operation requires contiguous tensor")]
119 NotContiguous,
120
121 /// Gradient computation error.
122 #[error("Gradient error: {message}")]
123 GradientError {
124 /// Description of the gradient error.
125 message: String,
126 },
127
128 /// Serialization/deserialization error.
129 #[error("Serialization error: {message}")]
130 SerializationError {
131 /// Description of the serialization error.
132 message: String,
133 },
134
135 /// Internal error (should not happen).
136 #[error("Internal error: {message}")]
137 InternalError {
138 /// Description of the internal error.
139 message: String,
140 },
141}
142
143// =============================================================================
144// Result Type
145// =============================================================================
146
147/// A specialized Result type for Axonml operations.
148pub type Result<T> = core::result::Result<T, Error>;
149
150// =============================================================================
151// Helper Functions
152// =============================================================================
153
154impl Error {
155 /// Creates a new shape mismatch error.
156 #[must_use]
157 pub fn shape_mismatch(expected: &[usize], actual: &[usize]) -> Self {
158 Self::ShapeMismatch {
159 expected: expected.to_vec(),
160 actual: actual.to_vec(),
161 }
162 }
163
164 /// Creates a new invalid operation error.
165 #[must_use]
166 pub fn invalid_operation(message: impl Into<String>) -> Self {
167 Self::InvalidOperation {
168 message: message.into(),
169 }
170 }
171
172 /// Creates a new internal error.
173 #[must_use]
174 pub fn internal(message: impl Into<String>) -> Self {
175 Self::InternalError {
176 message: message.into(),
177 }
178 }
179}
180
181// =============================================================================
182// Tests
183// =============================================================================
184
185#[cfg(test)]
186mod tests {
187 use super::*;
188
189 #[test]
190 fn test_error_display() {
191 let err = Error::shape_mismatch(&[2, 3], &[2, 4]);
192 assert!(err.to_string().contains("Shape mismatch"));
193 }
194
195 #[test]
196 fn test_error_equality() {
197 let err1 = Error::EmptyTensor;
198 let err2 = Error::EmptyTensor;
199 assert_eq!(err1, err2);
200 }
201}