mini_matrix/
operations.rs

1//! # mini_matrix
2//!
3//! A mini linear algebra library implemented in Rust.
4//!
5use num::{Float, Num};
6use std::iter::Sum;
7use std::ops::{Add, AddAssign, Mul};
8
9use super::Vector;
10
11/* ***************************** */
12/*      Linear Combination      */
13/* *************************** */
14
15/// Computes the linear combination of a set of vectors.
16///
17/// A linear combination is the sum of scalar multiples of vectors.
18///
19/// # Arguments
20///
21/// * `vectors` - A mutable slice of vectors to be combined
22/// * `scalars` - A slice of scalar values to multiply with each vector
23///
24/// # Returns
25///
26/// A new `Vector<T, N>` representing the linear combination of the input vectors.
27///
28/// # Examples
29///
30/// ```
31/// use mini_matrix::{Vector, linear_combination};
32///
33/// let mut v1 = Vector::from([1.0, 2.0, 3.0]);
34/// let mut v2 = Vector::from([4.0, 5.0, 6.0]);
35/// let scalars = [2.0, 3.0];
36///
37/// let result = linear_combination(&mut [v1, v2], &scalars);
38/// assert_eq!(result, Vector::from([14.0, 19.0, 24.0]));
39/// ```
40///
41/// # Panics
42///
43/// This function will panic if:
44/// - The number of vectors and scalars are not equal
45/// - The vector slice is empty
46
47// O(n)
48
49pub fn linear_combination<T, const N: usize>(
50    vectors: &[Vector<T, N>],
51    scalars: &[T],
52) -> Vector<T, N>
53where
54    T: Num + Copy + Clone + Default + PartialOrd + AddAssign + Mul<T>,
55{
56    assert_eq!(
57        vectors.len(),
58        scalars.len(),
59        "The number of vectors and scalars must be the same"
60    );
61
62    if vectors.is_empty() {
63        panic!("The number of vectors must be greater than 0");
64    }
65
66    let mut result = Vector::zero();
67    for (v, s) in vectors.iter().zip(scalars.iter()) {
68        result += *v * *s;
69    }
70    result
71}
72
73/// Computes the linear interpolation between two vectors.
74///
75/// Linear interpolation (lerp) finds a point that is between two vectors, based on a given parameter `t`.
76/// It computes a weighted average of the vectors where `t` determines the weight of the second vector.
77///
78/// # Arguments
79///
80/// * `u` - The starting vector.
81/// * `v` - The ending vector.
82/// * `t` - A scalar parameter between 0.0 and 1.0 that determines the interpolation point.
83///         If `t` is 0.0, the result is `u`. If `t` is 1.0, the result is `v`.
84///         For values between 0.0 and 1.0, the result is a point between `u` and `v`.
85///
86/// # Returns
87///
88/// A new vector that represents the interpolated result between `u` and `v`.
89///
90/// # Examples
91///
92/// ```
93/// use mini_matrix::{Vector, lerp};
94///
95/// let u = Vector::from([1.0, 2.0, 3.0]);
96/// let v = Vector::from([4.0, 5.0, 6.0]);
97///
98/// let result = lerp(u, v, 0.5);
99/// assert_eq!(result, Vector::from([2.5, 3.5, 4.5]));
100/// ```
101///
102/// # Panics
103///
104/// This function will panic if:
105/// - The type `V` does not implement the required traits (`Add`, `Mul`).
106///
107/// # Notes
108///
109/// - This function assumes `t` is a floating-point number (`f32`) and works with vectors where the `Add`
110///   and `Mul` traits are implemented.
111pub fn lerp<V>(u: V, v: V, t: f32) -> V
112where
113    V: Add<V, Output = V> + Mul<f32, Output = V>,
114{
115    u * (1.0 - t) + v * t
116}
117
118/* *********************** */
119/*      Cosine Angle       */
120/* *********************** */
121
122/// Calculates the cosine of the angle between two vectors.
123///
124/// For vectors a and b, the cosine of the angle θ between them is:
125/// cos(θ) = (a · b) / (||a|| ||b||)
126/// Where (a · b) is the dot product and ||a|| and ||b|| are the magnitudes of the vectors.
127///
128/// # Arguments
129/// * `u` - A reference to the first vector
130/// * `v` - A reference to the second vector
131///
132/// # Returns
133/// The cosine of the angle between the two vectors as a value of type `T`.
134///
135/// # Type Parameters
136/// * `T` - The floating-point type of the vector components
137/// * `N` - The dimensionality of the vectors
138///
139/// # Type Constraints
140/// * `T: Float` - The component type must be a floating-point type
141/// * `T: Sum` - The component type must support summation
142pub fn angle_cos<T, const N: usize>(u: &Vector<T, N>, v: &Vector<T, N>) -> T
143where
144    T: Float,
145    T: Sum,
146{
147    let dot_product = u.dot(v);
148    let norm_u = u.norm();
149    let norm_v = v.norm();
150    dot_product / (norm_u * norm_v)
151}
152
153/// Computes the cross product of two 3-dimensional vectors.
154///
155/// The cross product u × v is defined for 3D vectors as:
156/// u × v = [u2v3 - u3v2, u3v1 - u1v3, u1v2 - u2v1]
157///
158/// # Arguments
159/// * `u` - A reference to the first 3D vector
160/// * `v` - A reference to the second 3D vector
161///
162/// # Returns
163/// A new `Vector<T, 3>` representing the cross product of `u` and `v`.
164///
165/// # Type Parameters
166/// * `T` - The floating-point type of the vector components
167/// * `N` - The dimensionality of the vectors (should be 3)
168///
169/// # Panics
170/// This function will panic if the input vectors are not 3-dimensional.
171///
172pub fn cross_product<T, const N: usize>(u: &Vector<T, N>, v: &Vector<T, N>) -> Vector<T, 3>
173where
174    T: Float + Default,
175{
176    assert_eq!(N, 3, "Cross product is only defined for 3D vectors");
177
178    Vector::from([
179        u[1] * v[2] - u[2] * v[1],
180        u[2] * v[0] - u[0] * v[2],
181        u[0] * v[1] - u[1] * v[0],
182    ])
183}