1use std::str::FromStr;
2
3use crate::{result::Result, MathError};
4
5pub trait ArithmeticallyOperable<T>:
15 CheckedAdd + CheckedSub + CheckedMul + Sized + Clone + PartialEq + FromStr + Zero + Identity
16{
17}
18
19impl<T> ArithmeticallyOperable<T> for T where
20 T: CheckedAdd + CheckedSub + CheckedMul + Sized + Clone + PartialEq + FromStr + Zero + Identity
21{
22}
23
24pub trait CheckedAdd {
25 type Output;
26 fn checked_add(&self, rhs: &Self) -> Self::Output;
27}
28
29macro_rules! impl_checked_add {
30 ($($t:ty),*) => {
31 $(impl CheckedAdd for $t {
32 type Output = Result<$t>;
33 fn checked_add(&self, rhs: &Self) -> Self::Output {
34 (*self as $t).checked_add(*rhs).ok_or(MathError::MatrixError("Addition error".to_string()))
35 }
36 })*
37 };
38}
39impl_checked_add!(usize, u8, u16, u32, u64, u128, isize, i8, i16, i32, i64, i128);
40
41impl CheckedAdd for f32 {
42 type Output = Result<f32>;
43
44 fn checked_add(&self, rhs: &Self) -> Self::Output {
45 Ok(self + rhs)
46 }
47}
48
49impl CheckedAdd for f64 {
50 type Output = Result<f64>;
51
52 fn checked_add(&self, rhs: &Self) -> Self::Output {
53 Ok(self + rhs)
54 }
55}
56
57pub trait CheckedSub {
58 type Output;
59 fn checked_sub(&self, rhs: &Self) -> Self::Output;
60}
61
62macro_rules! impl_checked_sub {
63 ($($t:ty),*) => {
64 $(impl CheckedSub for $t {
65 type Output = Result<$t>;
66 fn checked_sub(&self, rhs: &Self) -> Self::Output {
67 (*self as $t).checked_sub(*rhs).ok_or(MathError::MatrixError("Substraction error".to_string()))
68 }
69 })*
70 };
71}
72impl_checked_sub!(isize, i8, i16, i32, i64, i128);
73
74impl CheckedSub for f32 {
75 type Output = Result<f32>;
76
77 fn checked_sub(&self, rhs: &Self) -> Self::Output {
78 Ok(self - rhs)
79 }
80}
81
82impl CheckedSub for f64 {
83 type Output = Result<f64>;
84
85 fn checked_sub(&self, rhs: &Self) -> Self::Output {
86 Ok(self - rhs)
87 }
88}
89
90impl CheckedSub for usize {
91 type Output = Result<isize>;
92 fn checked_sub(&self, rhs: &Self) -> Self::Output {
93 (*self as isize)
94 .checked_sub(*rhs as isize)
95 .ok_or(MathError::MatrixError("Substraction error".to_string()))
96 }
97}
98
99impl CheckedSub for u8 {
100 type Output = Result<i8>;
101 fn checked_sub(&self, rhs: &Self) -> Self::Output {
102 (*self as i8)
103 .checked_sub(*rhs as i8)
104 .ok_or(MathError::MatrixError("Substraction error".to_string()))
105 }
106}
107
108impl CheckedSub for u16 {
109 type Output = Result<i16>;
110 fn checked_sub(&self, rhs: &Self) -> Self::Output {
111 (*self as i16)
112 .checked_sub(*rhs as i16)
113 .ok_or(MathError::MatrixError("Substraction error".to_string()))
114 }
115}
116
117impl CheckedSub for u32 {
118 type Output = Result<i32>;
119 fn checked_sub(&self, rhs: &Self) -> Self::Output {
120 (*self as i32)
121 .checked_sub(*rhs as i32)
122 .ok_or(MathError::MatrixError("Substraction error".to_string()))
123 }
124}
125
126impl CheckedSub for u64 {
127 type Output = Result<i64>;
128 fn checked_sub(&self, rhs: &Self) -> Self::Output {
129 (*self as i64)
130 .checked_sub(*rhs as i64)
131 .ok_or(MathError::MatrixError("Substraction error".to_string()))
132 }
133}
134
135impl CheckedSub for u128 {
136 type Output = Result<i128>;
137 fn checked_sub(&self, rhs: &Self) -> Self::Output {
138 (*self as i128)
139 .checked_sub(*rhs as i128)
140 .ok_or(MathError::MatrixError("Substraction error".to_string()))
141 }
142}
143
144pub trait CheckedDiv {
145 type Output;
146 fn checked_div(&self, rhs: &Self) -> Self::Output;
147}
148
149macro_rules! impl_checked_div {
150 ($($t:ty),*) => {
151 $(impl CheckedDiv for $t {
152 type Output = Result<$t>;
153 fn checked_div(&self, rhs: &Self) -> Self::Output {
154 (*self as $t).checked_div(*rhs).ok_or(MathError::MatrixError("Division error".to_string()))
155 }
156 })*
157 };
158}
159
160impl_checked_div!(usize, u8, u16, u32, u64, u128, isize, i8, i16, i32, i64, i128);
161
162impl CheckedDiv for f32 {
163 type Output = Result<f32>;
164
165 fn checked_div(&self, rhs: &Self) -> Self::Output {
166 Ok(self / rhs)
167 }
168}
169
170impl CheckedDiv for f64 {
171 type Output = Result<f64>;
172
173 fn checked_div(&self, rhs: &Self) -> Self::Output {
174 Ok(self / rhs)
175 }
176}
177
178pub trait CheckedMul {
179 type Output;
180 fn checked_mul(&self, rhs: &Self) -> Self::Output;
181}
182
183macro_rules! impl_checked_mul {
184 ($($t:ty),*) => {
185 $(impl CheckedMul for $t {
186 type Output = Result<$t>;
187 fn checked_mul(&self, rhs: &Self) -> Self::Output {
188 (*self as $t).checked_mul(*rhs).ok_or(MathError::MatrixError("Multiplication error".to_string()))
189 }
190 })*
191 };
192}
193
194impl_checked_mul!(usize, u8, u16, u32, u64, u128, isize, i8, i16, i32, i64, i128);
195
196impl CheckedMul for f32 {
197 type Output = Result<f32>;
198
199 fn checked_mul(&self, rhs: &Self) -> Self::Output {
200 Ok(self * rhs)
201 }
202}
203
204impl CheckedMul for f64 {
205 type Output = Result<f64>;
206
207 fn checked_mul(&self, rhs: &Self) -> Self::Output {
208 Ok(self * rhs)
209 }
210}
211
212pub trait Zero {
213 fn zero(rows: usize, columns: usize, tolerance: f32) -> Self;
214 fn is_zero(&self) -> bool;
215}
216
217macro_rules! impl_zero {
218 ($($t:ty),*) => {
219 $(impl Zero for $t {
220 fn zero(_rows: usize, _columns: usize, _tolerance: f32) -> Self {
221 0 as $t
222 }
223 fn is_zero(&self) -> bool {
224 *self == 0 as $t
225 }
226 })*
227 };
228}
229
230impl_zero!(usize, u8, u16, u32, u64, u128, isize, i8, i16, i32, i64, i128, f32, f64);
231
232pub trait Identity {
233 fn id(dimensions: usize, tolerance: f32) -> Self;
234}
235
236macro_rules! impl_identity {
237 ($($t:ty),*) => {
238 $(impl Identity for $t {
239 fn id(_dimensions: usize, _tolerance: f32) -> Self {
240 1 as $t
241 }
242 })*
243 };
244}
245
246impl_identity!(usize, u8, u16, u32, u64, u128, isize, i8, i16, i32, i64, i128, f32, f64);
247
248pub trait Invertible {
249 fn inverse_gauss_jordan(&self) -> Result<Self>
250 where
251 Self: Sized;
252
253 fn inverse_montante(&self) -> Result<Self>
254 where
255 Self: Sized;
256
257 fn inverse_adjoint(&self) -> Result<Self>
258 where
259 Self: Sized;
260}
261
262pub trait Parseable {
263 fn parse(string: &str, tolerance: f32) -> Result<Self>
264 where
265 Self: Sized;
266}
267
268pub trait Serializable {
269 fn serialize(&self) -> String;
271}
272
273pub trait Matrix: ArithmeticallyOperable<Self> + Invertible + Parseable + Serializable {
274 type T: ArithmeticallyOperable<Self::T>;
275 fn columns(&self) -> usize;
277
278 fn rows(&self) -> usize;
280
281 fn is_square(&self) -> bool;
283
284 fn is_symmetric(&self) -> bool;
286
287 fn get(&self, row: usize, column: usize) -> Result<&Self::T>;
289
290 fn get_mut(&mut self, row: usize, column: usize) -> Result<&mut Self::T>;
292
293 fn set(&mut self, row: usize, column: usize, value: Self::T) -> Result<()>;
295
296 fn swap_rows(&mut self, row1: usize, row2: usize) -> Result<()>;
298
299 fn transpose(&self) -> Self;
301
302 fn gaussian_triangulation(&self) -> Result<Self>;
304
305 fn lu_decomposition(&self) -> Result<(Self, Self)>;
307
308 fn cholesky_decomposition(&self) -> Result<Self>;
310
311 fn determinant_using_gauss(&self) -> Option<Self::T>;
313
314 fn determinant_using_lu(&self) -> Option<Self::T>;
315}