use crate::common;
use crate::vector2::Vector2;
use std::cmp;
use std::fmt;
use std::fmt::{Display, Formatter};
use std::ops::{
Neg,
Add,
AddAssign,
Sub,
SubAssign,
Mul,
MulAssign,
Div,
DivAssign,
};
#[repr(C, packed)]
#[derive(Copy, Clone, Debug)]
pub struct Matrix2 {
pub m: [f32; 4],
}
impl Matrix2 {
#[inline]
pub fn new() -> Matrix2 {
Matrix2 {
m: [
1.0, 0.0,
0.0, 1.0,
],
}
}
#[inline]
pub fn make(m11: f32, m21: f32, m12: f32, m22: f32) -> Matrix2 {
Matrix2 {
m: [m11, m21, m12, m22],
}
}
#[inline]
pub fn m11(&self) -> f32 {
self.m[0]
}
#[inline]
pub fn m21(&self) -> f32 {
self.m[1]
}
#[inline]
pub fn m12(&self) -> f32 {
self.m[2]
}
#[inline]
pub fn m22(&self) -> f32 {
self.m[3]
}
#[inline]
pub fn set_m11(&mut self, v: f32) {
self.m[0] = v;
}
#[inline]
pub fn set_m21(&mut self, v: f32) {
self.m[1] = v;
}
#[inline]
pub fn set_m12(&mut self, v: f32) {
self.m[2] = v;
}
#[inline]
pub fn set_m22(&mut self, v: f32) {
self.m[3] = v;
}
#[inline]
pub fn set(&mut self, m11: f32, m21: f32, m12: f32, m22: f32) {
self.set_m11(m11);
self.set_m21(m21);
self.set_m12(m12);
self.set_m22(m22);
}
#[inline]
pub fn transpose(&mut self) {
let temp = self.m[1];
self.m[1] = self.m[2];
self.m[2] = temp;
}
#[inline]
pub fn determinant(&self) -> f32 {
self.m11() * self.m22() - self.m12() * self.m21()
}
#[inline]
pub fn inverse(&mut self) -> bool {
let det = self.determinant();
if det == 0.0 {
return false;
}
let inv_det = 1.0 / det;
let m11 = self.m22() * inv_det;
let m21 = -self.m21() * inv_det;
let m12 = -self.m12() * inv_det;
let m22 = self.m11() * inv_det;
self.set_m11(m11);
self.set_m21(m21);
self.set_m12(m12);
self.set_m22(m22);
true
}
#[inline]
pub fn is_valid(&self) -> bool {
for i in 0..4 {
if !common::is_valid(self.m[i]) {
return false;
}
}
true
}
}
impl Neg for Matrix2 {
type Output = Matrix2;
#[inline]
fn neg(self) -> Matrix2 {
let mut m = [0.0; 4];
unsafe {
for (i, elem) in self.m.iter().enumerate() {
m[i] = -*elem;
}
}
Matrix2 { m }
}
}
impl Add<f32> for Matrix2 {
type Output = Matrix2;
#[inline]
fn add(self, _rhs: f32) -> Matrix2 {
let mut mat = Matrix2::new();
unsafe {
for (i, elem) in self.m.iter().enumerate() {
mat.m[i] = *elem + _rhs;
}
}
mat
}
}
impl Add<Matrix2> for Matrix2 {
type Output = Matrix2;
#[inline]
fn add(self, _rhs: Matrix2) -> Matrix2 {
let mut mat = Matrix2::new();
unsafe {
for (i, elem) in self.m.iter().enumerate() {
mat.m[i] = *elem + _rhs.m[i];
}
}
mat
}
}
impl AddAssign<f32> for Matrix2 {
#[inline]
fn add_assign(&mut self, _rhs: f32) {
unsafe {
for elem in self.m.iter_mut() {
*elem += _rhs;
}
}
}
}
impl AddAssign<Matrix2> for Matrix2 {
#[inline]
fn add_assign(&mut self, _rhs: Matrix2) {
unsafe {
for (i, elem) in self.m.iter_mut().enumerate() {
*elem += _rhs.m[i];
}
}
}
}
impl Sub<f32> for Matrix2 {
type Output = Matrix2;
#[inline]
fn sub(self, _rhs: f32) -> Matrix2 {
let mut mat = Matrix2::new();
unsafe {
for (i, elem) in self.m.iter().enumerate() {
mat.m[i] = *elem - _rhs;
}
}
mat
}
}
impl Sub<Matrix2> for Matrix2 {
type Output = Matrix2;
#[inline]
fn sub(self, _rhs: Matrix2) -> Matrix2 {
let mut mat = Matrix2::new();
unsafe {
for (i, elem) in self.m.iter().enumerate() {
mat.m[i] = *elem - _rhs.m[i];
}
}
mat
}
}
impl SubAssign<f32> for Matrix2 {
#[inline]
fn sub_assign(&mut self, _rhs: f32) {
unsafe {
for elem in self.m.iter_mut() {
*elem -= _rhs;
}
}
}
}
impl SubAssign<Matrix2> for Matrix2 {
#[inline]
fn sub_assign(&mut self, _rhs: Matrix2) {
unsafe {
for (i, elem) in self.m.iter_mut().enumerate() {
*elem -= _rhs.m[i];
}
}
}
}
impl Mul<f32> for Matrix2 {
type Output = Matrix2;
#[inline]
fn mul(self, _rhs: f32) -> Matrix2 {
let mut mat = Matrix2::new();
unsafe {
for (i, elem) in self.m.iter().enumerate() {
mat.m[i] = *elem * _rhs;
}
}
mat
}
}
impl Mul<Matrix2> for Matrix2 {
type Output = Matrix2;
#[inline]
fn mul(self, _rhs: Matrix2) -> Matrix2 {
let m11 = self.m11() * _rhs.m11() + self.m12() * _rhs.m21();
let m21 = self.m21() * _rhs.m11() + self.m22() * _rhs.m21();
let m12 = self.m11() * _rhs.m12() + self.m12() * _rhs.m22();
let m22 = self.m21() * _rhs.m12() + self.m22() * _rhs.m22();
Matrix2::make(m11, m21, m12, m22)
}
}
impl MulAssign<f32> for Matrix2 {
#[inline]
fn mul_assign(&mut self, _rhs: f32) {
unsafe {
for elem in self.m.iter_mut() {
*elem *= _rhs;
}
}
}
}
impl MulAssign<Matrix2> for Matrix2 {
#[inline]
fn mul_assign(&mut self, _rhs: Matrix2) {
let res = *self * _rhs;
self.m = res.m;
}
}
impl Div<f32> for Matrix2 {
type Output = Matrix2;
#[inline]
fn div(self, _rhs: f32) -> Matrix2 {
let mut mat = Matrix2::new();
unsafe {
for (i, elem) in self.m.iter().enumerate() {
mat.m[i] = *elem / _rhs;
}
}
mat
}
}
impl DivAssign<f32> for Matrix2 {
#[inline]
fn div_assign(&mut self, _rhs: f32) {
unsafe {
for elem in self.m.iter_mut() {
*elem /= _rhs;
}
}
}
}
impl cmp::PartialEq for Matrix2 {
#[inline]
fn eq(&self, _rhs: &Matrix2) -> bool {
unsafe {
for (i, elem) in self.m.iter().enumerate() {
if *elem != _rhs.m[i] {
return false;
}
}
}
true
}
}
impl Display for Matrix2 {
#[inline]
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(
f,
"[\n {}, {}\n {}, {}\n]",
self.m11(),
self.m12(),
self.m21(),
self.m22()
)
}
}
impl common::Matrix<Vector2> for Matrix2 {
#[inline]
fn transform_point(&self, point: &Vector2) -> Vector2 {
Vector2::make(
self.m11() * point.x + self.m12() * point.y,
self.m21() * point.x + self.m22() * point.y,
)
}
}