1use std::{
2 fmt::Display,
3 ops::{Index, IndexMut},
4};
5
6use crate::detail;
7
8use pyinrs::Fraction;
9
10#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
12pub struct Vector {
13 pub(crate) elements: Vec<Fraction>,
14}
15
16impl Vector {
17 pub fn new() -> Self {
19 Self { elements: Vec::new() }
20 }
21
22 pub fn create(n: usize, value: Fraction) -> Self {
24 Self { elements: [value].repeat(n) }
25 }
26
27 pub fn zeros(n: usize) -> Self {
29 Self::create(n, 0.into())
30 }
31
32 pub fn ones(n: usize) -> Self {
34 Self::create(n, 1.into())
35 }
36
37 pub fn size(&self) -> usize {
39 self.elements.len()
40 }
41
42 pub fn is_empty(&self) -> bool {
44 self.elements.is_empty()
45 }
46
47 pub fn is_zero(&self) -> bool {
49 self.count_leading_zeros() == self.size()
50 }
51
52 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 pub fn is_parallel(&self, that: &Self) -> bool {
62 detail::check_empty(self.size());
63 detail::check_size(self.size(), that.size());
64
65 if self.is_zero() || that.is_zero() {
67 return true;
68 }
69
70 let i = self.count_leading_zeros();
72 let scale = that[i] / self[i];
74 self * scale == *that
76 }
77
78 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 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 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 let mut width = 0;
163 for i in 0..self.size() {
164 width = width.max(format!("{}", self[i]).len());
165 }
166
167 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}