pub type Matrix2x2 = [[f64; 2]; 2];
#[derive(Debug, Clone, PartialEq)]
pub enum MathError {
NotQuadratic,
SingularMatrix,
}
#[derive(Debug, Clone, PartialEq)]
pub enum QuadraticRoots {
TwoReal(f64, f64),
OneReal(f64),
Complex((f64, f64), (f64, f64)),
}
pub fn discriminant(a: f64, b: f64, c: f64) -> f64 {
b * b - 4.0 * a * c
}
pub fn solve_quadratic(a: f64, b: f64, c: f64) -> Result<QuadraticRoots, MathError> {
if a == 0.0 {
return Err(MathError::NotQuadratic);
}
let d = discriminant(a, b, c);
let two_a = 2.0 * a;
if d > 0.0 {
let sqrt_d = d.sqrt();
Ok(QuadraticRoots::TwoReal(
(-b + sqrt_d) / two_a,
(-b - sqrt_d) / two_a,
))
} else if d == 0.0 {
Ok(QuadraticRoots::OneReal(-b / two_a))
} else {
let real = -b / two_a;
let imag = (-d).sqrt() / two_a;
Ok(QuadraticRoots::Complex((real, imag), (real, -imag)))
}
}
pub fn determinant_2x2(m: Matrix2x2) -> f64 {
m[0][0] * m[1][1] - m[0][1] * m[1][0]
}
pub fn trace_2x2(m: Matrix2x2) -> f64 {
m[0][0] + m[1][1]
}
pub fn transpose_2x2(m: Matrix2x2) -> Matrix2x2 {
[[m[0][0], m[1][0]], [m[0][1], m[1][1]]]
}
pub fn inverse_2x2(m: Matrix2x2) -> Result<Matrix2x2, MathError> {
let det = determinant_2x2(m);
if det == 0.0 {
return Err(MathError::SingularMatrix);
}
Ok([
[m[1][1] / det, -m[0][1] / det],
[-m[1][0] / det, m[0][0] / det],
])
}
pub fn solve_linear_2x2(a: Matrix2x2, b: [f64; 2]) -> Result<[f64; 2], MathError> {
let det_a = determinant_2x2(a);
if det_a == 0.0 {
return Err(MathError::SingularMatrix);
}
let det_x = determinant_2x2([[b[0], a[0][1]], [b[1], a[1][1]]]);
let det_y = determinant_2x2([[a[0][0], b[0]], [a[1][0], b[1]]]);
Ok([det_x / det_a, det_y / det_a])
}