use std;
use vec2::Vec2;
type Row = (f32, f32);
type InlineMat2 = (f32, f32, f32, f32);
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Mat2 {
pub rows: [Vec2<f32>; 2],
}
impl Mat2 {
pub fn identity() -> Mat2 {
Self::default()
}
pub fn transposed(&self) -> Mat2 {
(
(self[0][0], self[1][0]),
(self[0][1], self[1][1]),
).into()
}
pub fn transpose(&mut self) {
*self = self.transposed();
}
pub fn rotation(radians: f32) -> Mat2 {
let sin = radians.sin();
let cos = radians.cos();
((cos, -sin), (sin, cos)).into()
}
pub fn rotated(&self, radians: f32) -> Mat2 {
*self * Mat2::rotation(radians)
}
pub fn rotate(&mut self, radians: f32) {
*self = self.rotated(radians);
}
pub fn scaled(&self, factor: Vec2<f32>) -> Mat2 {
let mut matrix = *self;
matrix[0] *= factor.x;
matrix[1] *= factor.y;
matrix
}
pub fn scale(&mut self, factor: Vec2<f32>) {
*self = self.scaled(factor);
}
}
impl Default for Mat2 {
fn default() -> Mat2 {
((1.0, 0.0), (0.0, 1.0)).into()
}
}
impl From<f32> for Mat2 {
fn from(value: f32) -> Mat2 {
Mat2 {
rows: [
(value, 0.0).into(),
(0.0, value).into(),
],
}
}
}
impl From<(Row, Row)> for Mat2 {
fn from(tuple: (Row, Row)) -> Mat2 {
Mat2 {
rows: [tuple.0.into(), tuple.1.into()],
}
}
}
impl From<InlineMat2> for Mat2 {
fn from(tuple: InlineMat2) -> Mat2 {
Mat2 {
rows: [
(tuple.0, tuple.1).into(),
(tuple.2, tuple.3).into(),
],
}
}
}
impl From<[[f32; 2]; 2]> for Mat2 {
fn from(slice: [[f32; 2]; 2]) -> Mat2 {
Mat2 {
rows: [slice[0].into(), slice[1].into()],
}
}
}
impl From<[f32; 4]> for Mat2 {
fn from(slice: [f32; 4]) -> Mat2 {
Mat2 {
rows: [
(slice[0], slice[1]).into(),
(slice[2], slice[3]).into(),
],
}
}
}
impl From<[Vec2<f32>; 2]> for Mat2 {
fn from(slice: [Vec2<f32>; 2]) -> Mat2 {
Mat2 {
rows: [slice[0], slice[1]],
}
}
}
impl From<(Vec2<f32>, Vec2<f32>, Vec2<f32>)> for Mat2 {
fn from(tuple: (Vec2<f32>, Vec2<f32>, Vec2<f32>)) -> Mat2 {
Mat2 {
rows: [tuple.0, tuple.1],
}
}
}
impl std::ops::Index<usize> for Mat2 {
type Output = Vec2<f32>;
fn index(&self, index: usize) -> &Vec2<f32> {
match index {
0 => &self.rows[0],
1 => &self.rows[1],
_ => panic!("Mat2 index out of range!"),
}
}
}
impl std::ops::IndexMut<usize> for Mat2 {
fn index_mut(&mut self, index: usize) -> &mut Vec2<f32> {
match index {
0 => &mut self.rows[0],
1 => &mut self.rows[1],
_ => panic!("Mat2 index out of range!"),
}
}
}
impl std::ops::Index<(usize, usize)> for Mat2 {
type Output = f32;
fn index(&self, index: (usize, usize)) -> &f32 {
&self.rows[index.0][index.1]
}
}
impl std::ops::IndexMut<(usize, usize)> for Mat2 {
fn index_mut(&mut self, index: (usize, usize)) -> &mut f32 {
&mut self.rows[index.0][index.1]
}
}
impl std::ops::Add for Mat2 {
type Output = Mat2;
fn add(self, right: Mat2) -> Mat2 {
Mat2 {
rows: [self[0] + right[0], self[1] + right[1]],
}
}
}
impl std::ops::AddAssign for Mat2 {
fn add_assign(&mut self, right: Mat2) {
*self = *self + right;
}
}
impl std::ops::Sub for Mat2 {
type Output = Mat2;
fn sub(self, right: Mat2) -> Mat2 {
Mat2 {
rows: [self[0] - right[0], self[1] - right[1]],
}
}
}
impl std::ops::SubAssign for Mat2 {
fn sub_assign(&mut self, right: Mat2) {
*self = *self - right;
}
}
impl std::ops::Mul<Vec2<f32>> for Mat2 {
type Output = Vec2<f32>;
fn mul(self, vec: Vec2<f32>) -> Vec2<f32> {
(self[0].dot(vec), self[1].dot(vec)).into()
}
}
impl std::ops::Mul<Mat2> for Mat2 {
type Output = Mat2;
fn mul(self, right: Mat2) -> Mat2 {
let mut result: Mat2 = 0.0.into();
result[0][0] =
self[0][0] * right[0][0] + self[1][0] * right[0][1];
result[0][1] =
self[0][1] * right[0][0] + self[1][1] * right[0][1];
result[1][0] =
self[0][0] * right[1][0] + self[1][0] * right[1][1];
result[1][1] =
self[0][1] * right[1][0] + self[1][1] * right[1][1];
result
}
}
impl std::ops::MulAssign<Mat2> for Mat2 {
fn mul_assign(&mut self, right: Mat2) {
*self = *self * right;
}
}