use std::ops::{Index, IndexMut, Add, AddAssign, Sub, SubAssign, Neg, Mul, MulAssign, Div, DivAssign};
#[derive(Copy, Clone, Debug, Eq, PartialEq, Default)]
pub struct Matrix2x2<U> {
mat: [[U; 2]; 2]
}
impl<U> Matrix2x2<U> {
pub const fn new(m00: U, m01: U, m10: U, m11: U) -> Self {
Matrix2x2 {
mat: [
[m00, m01],
[m10, m11]
]
}
}
}
impl<U> Index<usize> for Matrix2x2<U> {
type Output = [U; 2];
fn index(&self, index: usize) -> &Self::Output {
&self.mat[index]
}
}
impl<U> IndexMut<usize> for Matrix2x2<U> {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
&mut self.mat[index]
}
}
impl<U: Add<Output = V>, V> Add for Matrix2x2<U> {
type Output = V;
fn add(self, rhs: Self) -> Self::Output {
self[0][0] + other[0][0]
}
}
impl<U: AddAssign> AddAssign for Matrix2x2<U> {
fn add_assign(&mut self, rhs: Self) {
self.x += rhs.x;
self.y += rhs.y;
}
}
impl<U: Sub<Output = V>, V> Sub for Matrix2x2<U> {
type Output = Matrix2x2<V>;
fn sub(self, rhs: Self) -> Self::Output {
Matrix2x2 {
x: self.x-rhs.x,
y: self.y-rhs.y
}
}
}
impl<U: SubAssign> SubAssign for Matrix2x2<U> {
fn sub_assign(&mut self, rhs: Self) {
self.x -= rhs.x;
self.y -= rhs.y;
}
}
impl<U: Neg<Output = V>, V> Neg for Matrix2x2<U> {
type Output = Matrix2x2<V>;
fn neg(self) -> Self::Output {
Matrix2x2 {
x: -self.x,
y: -self.y
}
}
}
impl<U, V> Mul<U> for Matrix2x2<U>
where
U: Mul<Output = V> + Clone
{
type Output = Matrix2x2<V>;
fn mul(self, rhs: U) -> Self::Output {
Matrix2x2 {
x: self.x*rhs.clone(),
y: self.y*rhs.clone()
}
}
}
impl<U: MulAssign + Clone> MulAssign<U> for Matrix2x2<U> {
fn mul_assign(&mut self, rhs: U) {
self.x *= rhs.clone();
self.y *= rhs.clone();
}
}
impl<U, V> Div<U> for Matrix2x2<U>
where
U: Div<Output = V> + Clone
{
type Output = Matrix2x2<V>;
fn div(self, rhs: U) -> Self::Output {
Matrix2x2 {
x: self.x/rhs.clone(),
y: self.y/rhs.clone()
}
}
}
impl<U: DivAssign + Clone> DivAssign<U> for Matrix2x2<U> {
fn div_assign(&mut self, rhs: U) {
self.x /= rhs.clone();
self.y /= rhs.clone();
}
}
impl<U> Mul<Matrix2x2<U>> for Matrix2x2<U>
where
U: Mul<Output = U> + Add<Output = U>
{
type Output = U;
fn mul(self, rhs: Matrix2x2<U>) -> Self::Output {
self.x*rhs.x + self.y*rhs.y
}
}
impl<U, V, W> Matrix2x2<U>
where
U: Mul<Output = V> + Clone,
V: Add<Output = W>
{
pub fn length_squared(&self) -> W {
self.x.clone()*self.x.clone() + self.y.clone()*self.y.clone()
}
}
impl Matrix2x2<f32> {
pub fn length(&self) -> f32 {
f32::sqrt(self.length_squared())
}
pub fn distance(self, other: Self) -> f32 {
(self - other).length()
}
pub fn normalized(&self) -> Self {
let length = self.length();
if length == 0. {
*self
} else {
*self / length
}
}
pub fn normalize(&mut self) -> &mut Self {
*self = self.normalized();
self
}
pub fn angle(&self) -> f32 {
f32::atan2(self.y, self.x)
}
}
impl Matrix2x2<f64> {
pub fn length(&self) -> f64 {
f64::sqrt(self.length_squared())
}
pub fn distance(self, other: Self) -> f64 {
(self - other).length()
}
pub fn normalized(&self) -> Self {
let length = self.length();
if length == 0. {
*self
} else {
*self / length
}
}
pub fn normalize(&mut self) -> &mut Self {
*self = self.normalized();
self
}
pub fn angle(&self) -> f64 {
f64::atan2(self.y, self.x)
}
}
impl<U: Clone + Default> Matrix2x2<U> {
pub fn horizontal(&self) -> Self {
Matrix2x2 {
x: self.x.clone(),
y: U::default()
}
}
pub fn vertical(&self) -> Self {
Matrix2x2 {
x: U::default(),
y: self.y.clone()
}
}
}
impl<U: Clone + Copy + Neg<Output = U>> Vector2<U> {
pub fn normal(&self) -> Self {
Vector2 {
x: -self.y,
y: self.x
}
}
}
impl<U: Clone + Copy> From<[U; 2]> for Vector2<U> {
fn from(value: [U; 2]) -> Self {
Vector2::new(value[0], value[1])
}
}
impl<U: Clone + Copy> From<(U, U)> for Vector2<U> {
fn from(value: (U, U)) -> Self {
Vector2::new(value.0, value.1)
}
}
impl<U> Vector2<U> {
fn from_vec2<V: From<U>>(src: Vector2<U>) -> Vector2<V> {
Vector2::<V>::new(src.x.into(), src.y.into())
}
fn into_vec2<V: Into<U>>(src: Vector2<V>) -> Vector2<U> {
Vector2::<U>::new(src.x.into(), src.y.into())
}
}