Created
April 27, 2013 00:43
-
-
Save mstewartgallus/5471387 to your computer and use it in GitHub Desktop.
Buggy matrix math code.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use core::num::*; | |
use std::complex::*; | |
use core::ops::*; | |
pub struct Vector { x : f32, y : f32 } | |
pub impl Vector { | |
fn from_scalar (scalar : f32) -> Vector { Vector { x : scalar, y : scalar } } | |
fn normal_to (vector : Vector) -> Vector { | |
Vector { x : -vector.y, y : vector.x } | |
} | |
} | |
impl Add <Vector, Vector> for Vector { | |
fn add (&self, rhs : &Vector) -> Vector { | |
Vector { x : self.x + rhs.x, y : self.y + rhs.y } | |
} | |
} | |
impl Sub <Vector, Vector> for Vector { | |
fn sub (&self, rhs : &Vector) -> Vector { | |
Vector { x : self.x - rhs.x, y : self.y - rhs.y } | |
} | |
} | |
impl Mul <Vector, Vector> for Vector { | |
fn mul (&self, rhs : &Vector) -> Vector { | |
Vector { x : self.x * rhs.x, y : self.y * rhs.y } | |
} | |
} | |
pub fn dot (lhs : Vector, rhs : Vector) -> f32 { lhs.x * rhs.x + lhs.y * rhs.y } | |
pub fn length (vector : Vector) -> f32 { | |
f32::sqrt (dot (vector, vector)) | |
} | |
pub fn direction (vector : Vector) -> Vector { | |
let len = length (vector); | |
Vector { x : vector.x / len, y : vector.y / len } | |
} | |
#[deriving (Eq)] | |
pub struct Vector2 <T> { x : T, y : T } | |
#[deriving (Eq)] | |
pub struct RotationMultiplicationMatrix2x2 <T> (Cmplx <T>); | |
pub impl <T : Add <T, T> + Sub <T, T> + Mul <T, T>> RotationMultiplicationMatrix2x2 <T> { | |
// self = [a, -b], a rotation matrix, or a + ib | |
// [b, a] | |
fn rotate (self, Vector2 { x, y } : Vector2 <T>) -> Vector2 <T> { | |
let RotationMultiplicationMatrix2x2 (Cmplx { re, im }) = self; | |
Vector2 { | |
x : x * re - y * im, | |
y : x * im + y * re | |
} | |
} | |
} | |
pub type RotationMultiplicationMatrix4x4 <T> = RotationMultiplicationMatrix2x2 <RotationMultiplicationMatrix2x2 <T>>; | |
pub type Matrix2x2 <T> = RotationMultiplicationMatrix4x4 <T>; | |
pub impl <T> Matrix2x2 <T> { | |
fn new ( | |
a : T, b : T, | |
c : T, d : T | |
) -> Matrix2x2 <T> { | |
// ((x +jy) + i(z + jw)) * _ = [[x, -y] [z, -w]] [[a, 0]] = [[]] | |
// [[y, x ], -[w, z ]] * [[0, a ]] [[]] | |
// [[z, -w] [x, -y]] [[c, 0]] [[]] | |
// [[w, z ], [y, x ]] [[0, c ]] [[]] | |
RotationMultiplicationMatrix2x2 (Cmplx { | |
re : RotationMultiplicationMatrix2x2 (Cmplx { re : a, im : b }), | |
im : RotationMultiplicationMatrix2x2 (Cmplx { re : c, im : d }) | |
}) | |
} | |
} | |
impl <T : Num + Copy> Add <RotationMultiplicationMatrix2x2 <T>, RotationMultiplicationMatrix2x2 <T>> for RotationMultiplicationMatrix2x2 <T> { | |
pub fn add ( | |
&self, | |
matrix : &RotationMultiplicationMatrix2x2 <T> | |
) -> RotationMultiplicationMatrix2x2 <T> { | |
RotationMultiplicationMatrix2x2 (**self + **matrix) | |
} | |
} | |
impl <T : Num + Copy> Sub <RotationMultiplicationMatrix2x2 <T>, RotationMultiplicationMatrix2x2 <T>> for RotationMultiplicationMatrix2x2 <T> { | |
pub fn sub ( | |
&self, | |
matrix : &RotationMultiplicationMatrix2x2 <T> | |
) -> RotationMultiplicationMatrix2x2 <T> { | |
RotationMultiplicationMatrix2x2 (**self - **matrix) | |
} | |
} | |
impl <T : Num + Copy> Mul <RotationMultiplicationMatrix2x2 <T>, RotationMultiplicationMatrix2x2 <T>> for RotationMultiplicationMatrix2x2 <T> { | |
pub fn mul ( | |
&self, | |
matrix : &RotationMultiplicationMatrix2x2 <T> | |
) -> RotationMultiplicationMatrix2x2 <T> { | |
RotationMultiplicationMatrix2x2 (**self * **matrix) | |
} | |
} | |
impl <T : Num + Quot <T, T> + Copy> Quot <RotationMultiplicationMatrix2x2 <T>, RotationMultiplicationMatrix2x2 <T>> for RotationMultiplicationMatrix2x2 <T> { | |
pub fn quot ( | |
&self, | |
matrix : &RotationMultiplicationMatrix2x2 <T> | |
) -> RotationMultiplicationMatrix2x2 <T> { | |
RotationMultiplicationMatrix2x2 (**self / **matrix) | |
} | |
} | |
impl <T : Num> One for RotationMultiplicationMatrix2x2 <T> { | |
pub fn one () -> RotationMultiplicationMatrix2x2 <T> { | |
RotationMultiplicationMatrix2x2 (One::one ()) | |
} | |
} | |
impl <T : Num> Zero for RotationMultiplicationMatrix2x2 <T> { | |
pub fn zero () -> RotationMultiplicationMatrix2x2 <T> { | |
RotationMultiplicationMatrix2x2 (Zero::zero ()) | |
} | |
} | |
impl <T : Num + Copy> Neg <RotationMultiplicationMatrix2x2 <T>> for RotationMultiplicationMatrix2x2 <T> { | |
pub fn neg (&self) -> RotationMultiplicationMatrix2x2 <T> { | |
RotationMultiplicationMatrix2x2 (-**self) | |
} | |
} | |
impl <T> Num for RotationMultiplicationMatrix2x2 <T> { | |
} | |
impl <T : Num + Copy> Matrix2x2 <T> { | |
pub fn apply (self, Vector2 { x, y } : Vector2 <T>) -> Vector2 <T> { | |
let Vector2 { x, y } = self.rotate (Vector2 { | |
x : RotationMultiplicationMatrix2x2 (Cmplx { re : x, im : Zero::zero () }), | |
y : RotationMultiplicationMatrix2x2 (Cmplx { re : y, im : Zero::zero () }) | |
}); | |
Vector2 { x : x.re, y : y.re } | |
} | |
} | |
#[test] | |
pub fn identity_matrix_works () { | |
// Use uint arithmetic because floating point is strange | |
let identity = Matrix2x2::new ( | |
1, 0, | |
0, 1 | |
); | |
let test_cases = [ | |
Vector2 { x : 1, y : 0 }, | |
Vector2 { x : 1, y : 1 }, | |
Vector2 { x : 0, y : 1 }, | |
Vector2 { x : 4, y : 5 }, | |
Vector2 { x : 320, y : 50 } | |
]; | |
for test_cases.each |&test_case| { | |
let result = identity.apply (test_case); | |
if result != test_case { | |
fail! (fmt! ( | |
"The test case %? applied to the identity became %?", | |
test_case, | |
result)); | |
} | |
} | |
} | |
#[test] | |
pub fn other_matrix_works () { | |
let one : Matrix2x2 <f32> = Zero::zero (); | |
} | |
// x = [a, -b], a rotation matrix, or a + ib. | |
// [b, a] | |
// | |
// The matrix inverse of it is therefore [a, b] / (a * a + b * b), or | |
// [-b, a] | |
// (a - ib) / (a * a + b * b) | |
// |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment