mymatrix/
vector.rs

1use std::{
2    fmt::Display,
3    ops::{Index, IndexMut},
4};
5
6use crate::detail;
7
8use pyinrs::Fraction;
9
10/// Vector with fractions as elements.
11#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
12pub struct Vector {
13    pub(crate) elements: Vec<Fraction>,
14}
15
16impl Vector {
17    /// Create a new vector object.
18    pub fn new() -> Self {
19        Self { elements: Vec::new() }
20    }
21
22    /// Create an n-dimensional vector with all identical elements.
23    pub fn create(n: usize, value: Fraction) -> Self {
24        Self { elements: [value].repeat(n) }
25    }
26
27    /// Create an n-dimensional vector with all 0 elements.
28    pub fn zeros(n: usize) -> Self {
29        Self::create(n, 0.into())
30    }
31
32    /// Create an n-dimensional vector with all 1 elements.
33    pub fn ones(n: usize) -> Self {
34        Self::create(n, 1.into())
35    }
36
37    /// Returns the number of elements in the vector.
38    pub fn size(&self) -> usize {
39        self.elements.len()
40    }
41
42    /// Returns `true` if the vector contains no elements.
43    pub fn is_empty(&self) -> bool {
44        self.elements.is_empty()
45    }
46
47    /// Determine if it is a zero vector.
48    pub fn is_zero(&self) -> bool {
49        self.count_leading_zeros() == self.size()
50    }
51
52    /// Determine whether two vectors are orthogonal.
53    pub fn is_orthogonal(&self, that: &Self) -> bool {
54        detail::check_empty(self.size());
55        detail::check_size(self.size(), that.size());
56
57        (self * that) == 0.into()
58    }
59
60    /// Determine whether two vectors are paralle.
61    pub fn is_parallel(&self, that: &Self) -> bool {
62        detail::check_empty(self.size());
63        detail::check_size(self.size(), that.size());
64
65        // zero vector parallel to any vector
66        if self.is_zero() || that.is_zero() {
67            return true;
68        }
69
70        // find the first non-zero element
71        let i = self.count_leading_zeros();
72        // calc the scale factor
73        let scale = that[i] / self[i];
74        // if equal after scale-up, then parallel
75        self * scale == *that
76    }
77
78    /// Calculate the norm (abs) of the vector.
79    pub fn norm(&self) -> f64 {
80        detail::check_empty(self.size());
81
82        let mut norm = 0.0;
83        for i in 0..self.size() {
84            norm += f64::from(self.elements[i] * self.elements[i]);
85        }
86        norm.sqrt()
87    }
88
89    /// Calculate the number of leading zeros of this vector.
90    pub fn count_leading_zeros(&self) -> usize {
91        detail::check_empty(self.size());
92
93        let mut lz: usize = 0;
94        while self.elements[lz] == 0.into() {
95            lz += 1;
96            if lz == self.size() {
97                break;
98            }
99        }
100        lz
101    }
102
103    /// Return the cross product of two vectors.
104    pub fn cross(a: &Self, b: &Self) -> Self {
105        if a.size() == 2 && b.size() == 2 {
106            Self::from([a[0] * b[1] - a[1] * b[0]])
107        } else if a.size() == 3 && b.size() == 3 {
108            return Self::from([a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]]);
109        } else {
110            panic!("Error: Incompatible dimensions for cross product.");
111        }
112    }
113}
114
115impl<const N: usize> From<[Fraction; N]> for Vector {
116    fn from(value: [Fraction; N]) -> Self {
117        Self { elements: Vec::from(value) }
118    }
119}
120
121impl<const N: usize> From<[i32; N]> for Vector {
122    fn from(value: [i32; N]) -> Self {
123        Self {
124            elements: Vec::from(value.map(Fraction::from)),
125        }
126    }
127}
128
129impl From<Vec<Fraction>> for Vector {
130    fn from(value: Vec<Fraction>) -> Self {
131        Self { elements: value }
132    }
133}
134
135impl From<Vec<i32>> for Vector {
136    fn from(value: Vec<i32>) -> Self {
137        Self {
138            elements: value.into_iter().map(Fraction::from).collect(),
139        }
140    }
141}
142
143impl Index<usize> for Vector {
144    type Output = Fraction;
145
146    fn index(&self, index: usize) -> &Self::Output {
147        &self.elements[index]
148    }
149}
150
151impl IndexMut<usize> for Vector {
152    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
153        &mut self.elements[index]
154    }
155}
156
157impl Display for Vector {
158    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
159        write!(f, "[")?;
160
161        // calc the max width of element
162        let mut width = 0;
163        for i in 0..self.size() {
164            width = width.max(format!("{}", self[i]).len());
165        }
166
167        // align right, fill with space
168        for i in 0..self.size() {
169            if i != 0 {
170                write!(f, " ")?;
171            }
172            write!(f, "{:>width$}", format!("{}", self[i]))?;
173        }
174
175        write!(f, "]")
176    }
177}
178
179auto_ops::impl_op_ex!(+=|a: &mut Vector, b: &Vector| {
180    detail::check_size(a.size(), b.size());
181    for i in 0..a.size() {
182        a[i] += b[i];
183    };
184});
185
186auto_ops::impl_op_ex!(+|a: &Vector, b: &Vector| -> Vector {
187    let mut a = a.clone();
188    a += b;
189    a
190});
191
192auto_ops::impl_op_ex!(-=|a: &mut Vector, b: &Vector| {
193    detail::check_size(a.size(), b.size());
194    for i in 0..a.size() {
195        a[i] -= b[i];
196    };
197});
198
199auto_ops::impl_op_ex!(-|a: &Vector, b: &Vector| -> Vector {
200    let mut a = a.clone();
201    a -= b;
202    a
203});
204
205auto_ops::impl_op_ex!(*=|a: &mut Vector, b: Fraction| {
206    for i in 0..a.size() {
207        a[i] *= b;
208    }
209});
210
211auto_ops::impl_op_ex_commutative!(*|a: &Vector, b: Fraction| -> Vector {
212    let mut a = a.clone();
213    a *= b;
214    a
215});
216
217auto_ops::impl_op_ex!(*=|a: &mut Vector, b: i32| {
218    for i in 0..a.size() {
219        a[i] *= Fraction::from(b);
220    }
221});
222
223auto_ops::impl_op_ex_commutative!(*|a: &Vector, b: i32| -> Vector {
224    let mut a = a.clone();
225    a *= b;
226    a
227});
228
229auto_ops::impl_op_ex!(*|a: &Vector, b: &Vector| -> Fraction {
230    detail::check_empty(a.size());
231    detail::check_size(a.size(), b.size());
232
233    let mut result = Fraction::new();
234    for i in 0..a.size() {
235        result += a[i] * b[i];
236    }
237    result
238});
239
240impl IntoIterator for Vector {
241    type Item = Fraction;
242    type IntoIter = std::vec::IntoIter<Self::Item>;
243
244    fn into_iter(self) -> Self::IntoIter {
245        self.elements.into_iter()
246    }
247}