Skip to main content

numeris/dynmatrix/
vector.rs

1use alloc::vec::Vec;
2use core::ops::{Index, IndexMut};
3
4use crate::matrix::vector::Vector;
5use crate::traits::{MatrixMut, MatrixRef, Scalar};
6
7use super::DynMatrix;
8
9/// Dynamically-sized vector (wraps a 1×N `DynMatrix`).
10///
11/// Enforces single-row constraint and provides single-index access `v[i]`.
12///
13/// # Examples
14///
15/// ```
16/// use numeris::DynVector;
17///
18/// let v = DynVector::from_slice(&[1.0_f64, 2.0, 3.0]);
19/// assert_eq!(v[0], 1.0);
20/// assert_eq!(v.len(), 3);
21/// assert!((v.dot(&v) - 14.0).abs() < 1e-12);
22/// ```
23#[derive(Debug, Clone, PartialEq)]
24pub struct DynVector<T> {
25    pub(crate) inner: DynMatrix<T>,
26}
27
28impl<T: Scalar> DynVector<T> {
29    /// Create a vector from a flat slice.
30    ///
31    /// ```
32    /// use numeris::DynVector;
33    /// let v = DynVector::from_slice(&[1.0, 2.0, 3.0]);
34    /// assert_eq!(v[0], 1.0);
35    /// assert_eq!(v.len(), 3);
36    /// ```
37    pub fn from_slice(data: &[T]) -> Self {
38        Self {
39            inner: DynMatrix::from_slice(1, data.len(), data),
40        }
41    }
42
43    /// Create a vector from an owned `Vec`.
44    ///
45    /// ```
46    /// use numeris::DynVector;
47    /// let v = DynVector::from_vec(vec![1.0, 2.0, 3.0]);
48    /// assert_eq!(v[2], 3.0);
49    /// ```
50    pub fn from_vec(data: Vec<T>) -> Self {
51        let n = data.len();
52        Self {
53            inner: DynMatrix::from_vec(1, n, data),
54        }
55    }
56
57    /// Create a zero vector of length `n`.
58    ///
59    /// ```
60    /// use numeris::DynVector;
61    /// let v = DynVector::zeros(4, 0.0_f64);
62    /// assert_eq!(v.len(), 4);
63    /// assert_eq!(v[3], 0.0);
64    /// ```
65    pub fn zeros(n: usize, _zero: T) -> Self {
66        Self {
67            inner: DynMatrix::zeros(1, n, T::zero()),
68        }
69    }
70
71    /// Create a vector filled with a value.
72    pub fn fill(n: usize, value: T) -> Self {
73        Self {
74            inner: DynMatrix::fill(1, n, value),
75        }
76    }
77
78    /// Number of elements.
79    #[inline]
80    pub fn len(&self) -> usize {
81        self.inner.ncols()
82    }
83
84    /// Whether the vector is empty.
85    #[inline]
86    pub fn is_empty(&self) -> bool {
87        self.len() == 0
88    }
89
90    /// Dot product.
91    ///
92    /// ```
93    /// use numeris::DynVector;
94    /// let a = DynVector::from_slice(&[1.0, 2.0, 3.0]);
95    /// let b = DynVector::from_slice(&[4.0, 5.0, 6.0]);
96    /// assert_eq!(a.dot(&b), 32.0);
97    /// ```
98    pub fn dot(&self, rhs: &Self) -> T {
99        assert_eq!(self.len(), rhs.len(), "vector length mismatch");
100        crate::simd::dot_dispatch(self.as_slice(), rhs.as_slice())
101    }
102
103    /// Cast every element to a different numeric type.
104    ///
105    /// ```
106    /// use numeris::DynVector;
107    /// let v = DynVector::from_slice(&[1.0_f64, 2.0, 3.0]);
108    /// let v32: DynVector<f32> = v.cast();
109    /// assert_eq!(v32[0], 1.0_f32);
110    /// ```
111    pub fn cast<U: Scalar + num_traits::NumCast>(&self) -> DynVector<U>
112    where
113        T: num_traits::ToPrimitive,
114    {
115        DynVector {
116            inner: self.inner.cast(),
117        }
118    }
119
120    /// View the vector data as a slice.
121    #[inline]
122    pub fn as_slice(&self) -> &[T] {
123        self.inner.as_slice()
124    }
125
126    /// View the vector data as a mutable slice.
127    #[inline]
128    pub fn as_mut_slice(&mut self) -> &mut [T] {
129        self.inner.as_mut_slice()
130    }
131}
132
133// ── Index ───────────────────────────────────────────────────────────
134
135impl<T> Index<usize> for DynVector<T> {
136    type Output = T;
137
138    #[inline]
139    fn index(&self, i: usize) -> &T {
140        &self.inner[(0, i)]
141    }
142}
143
144impl<T> IndexMut<usize> for DynVector<T> {
145    #[inline]
146    fn index_mut(&mut self, i: usize) -> &mut T {
147        &mut self.inner[(0, i)]
148    }
149}
150
151// ── MatrixRef / MatrixMut ───────────────────────────────────────────
152
153impl<T> MatrixRef<T> for DynVector<T> {
154    #[inline]
155    fn nrows(&self) -> usize {
156        1
157    }
158
159    #[inline]
160    fn ncols(&self) -> usize {
161        self.inner.ncols()
162    }
163
164    #[inline]
165    fn get(&self, row: usize, col: usize) -> &T {
166        self.inner.get(row, col)
167    }
168
169    #[inline]
170    fn col_as_slice(&self, col: usize, row_start: usize) -> &[T] {
171        self.inner.col_as_slice(col, row_start)
172    }
173}
174
175impl<T> MatrixMut<T> for DynVector<T> {
176    #[inline]
177    fn get_mut(&mut self, row: usize, col: usize) -> &mut T {
178        self.inner.get_mut(row, col)
179    }
180
181    #[inline]
182    fn col_as_mut_slice(&mut self, col: usize, row_start: usize) -> &mut [T] {
183        self.inner.col_as_mut_slice(col, row_start)
184    }
185}
186
187// ── Conversions: Vector ↔ DynVector ─────────────────────────────────
188
189impl<T: Scalar, const N: usize> From<Vector<T, N>> for DynVector<T> {
190    /// Convert a fixed-size `Vector` into a `DynVector`.
191    ///
192    /// ```
193    /// use numeris::{Vector, DynVector};
194    /// let v = Vector::from_array([1.0, 2.0, 3.0]);
195    /// let dv: DynVector<f64> = v.into();
196    /// assert_eq!(dv.len(), 3);
197    /// assert_eq!(dv[0], 1.0);
198    /// ```
199    fn from(v: Vector<T, N>) -> Self {
200        Self {
201            inner: DynMatrix::from(v),
202        }
203    }
204}
205
206impl<T: Scalar, const N: usize> From<&Vector<T, N>> for DynVector<T> {
207    fn from(v: &Vector<T, N>) -> Self {
208        Self {
209            inner: DynMatrix::from(v),
210        }
211    }
212}
213
214impl<T: Scalar> From<DynVector<T>> for DynMatrix<T> {
215    fn from(v: DynVector<T>) -> Self {
216        v.inner
217    }
218}
219
220impl<T: Scalar> From<&DynVector<T>> for DynMatrix<T> {
221    fn from(v: &DynVector<T>) -> Self {
222        v.inner.clone()
223    }
224}
225
226#[cfg(test)]
227mod tests {
228    use super::*;
229    use crate::Vector;
230
231    #[test]
232    fn from_slice() {
233        let v = DynVector::from_slice(&[1.0, 2.0, 3.0]);
234        assert_eq!(v.len(), 3);
235        assert_eq!(v[0], 1.0);
236        assert_eq!(v[2], 3.0);
237    }
238
239    #[test]
240    fn from_vec() {
241        let v = DynVector::from_vec(vec![10.0, 20.0]);
242        assert_eq!(v.len(), 2);
243        assert_eq!(v[1], 20.0);
244    }
245
246    #[test]
247    fn zeros() {
248        let v = DynVector::zeros(4, 0.0_f64);
249        assert_eq!(v.len(), 4);
250        for i in 0..4 {
251            assert_eq!(v[i], 0.0);
252        }
253    }
254
255    #[test]
256    fn index_mut() {
257        let mut v = DynVector::zeros(3, 0.0_f64);
258        v[1] = 42.0;
259        assert_eq!(v[1], 42.0);
260    }
261
262    #[test]
263    fn dot_product() {
264        let a = DynVector::from_slice(&[1.0, 2.0, 3.0]);
265        let b = DynVector::from_slice(&[4.0, 5.0, 6.0]);
266        assert_eq!(a.dot(&b), 32.0);
267    }
268
269    #[test]
270    fn from_fixed_vector() {
271        let v = Vector::from_array([1.0, 2.0, 3.0]);
272        let dv: DynVector<f64> = v.into();
273        assert_eq!(dv.len(), 3);
274        assert_eq!(dv[0], 1.0);
275        assert_eq!(dv[2], 3.0);
276    }
277
278    #[test]
279    fn matrix_ref_trait() {
280        let v = DynVector::from_slice(&[1.0, 2.0, 3.0]);
281        assert_eq!(v.nrows(), 1);
282        assert_eq!(v.ncols(), 3);
283        assert_eq!(*v.get(0, 1), 2.0);
284    }
285
286    #[test]
287    fn as_slice() {
288        let v = DynVector::from_slice(&[1.0, 2.0, 3.0]);
289        assert_eq!(v.as_slice(), &[1.0, 2.0, 3.0]);
290    }
291
292    #[test]
293    fn into_dynmatrix() {
294        let v = DynVector::from_slice(&[1.0, 2.0, 3.0]);
295        let m: DynMatrix<f64> = v.into();
296        assert_eq!(m.nrows(), 1);
297        assert_eq!(m.ncols(), 3);
298        assert_eq!(m[(0, 1)], 2.0);
299    }
300}