1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
//! # matrix
//!
//! A mini linear algebra library implemented in Rust.
//!
use num::Float;
use std::iter::Sum;
use std::ops::{Add, Mul};
use super::Vector;
/* ***************************** */
/* Linear Combination */
/* *************************** */
/// Computes the linear combination of a set of vectors.
///
/// A linear combination is the sum of scalar multiples of vectors.
///
/// # Arguments
///
/// * `vectors` - A mutable slice of vectors to be combined
/// * `scalars` - A slice of scalar values to multiply with each vector
///
/// # Returns
///
/// A new `Vector<T, N>` representing the linear combination of the input vectors.
///
/// # Examples
///
/// ```
/// use mini_matrix::{Vector, linear_combination};
///
/// let mut v1 = Vector::from([1.0, 2.0, 3.0]);
/// let mut v2 = Vector::from([4.0, 5.0, 6.0]);
/// let scalars = [2.0, 3.0];
///
/// let result = linear_combination(&mut [v1, v2], &scalars);
/// assert_eq!(result, Vector::from([14.0, 19.0, 24.0]));
/// ```
///
/// # Panics
///
/// This function will panic if:
/// - The number of vectors and scalars are not equal
/// - The vector slice is empty
// O(n)
pub fn linear_combination<T, const N: usize>(
vectors: &mut [Vector<T, N>],
scalars: &[T],
) -> Vector<T, N>
where
T: Add<Output = T> + Mul<Output = T> + Copy + Clone + Default + PartialOrd,
Vector<T, N>: Mul<T>,
{
assert_eq!(
vectors.len(),
scalars.len(),
"The number of vectors and scalars must be the same"
);
if vectors.is_empty() {
panic!("The number of vectors must be greater than 0");
}
let mut result = Vector::zero();
for (vector, scalar) in vectors.iter_mut().zip(scalars.iter()) {
for (result_elem, vector_elem) in result.store.iter_mut().zip(vector.store.iter()) {
*result_elem = *result_elem + *vector_elem * *scalar;
}
}
result
}
/* *********************** */
/* Cosine Angle */
/* *********************** */
/// Calculates the cosine of the angle between two vectors.
///
/// For vectors a and b, the cosine of the angle θ between them is:
/// cos(θ) = (a · b) / (||a|| ||b||)
/// Where (a · b) is the dot product and ||a|| and ||b|| are the magnitudes of the vectors.
///
/// # Arguments
/// * `u` - A reference to the first vector
/// * `v` - A reference to the second vector
///
/// # Returns
/// The cosine of the angle between the two vectors as a value of type `T`.
///
/// # Type Parameters
/// * `T` - The floating-point type of the vector components
/// * `N` - The dimensionality of the vectors
///
/// # Type Constraints
/// * `T: Float` - The component type must be a floating-point type
/// * `T: Sum` - The component type must support summation
pub fn angle_cos<T, const N: usize>(u: &Vector<T, N>, v: &Vector<T, N>) -> T
where
T: Float,
T: Sum,
{
let dot_product = u.dot(v);
let norm_u = u.norm();
let norm_v = v.norm();
dot_product / (norm_u * norm_v)
}
/// Computes the cross product of two 3-dimensional vectors.
///
/// The cross product u × v is defined for 3D vectors as:
/// u × v = [u2v3 - u3v2, u3v1 - u1v3, u1v2 - u2v1]
///
/// # Arguments
/// * `u` - A reference to the first 3D vector
/// * `v` - A reference to the second 3D vector
///
/// # Returns
/// A new `Vector<T, 3>` representing the cross product of `u` and `v`.
///
/// # Type Parameters
/// * `T` - The floating-point type of the vector components
/// * `N` - The dimensionality of the vectors (should be 3)
///
/// # Panics
/// This function will panic if the input vectors are not 3-dimensional.
///
pub fn cross_product<T, const N: usize>(u: &Vector<T, N>, v: &Vector<T, N>) -> Vector<T, 3>
where
T: Float + Default,
{
assert_eq!(N, 3, "Cross product is only defined for 3D vectors");
Vector::from([
u[1] * v[2] - u[2] * v[1],
u[2] * v[0] - u[0] * v[2],
u[0] * v[1] - u[1] * v[0],
])
}