evalexpr_jit/backends/vector.rs
1/// A trait for vector-like types that can be used with the JIT compiler.
2///
3/// This trait provides a common interface for different vector implementations,
4/// allowing them to be used interchangeably in JIT-compiled functions. It defines
5/// core vector operations needed for JIT compilation, including accessing raw data
6/// and creating zero-initialized vectors.
7///
8/// # Examples
9///
10/// ```rust
11/// use evalexpr_jit::prelude::Vector;
12///
13/// // Create a zero vector
14/// let vec: Vec<f64> = Vector::zeros(5);
15/// assert_eq!(vec.len(), 5);
16///
17/// // Access elements
18/// let mut vec = vec![1.0, 2.0, 3.0];
19/// let slice = vec.as_slice();
20/// assert_eq!(slice[0], 1.0);
21/// ```
22pub trait Vector {
23 /// Returns a reference to the vector's data as a slice.
24 fn as_slice(&self) -> &[f64];
25
26 /// Returns a mutable reference to the vector's data as a slice.
27 fn as_mut_slice(&mut self) -> &mut [f64];
28
29 /// Creates a new vector of the specified length filled with zeros.
30 ///
31 /// # Arguments
32 /// * `len` - The length of the vector to create
33 fn zeros(len: usize) -> Self;
34
35 /// Returns the length of the vector.
36 fn len(&self) -> usize;
37
38 /// Checks if the vector is empty.
39 fn is_empty(&self) -> bool {
40 self.len() == 0
41 }
42}
43
44/// Implementation of Vector trait for standard Vec<f64>.
45///
46/// This implementation provides an interface between the Vector trait and Rust's
47/// standard vector type. Vec<f64> already provides slice access, making this
48/// implementation straightforward.
49///
50/// # Examples
51///
52/// ```rust
53/// use evalexpr_jit::prelude::Vector;
54///
55/// let mut vec = Vec::<f64>::zeros(3);
56/// let slice = vec.as_mut_slice();
57/// slice[0] = 1.0;
58/// assert_eq!(vec[0], 1.0);
59/// ```
60impl Vector for Vec<f64> {
61 fn as_slice(&self) -> &[f64] {
62 self
63 }
64
65 fn as_mut_slice(&mut self) -> &mut [f64] {
66 self
67 }
68
69 fn zeros(len: usize) -> Self {
70 vec![0.0; len]
71 }
72
73 fn len(&self) -> usize {
74 self.len()
75 }
76}
77
78/// Implementation of Vector trait for ndarray's Array1<f64>.
79///
80/// This implementation provides an interface between the Vector trait and ndarray's
81/// 1-dimensional array type. It handles the conversion between ndarray's internal
82/// representation and the slice representation required by the JIT compiler.
83///
84/// # Examples
85///
86/// ```rust
87/// use evalexpr_jit::prelude::Vector;
88/// use ndarray::Array1;
89///
90/// let mut vec = Array1::<f64>::zeros(3);
91/// let slice = vec.as_mut_slice();
92/// slice[0] = 1.0;
93/// assert!(std::ptr::eq(slice, vec.as_slice().unwrap()));
94/// ```
95#[cfg(feature = "ndarray")]
96impl Vector for ndarray::Array1<f64> {
97 fn as_slice(&self) -> &[f64] {
98 self.as_slice().unwrap()
99 }
100
101 fn as_mut_slice(&mut self) -> &mut [f64] {
102 self.as_slice_mut().unwrap()
103 }
104
105 fn zeros(len: usize) -> Self {
106 ndarray::Array1::zeros(len)
107 }
108
109 fn len(&self) -> usize {
110 self.len()
111 }
112}
113
114/// Implementation of Vector trait for nalgebra's DVector<f64>.
115///
116/// This implementation provides an interface between the Vector trait and nalgebra's
117/// dynamic vector type. It handles the conversion between nalgebra's internal
118/// representation and the slice representation required by the JIT compiler.
119///
120/// # Examples
121///
122/// ```rust
123/// use evalexpr_jit::prelude::Vector;
124/// use nalgebra::DVector;
125///
126/// let mut vec = DVector::<f64>::zeros(3);
127/// let slice = vec.as_mut_slice();
128/// slice[0] = 1.0;
129/// assert!(std::ptr::eq(slice, vec.as_slice()));
130/// ```
131#[cfg(feature = "nalgebra")]
132impl Vector for nalgebra::DVector<f64> {
133 fn as_slice(&self) -> &[f64] {
134 self.as_slice()
135 }
136
137 fn as_mut_slice(&mut self) -> &mut [f64] {
138 self.as_mut_slice()
139 }
140
141 fn zeros(len: usize) -> Self {
142 nalgebra::DVector::zeros(len)
143 }
144
145 fn len(&self) -> usize {
146 self.len()
147 }
148}
149
150/// Implementation of Vector trait for fixed-size arrays.
151///
152/// This implementation allows fixed-size arrays to be used with the JIT compiler.
153/// The array size is specified through the const generic parameter N.
154///
155/// # Type Parameters
156/// * `N` - The fixed size of the array
157///
158/// # Examples
159///
160/// ```rust
161/// use evalexpr_jit::prelude::Vector;
162///
163/// let mut arr = <[f64; 3]>::zeros(3);
164/// let slice = arr.as_mut_slice();
165/// slice[0] = 1.0;
166/// assert_eq!(arr[0], 1.0);
167/// ```
168impl<const N: usize> Vector for [f64; N] {
169 fn as_slice(&self) -> &[f64] {
170 self
171 }
172
173 fn as_mut_slice(&mut self) -> &mut [f64] {
174 self
175 }
176
177 fn zeros(len: usize) -> Self {
178 assert_eq!(len, N, "Array length must match const generic size");
179 [0.0; N]
180 }
181
182 fn len(&self) -> usize {
183 N
184 }
185}