Skip to main content

simple_vectors/
lib.rs

1#![deny(missing_docs)]
2
3/*!
4A simple, dimension-generic vector math library.
5
6This crate provides a generic `Vector` type for performing vector operations with compile-time dimension checking. It's designed to be lightweight, and integrates well with the `vector-space` ecosystem.
7
8# Features
9
10- **Dimension and type generic**: Works with vectors of any compile-time dimension and scalar type
11- **Trait integration**: Implements `VectorSpace`, `DotProduct`, and `InnerSpace`
12- **Optional parsing**: Parsing support via the `parsable` feature
13
14# Basic Usage
15
16```rust
17use scalars::Zero;
18use simple_vectors::Vector;
19
20// Create a 3D vector
21let v = Vector::new([1.0, 2.0, 3.0]);
22let w = Vector::new([4.0, 5.0, 6.0]);
23
24// Basic arithmetic
25let sum = v + w;
26let scaled = v * 2.0;
27
28// Dot product
29let dot = v * w;
30
31// Zero vector
32let zero = Vector::<f64, 3>::zero();
33```
34
35# Examples
36
37## 2D Vector Operations
38
39```rust
40use simple_vectors::Vector;
41
42let position = Vector::new([10.0, 20.0]);
43let velocity = Vector::new([5.0, -2.0]);
44let new_position = position + velocity;
45```
46
47## Generic Dimension Functions
48
49```rust
50use scalars::Real;
51use simple_vectors::Vector;
52
53fn magnitude<T: Real, const N: usize>(v: Vector<T, N>) -> T {
54    (v * v).sqrt()
55}
56
57let v = Vector::new([1.0, 2.0, 3.0]);
58let mag = magnitude(v);
59```
60
61# Integration with vector-space
62
63This crate implements the standard `vector-space` traits, making it compatible
64with other libraries in the ecosystem:
65
66```rust
67use simple_vectors::Vector;
68use inner_space::{InnerSpace, distance};
69
70let v = Vector::new([1.0, 2.0]);
71let w = Vector::new([3.0, 4.0]);
72
73// Both work the same:
74let dis1 = distance(v, w);
75let dis2 = (w - v).magnitude();
76
77assert_eq!(dis1, dis2);
78```
79*/
80
81use inner_space::{DotProduct, VectorSpace};
82use scalars::{Real, Zero};
83use vector_basis::Basis;
84
85use std::{
86    iter::Sum,
87    ops::{Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign},
88};
89
90/// A generic, fixed-size vector with compile-time dimension checking.
91///
92/// The `Vector` type represents a mathematical vector with `N` components
93/// of type `T`. It provides common vector operations and integrates with
94/// the `vector-space` trait ecosystem.
95///
96/// # Type Parameters
97///
98/// - `T`: The scalar type of vector components (must implement relevant traits for operations)
99/// - `N`: The dimension of the vector (must be a compile-time constant)
100///
101/// # Examples
102///
103/// Basic usage with f32:
104///
105/// ```
106/// use simple_vectors::Vector;
107///
108/// let v = Vector::new([1.0, 2.0, 3.0]);
109/// assert_eq!(v[0], 1.0);
110/// assert_eq!(v[1], 2.0);
111/// assert_eq!(v[2], 3.0);
112/// ```
113///
114/// Using with integer types:
115///
116/// ```
117/// use simple_vectors::Vector;
118///
119/// let int_vec = Vector::new([1, 2, 3, 4]);
120/// let scaled = int_vec * 2;
121/// assert_eq!(scaled, Vector::new([2, 4, 6, 8]));
122/// ```
123#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
124pub struct Vector<T, const N: usize>([T; N]);
125
126impl<T, const N: usize> Vector<T, N> {
127    /// Creates a new vector from the given array of elements.
128    ///
129    /// This is a const function, allowing vector creation in const contexts.
130    ///
131    /// # Arguments
132    ///
133    /// * `elements` - An array of `N` elements to initialize the vector
134    ///
135    /// # Examples
136    ///
137    /// ```
138    /// use simple_vectors::Vector;
139    ///
140    /// const V: Vector<i32, 3> = Vector::new([1, 2, 3]);
141    /// assert_eq!(V, Vector::new([1, 2, 3]));
142    /// ```
143    ///
144    /// Creating a 2D vector:
145    /// ```
146    /// use simple_vectors::Vector;
147    ///
148    /// let point = Vector::new([10.5, 20.3]);
149    /// ```
150    pub const fn new(elements: [T; N]) -> Self {
151        Self(elements)
152    }
153}
154
155impl<T: Real, const N: usize, const I: usize> Basis<I> for Vector<T, N> {
156    fn unit_basis() -> Self {
157        let mut result = Self::zero();
158        result.0[I] = T::one();
159        result
160    }
161
162    fn basis_of(magnitude: T) -> Self {
163        let mut result = Self::zero();
164        result.0[I] = magnitude;
165        result
166    }
167
168    fn basis(&self) -> Self::Scalar {
169        self.0[I]
170    }
171
172    fn basis_mut(&mut self) -> &mut Self::Scalar {
173        &mut self.0[I]
174    }
175}
176
177impl<T: Default + Copy, const N: usize> Default for Vector<T, N> {
178    fn default() -> Self {
179        Self([T::default(); N])
180    }
181}
182
183impl<T, const N: usize> Add<Self> for Vector<T, N>
184where
185    T: Add<Output = T> + Copy,
186{
187    type Output = Self;
188    fn add(mut self, other: Self) -> Self {
189        for i in 0..N {
190            self.0[i] = self.0[i] + other.0[i];
191        }
192        self
193    }
194}
195
196impl<T, const N: usize> AddAssign<Self> for Vector<T, N>
197where
198    T: AddAssign + Copy,
199{
200    fn add_assign(&mut self, other: Self) {
201        for i in 0..N {
202            self.0[i] += other.0[i];
203        }
204    }
205}
206
207impl<T, const N: usize> Sub<Self> for Vector<T, N>
208where
209    T: Sub<Output = T> + Copy,
210{
211    type Output = Self;
212    fn sub(mut self, other: Self) -> Self {
213        for i in 0..N {
214            self.0[i] = self.0[i] - other.0[i];
215        }
216        self
217    }
218}
219
220impl<T, const N: usize> SubAssign<Self> for Vector<T, N>
221where
222    T: SubAssign + Copy,
223{
224    fn sub_assign(&mut self, other: Self) {
225        for i in 0..N {
226            self.0[i] -= other.0[i];
227        }
228    }
229}
230
231impl<T, const N: usize> Neg for Vector<T, N>
232where
233    T: Neg<Output = T> + Copy,
234{
235    type Output = Self;
236    fn neg(mut self) -> Self {
237        for i in 0..N {
238            self.0[i] = -self.0[i];
239        }
240        self
241    }
242}
243
244impl<T, const N: usize> Mul<T> for Vector<T, N>
245where
246    T: Mul<Output = T> + Copy,
247{
248    type Output = Self;
249    fn mul(mut self, other: T) -> Self {
250        for i in 0..N {
251            self.0[i] = self.0[i] * other;
252        }
253        self
254    }
255}
256
257impl<T, const N: usize> MulAssign<T> for Vector<T, N>
258where
259    T: MulAssign + Copy,
260{
261    fn mul_assign(&mut self, other: T) {
262        for i in 0..N {
263            self.0[i] *= other;
264        }
265    }
266}
267
268impl<T, const N: usize> Div<T> for Vector<T, N>
269where
270    T: Div<Output = T> + Copy,
271{
272    type Output = Self;
273    fn div(mut self, other: T) -> Self {
274        for i in 0..N {
275            self.0[i] = self.0[i] / other;
276        }
277        self
278    }
279}
280
281impl<T, const N: usize> DivAssign<T> for Vector<T, N>
282where
283    T: DivAssign + Copy,
284{
285    fn div_assign(&mut self, other: T) {
286        for i in 0..N {
287            self.0[i] /= other;
288        }
289    }
290}
291
292impl<T, const N: usize> Mul<Self> for Vector<T, N>
293where
294    T: Add<Output = T> + Mul<Output = T> + Zero + Copy,
295{
296    type Output = T;
297    fn mul(self, other: Self) -> T {
298        self.0
299            .iter()
300            .zip(other.0.iter())
301            .fold(T::zero(), |result, (&left, &right)| result + left * right)
302    }
303}
304
305impl<T: Zero + Copy, const N: usize> Zero for Vector<T, N> {
306    fn zero() -> Self {
307        Self([T::zero(); N])
308    }
309
310    fn is_zero(&self) -> bool {
311        for i in 0..N {
312            if !self.0[i].is_zero() {
313                return false;
314            }
315        }
316        true
317    }
318}
319
320impl<T: Real, const N: usize> VectorSpace for Vector<T, N> {
321    type Scalar = T;
322}
323
324impl<T: Real, const N: usize> DotProduct for Vector<T, N> {
325    type Output = Self::Scalar;
326    fn dot(&self, other: &Self) -> T {
327        *self * *other
328    }
329}
330
331impl<T, const N: usize> From<[T; N]> for Vector<T, N> {
332    fn from(elements: [T; N]) -> Self {
333        Self::new(elements)
334    }
335}
336
337impl<T, const N: usize> From<Vector<T, N>> for [T; N] {
338    fn from(val: Vector<T, N>) -> Self {
339        val.0
340    }
341}
342
343impl<'a, T, const N: usize> From<&'a Vector<T, N>> for &'a [T; N] {
344    fn from(val: &'a Vector<T, N>) -> Self {
345        &val.0
346    }
347}
348
349impl<'a, T, const N: usize> From<&'a mut Vector<T, N>> for &'a mut [T; N] {
350    fn from(val: &'a mut Vector<T, N>) -> Self {
351        &mut val.0
352    }
353}
354
355impl<'a, T, const N: usize> From<&'a Vector<T, N>> for &'a [T] {
356    fn from(val: &'a Vector<T, N>) -> Self {
357        &val.0
358    }
359}
360
361impl<'a, T, const N: usize> From<&'a mut Vector<T, N>> for &'a mut [T] {
362    fn from(val: &'a mut Vector<T, N>) -> Self {
363        &mut val.0
364    }
365}
366
367impl<I, T, const N: usize> Index<I> for Vector<T, N>
368where
369    [T; N]: Index<I>,
370{
371    type Output = <[T; N] as Index<I>>::Output;
372    fn index(&self, index: I) -> &Self::Output {
373        &self.0[index]
374    }
375}
376
377impl<I, T, const N: usize> IndexMut<I> for Vector<T, N>
378where
379    [T; N]: IndexMut<I>,
380{
381    fn index_mut(&mut self, index: I) -> &mut Self::Output {
382        &mut self.0[index]
383    }
384}
385
386impl<T, const N: usize> Sum for Vector<T, N>
387where
388    T: Add<Output = T> + Zero + Copy,
389{
390    fn sum<I>(iter: I) -> Self
391    where
392        I: Iterator<Item = Self>,
393    {
394        iter.fold(Self::zero(), |acc, v| acc + v)
395    }
396}
397
398mod point;
399
400pub use point::Point;
401
402#[cfg(feature = "parsable")]
403mod parsable;