Switch to column-major representation.
Matrices are now column-major. This will be useful to interop with opengl and lapack.
This commit is contained in:
parent
90e40aaec0
commit
8423286911
|
@ -101,16 +101,35 @@ impl<N: Clone> DMat<N> {
|
|||
}
|
||||
|
||||
/// Builds a matrix filled with the components provided by a vector.
|
||||
/// The vector contains the matrix data in row-major order.
|
||||
/// Note that `from_col_vec` is a lot faster than `from_row_vec` since a `DMat` stores its data
|
||||
/// in column-major order.
|
||||
///
|
||||
/// The vector must have at least `nrows * ncols` elements.
|
||||
#[inline]
|
||||
pub fn from_vec(nrows: uint, ncols: uint, vec: &[N]) -> DMat<N> {
|
||||
assert!(nrows * ncols <= vec.len());
|
||||
pub fn from_row_vec(nrows: uint, ncols: uint, vec: &[N]) -> DMat<N> {
|
||||
let mut res = DMat::from_col_vec(ncols, nrows, vec);
|
||||
|
||||
// we transpose because the buffer is row_major
|
||||
res.transpose();
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
/// Builds a matrix filled with the components provided by a vector.
|
||||
/// The vector contains the matrix data in column-major order.
|
||||
/// Note that `from_col_vec` is a lot faster than `from_row_vec` since a `DMat` stores its data
|
||||
/// in column-major order.
|
||||
///
|
||||
/// The vector must have at least `nrows * ncols` elements.
|
||||
#[inline]
|
||||
pub fn from_col_vec(nrows: uint, ncols: uint, vec: &[N]) -> DMat<N> {
|
||||
assert!(nrows * ncols == vec.len());
|
||||
|
||||
DMat {
|
||||
nrows: nrows,
|
||||
ncols: ncols,
|
||||
mij: vec.slice_to(nrows * ncols).to_owned()
|
||||
mij: vec.to_owned()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -139,10 +158,29 @@ impl<N> DMat<N> {
|
|||
}
|
||||
|
||||
/// Transforms this matrix into an array. This consumes the matrix and is O(1).
|
||||
/// The returned vector contains the matrix data in column-major order.
|
||||
#[inline]
|
||||
pub fn to_vec(self) -> ~[N] {
|
||||
self.mij
|
||||
}
|
||||
|
||||
/// Gets a reference to this matrix data.
|
||||
/// The returned vector contains the matrix data in column-major order.
|
||||
#[inline]
|
||||
pub fn as_vec<'r>(&'r self) -> &'r [N] {
|
||||
let res: &'r [N] = self.mij;
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
/// Gets a mutable reference to this matrix data.
|
||||
/// The returned vector contains the matrix data in column-major order.
|
||||
#[inline]
|
||||
pub fn as_mut_vec<'r>(&'r mut self) -> &'r mut [N] {
|
||||
let res: &'r mut [N] = self.mij;
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: add a function to modify the dimension (to avoid useless allocations)?
|
||||
|
@ -167,9 +205,9 @@ impl<N: One + Zero + Clone> DMat<N> {
|
|||
}
|
||||
|
||||
impl<N: Clone> DMat<N> {
|
||||
#[inline]
|
||||
#[inline(always)]
|
||||
fn offset(&self, i: uint, j: uint) -> uint {
|
||||
i * self.ncols + j
|
||||
i + j * self.nrows
|
||||
}
|
||||
|
||||
/// Changes the value of a component of the matrix.
|
||||
|
|
|
@ -20,7 +20,7 @@ mod iso_macros;
|
|||
///
|
||||
/// This is the composition of a rotation followed by a translation.
|
||||
/// Isometries conserve angles and distances, hence do not allow shearing nor scaling.
|
||||
#[deriving(Eq, Encodable, Decodable, Clone, DeepClone, ToStr)]
|
||||
#[deriving(Eq, Encodable, Decodable, Clone, DeepClone, ToStr, IterBytes)]
|
||||
pub struct Iso2<N> {
|
||||
/// The rotation applicable by this isometry.
|
||||
rotation: Rot2<N>,
|
||||
|
@ -32,7 +32,7 @@ pub struct Iso2<N> {
|
|||
///
|
||||
/// This is the composition of a rotation followed by a translation.
|
||||
/// Isometries conserve angles and distances, hence do not allow shearing nor scaling.
|
||||
#[deriving(Eq, Encodable, Decodable, Clone, DeepClone, ToStr)]
|
||||
#[deriving(Eq, Encodable, Decodable, Clone, DeepClone, ToStr, IterBytes)]
|
||||
pub struct Iso3<N> {
|
||||
/// The rotation applicable by this isometry.
|
||||
rotation: Rot3<N>,
|
||||
|
@ -43,7 +43,7 @@ pub struct Iso3<N> {
|
|||
/// Four dimensional isometry.
|
||||
///
|
||||
/// Isometries conserve angles and distances, hence do not allow shearing nor scaling.
|
||||
#[deriving(Eq, Encodable, Decodable, Clone, DeepClone, ToStr)]
|
||||
#[deriving(Eq, Encodable, Decodable, Clone, DeepClone, ToStr, IterBytes)]
|
||||
pub struct Iso4<N> {
|
||||
/// The rotation applicable by this isometry.
|
||||
rotation: Rot4<N>,
|
||||
|
|
|
@ -127,8 +127,8 @@ outer_impl!(Vec1, Mat1)
|
|||
/// Square matrix of dimension 2.
|
||||
#[deriving(Eq, Encodable, Decodable, Clone, DeepClone, IterBytes, Rand, Zero, ToStr)]
|
||||
pub struct Mat2<N> {
|
||||
m11: N, m12: N,
|
||||
m21: N, m22: N
|
||||
m11: N, m21: N,
|
||||
m12: N, m22: N
|
||||
}
|
||||
|
||||
double_dispatch_binop_decl_trait!(Mat2, Mat2MulRhs)
|
||||
|
@ -224,9 +224,9 @@ outer_impl!(Vec2, Mat2)
|
|||
/// Square matrix of dimension 3.
|
||||
#[deriving(Eq, Encodable, Decodable, Clone, DeepClone, IterBytes, Rand, Zero, ToStr)]
|
||||
pub struct Mat3<N> {
|
||||
m11: N, m12: N, m13: N,
|
||||
m21: N, m22: N, m23: N,
|
||||
m31: N, m32: N, m33: N
|
||||
m11: N, m21: N, m31: N,
|
||||
m12: N, m22: N, m32: N,
|
||||
m13: N, m23: N, m33: N
|
||||
}
|
||||
|
||||
double_dispatch_binop_decl_trait!(Mat3, Mat3MulRhs)
|
||||
|
@ -335,10 +335,10 @@ outer_impl!(Vec3, Mat3)
|
|||
/// Square matrix of dimension 4.
|
||||
#[deriving(Eq, Encodable, Decodable, Clone, DeepClone, IterBytes, Rand, Zero, ToStr)]
|
||||
pub struct Mat4<N> {
|
||||
m11: N, m12: N, m13: N, m14: N,
|
||||
m21: N, m22: N, m23: N, m24: N,
|
||||
m31: N, m32: N, m33: N, m34: N,
|
||||
m41: N, m42: N, m43: N, m44: N
|
||||
m11: N, m21: N, m31: N, m41: N,
|
||||
m12: N, m22: N, m32: N, m42: N,
|
||||
m13: N, m23: N, m33: N, m43: N,
|
||||
m14: N, m24: N, m34: N, m44: N
|
||||
}
|
||||
|
||||
double_dispatch_binop_decl_trait!(Mat4, Mat4MulRhs)
|
||||
|
@ -498,11 +498,11 @@ outer_impl!(Vec4, Mat4)
|
|||
/// Square matrix of dimension 5.
|
||||
#[deriving(Eq, Encodable, Decodable, Clone, DeepClone, IterBytes, Rand, Zero, ToStr)]
|
||||
pub struct Mat5<N> {
|
||||
m11: N, m12: N, m13: N, m14: N, m15: N,
|
||||
m21: N, m22: N, m23: N, m24: N, m25: N,
|
||||
m31: N, m32: N, m33: N, m34: N, m35: N,
|
||||
m41: N, m42: N, m43: N, m44: N, m45: N,
|
||||
m51: N, m52: N, m53: N, m54: N, m55: N
|
||||
m11: N, m21: N, m31: N, m41: N, m51: N,
|
||||
m12: N, m22: N, m32: N, m42: N, m52: N,
|
||||
m13: N, m23: N, m33: N, m43: N, m53: N,
|
||||
m14: N, m24: N, m34: N, m44: N, m54: N,
|
||||
m15: N, m25: N, m35: N, m45: N, m55: N
|
||||
}
|
||||
|
||||
double_dispatch_binop_decl_trait!(Mat5, Mat5MulRhs)
|
||||
|
@ -677,12 +677,12 @@ outer_impl!(Vec5, Mat5)
|
|||
/// Square matrix of dimension 6.
|
||||
#[deriving(Eq, Encodable, Decodable, Clone, DeepClone, IterBytes, Rand, Zero, ToStr)]
|
||||
pub struct Mat6<N> {
|
||||
m11: N, m12: N, m13: N, m14: N, m15: N, m16: N,
|
||||
m21: N, m22: N, m23: N, m24: N, m25: N, m26: N,
|
||||
m31: N, m32: N, m33: N, m34: N, m35: N, m36: N,
|
||||
m41: N, m42: N, m43: N, m44: N, m45: N, m46: N,
|
||||
m51: N, m52: N, m53: N, m54: N, m55: N, m56: N,
|
||||
m61: N, m62: N, m63: N, m64: N, m65: N, m66: N
|
||||
m11: N, m21: N, m31: N, m41: N, m51: N, m61: N,
|
||||
m12: N, m22: N, m32: N, m42: N, m52: N, m62: N,
|
||||
m13: N, m23: N, m33: N, m43: N, m53: N, m63: N,
|
||||
m14: N, m24: N, m34: N, m44: N, m54: N, m64: N,
|
||||
m15: N, m25: N, m35: N, m45: N, m55: N, m65: N,
|
||||
m16: N, m26: N, m36: N, m46: N, m56: N, m66: N
|
||||
}
|
||||
|
||||
double_dispatch_binop_decl_trait!(Mat6, Mat6MulRhs)
|
||||
|
|
|
@ -20,13 +20,13 @@ macro_rules! at_fast_impl(
|
|||
#[inline]
|
||||
unsafe fn at_fast(&self, (i, j): (uint, uint)) -> N {
|
||||
(*cast::transmute::<&$t<N>, &[N, ..$dim * $dim]>(self)
|
||||
.unsafe_ref(i * $dim + j)).clone()
|
||||
.unsafe_ref(i + j * $dim)).clone()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn set_fast(&mut self, (i, j): (uint, uint), val: N) {
|
||||
(*cast::transmute::<&mut $t<N>, &mut [N, ..$dim * $dim]>(self)
|
||||
.unsafe_mut_ref(i * $dim + j)) = val
|
||||
.unsafe_mut_ref(i + j * $dim)) = val
|
||||
}
|
||||
}
|
||||
)
|
||||
|
@ -174,14 +174,14 @@ macro_rules! indexable_impl(
|
|||
#[inline]
|
||||
fn at(&self, (i, j): (uint, uint)) -> N {
|
||||
unsafe {
|
||||
cast::transmute::<&$t<N>, &[N, ..$dim * $dim]>(self)[i * $dim + j].clone()
|
||||
cast::transmute::<&$t<N>, &[N, ..$dim * $dim]>(self)[i + j * $dim].clone()
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set(&mut self, (i, j): (uint, uint), val: N) {
|
||||
unsafe {
|
||||
cast::transmute::<&mut $t<N>, &mut [N, ..$dim * $dim]>(self)[i * $dim + j] = val
|
||||
cast::transmute::<&mut $t<N>, &mut [N, ..$dim * $dim]>(self)[i + j * $dim] = val
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -189,7 +189,7 @@ macro_rules! indexable_impl(
|
|||
fn swap(&mut self, (i1, j1): (uint, uint), (i2, j2): (uint, uint)) {
|
||||
unsafe {
|
||||
cast::transmute::<&mut $t<N>, &mut [N, ..$dim * $dim]>(self)
|
||||
.swap(i1 * $dim + j1, i2 * $dim + j2)
|
||||
.swap(i1 + j1 * $dim, i2 + j2 * $dim)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use std::num::{Zero, One};
|
|||
use std::rand::{Rand, Rng};
|
||||
use traits::geometry::{Rotate, Rotation, AbsoluteRotate, RotationMatrix, Transform, ToHomogeneous,
|
||||
Norm, Cross};
|
||||
use traits::structure::{Cast, Dim, Indexable, Row, Col};
|
||||
use traits::structure::{Cast, Dim, Row, Col};
|
||||
use traits::operations::{Absolute, Inv, Transpose};
|
||||
use structs::vec::{Vec1, Vec2, Vec3, Vec4, Vec2MulRhs, Vec3MulRhs, Vec4MulRhs};
|
||||
use structs::mat::{Mat2, Mat3, Mat4, Mat5};
|
||||
|
@ -15,7 +15,7 @@ mod metal;
|
|||
mod rot_macros;
|
||||
|
||||
/// Two dimensional rotation matrix.
|
||||
#[deriving(Eq, Encodable, Decodable, Clone, DeepClone, ToStr)]
|
||||
#[deriving(Eq, Encodable, Decodable, Clone, DeepClone, ToStr, IterBytes)]
|
||||
pub struct Rot2<N> {
|
||||
priv submat: Mat2<N>
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ impl<N: Trigonometric + Num + Clone>
|
|||
Rotation<Vec1<N>> for Rot2<N> {
|
||||
#[inline]
|
||||
fn rotation(&self) -> Vec1<N> {
|
||||
Vec1::new((-self.submat.at((0, 1))).atan2(&self.submat.at((0, 0))))
|
||||
Vec1::new((-self.submat.m12).atan2(&self.submat.m11))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -93,7 +93,7 @@ impl<N: Signed> AbsoluteRotate<Vec2<N>> for Rot2<N> {
|
|||
* 3d rotation
|
||||
*/
|
||||
/// Three dimensional rotation matrix.
|
||||
#[deriving(Eq, Encodable, Decodable, Clone, DeepClone, ToStr)]
|
||||
#[deriving(Eq, Encodable, Decodable, Clone, DeepClone, ToStr, IterBytes)]
|
||||
pub struct Rot3<N> {
|
||||
priv submat: Mat3<N>
|
||||
}
|
||||
|
@ -264,7 +264,7 @@ impl<N: Signed> AbsoluteRotate<Vec3<N>> for Rot3<N> {
|
|||
}
|
||||
|
||||
/// Four dimensional rotation matrix.
|
||||
#[deriving(Eq, Encodable, Decodable, Clone, DeepClone, ToStr)]
|
||||
#[deriving(Eq, Encodable, Decodable, Clone, DeepClone, ToStr, IterBytes)]
|
||||
pub struct Rot4<N> {
|
||||
priv submat: Mat4<N>
|
||||
}
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
use std::num::{Real, abs};
|
||||
use std::rand::random;
|
||||
use std::cmp::ApproxEq;
|
||||
use na::{Vec1, DMat, DVec};
|
||||
use na::Indexable; // FIXME: get rid of that
|
||||
use na::{Vec1, Vec3, Mat1, Mat2, Mat3, Mat4, Mat5, Mat6, Rot3, DMat, DVec, Indexable};
|
||||
use na;
|
||||
|
||||
macro_rules! test_inv_mat_impl(
|
||||
|
@ -27,62 +26,62 @@ macro_rules! test_transpose_mat_impl(
|
|||
|
||||
#[test]
|
||||
fn test_transpose_mat1() {
|
||||
test_transpose_mat_impl!(na::Mat1<f64>);
|
||||
test_transpose_mat_impl!(Mat1<f64>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_transpose_mat2() {
|
||||
test_transpose_mat_impl!(na::Mat2<f64>);
|
||||
test_transpose_mat_impl!(Mat2<f64>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_transpose_mat3() {
|
||||
test_transpose_mat_impl!(na::Mat3<f64>);
|
||||
test_transpose_mat_impl!(Mat3<f64>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_transpose_mat4() {
|
||||
test_transpose_mat_impl!(na::Mat4<f64>);
|
||||
test_transpose_mat_impl!(Mat4<f64>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_transpose_mat5() {
|
||||
test_transpose_mat_impl!(na::Mat5<f64>);
|
||||
test_transpose_mat_impl!(Mat5<f64>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_transpose_mat6() {
|
||||
test_transpose_mat_impl!(na::Mat6<f64>);
|
||||
test_transpose_mat_impl!(Mat6<f64>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_inv_mat1() {
|
||||
test_inv_mat_impl!(na::Mat1<f64>);
|
||||
test_inv_mat_impl!(Mat1<f64>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_inv_mat2() {
|
||||
test_inv_mat_impl!(na::Mat2<f64>);
|
||||
test_inv_mat_impl!(Mat2<f64>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_inv_mat3() {
|
||||
test_inv_mat_impl!(na::Mat3<f64>);
|
||||
test_inv_mat_impl!(Mat3<f64>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_inv_mat4() {
|
||||
test_inv_mat_impl!(na::Mat4<f64>);
|
||||
test_inv_mat_impl!(Mat4<f64>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_inv_mat5() {
|
||||
test_inv_mat_impl!(na::Mat5<f64>);
|
||||
test_inv_mat_impl!(Mat5<f64>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_inv_mat6() {
|
||||
test_inv_mat_impl!(na::Mat6<f64>);
|
||||
test_inv_mat_impl!(Mat6<f64>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -97,7 +96,7 @@ fn test_rotation2() {
|
|||
|
||||
#[test]
|
||||
fn test_index_mat2() {
|
||||
let mat: na::Mat2<f64> = random();
|
||||
let mat: Mat2<f64> = random();
|
||||
|
||||
assert!(mat.at((0, 1)) == na::transpose(&mat).at((1, 0)));
|
||||
}
|
||||
|
@ -105,8 +104,8 @@ fn test_index_mat2() {
|
|||
#[test]
|
||||
fn test_inv_rotation3() {
|
||||
do 10000.times {
|
||||
let randmat: na::Rot3<f64> = na::one();
|
||||
let dir: na::Vec3<f64> = random();
|
||||
let randmat: Rot3<f64> = na::one();
|
||||
let dir: Vec3<f64> = random();
|
||||
let ang = na::normalize(&dir) * (abs::<f64>(random()) % Real::pi());
|
||||
let rot = na::append_rotation(&randmat, &ang);
|
||||
|
||||
|
@ -116,7 +115,7 @@ fn test_inv_rotation3() {
|
|||
|
||||
#[test]
|
||||
fn test_mean_dmat() {
|
||||
let mat = DMat::from_vec(
|
||||
let mat = DMat::from_row_vec(
|
||||
3,
|
||||
3,
|
||||
[
|
||||
|
@ -131,7 +130,7 @@ fn test_mean_dmat() {
|
|||
|
||||
#[test]
|
||||
fn test_cov_dmat() {
|
||||
let mat = DMat::from_vec(
|
||||
let mat = DMat::from_row_vec(
|
||||
5,
|
||||
3,
|
||||
[
|
||||
|
@ -143,7 +142,7 @@ fn test_cov_dmat() {
|
|||
]
|
||||
);
|
||||
|
||||
let expected = DMat::from_vec(
|
||||
let expected = DMat::from_row_vec(
|
||||
3,
|
||||
3,
|
||||
[
|
||||
|
@ -155,3 +154,56 @@ fn test_cov_dmat() {
|
|||
|
||||
assert!(na::cov(&mat).approx_eq(&expected));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_transpose_dmat() {
|
||||
let mat = DMat::from_row_vec(
|
||||
8,
|
||||
4,
|
||||
[
|
||||
1, 2, 3, 4,
|
||||
5, 6, 7, 8,
|
||||
9, 10, 11, 12,
|
||||
13, 14, 15, 16,
|
||||
17, 18, 19, 20,
|
||||
21, 22, 23, 24,
|
||||
25, 26, 27, 28,
|
||||
29, 30, 31, 32
|
||||
]
|
||||
);
|
||||
|
||||
assert!(na::transpose(&na::transpose(&mat)) == mat);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dmat_from_vec() {
|
||||
let mat1 = DMat::from_row_vec(
|
||||
8,
|
||||
4,
|
||||
[
|
||||
1, 2, 3, 4,
|
||||
5, 6, 7, 8,
|
||||
9, 10, 11, 12,
|
||||
13, 14, 15, 16,
|
||||
17, 18, 19, 20,
|
||||
21, 22, 23, 24,
|
||||
25, 26, 27, 28,
|
||||
29, 30, 31, 32
|
||||
]
|
||||
);
|
||||
|
||||
let mat2 = DMat::from_col_vec(
|
||||
8,
|
||||
4,
|
||||
[
|
||||
1, 5, 9, 13, 17, 21, 25, 29,
|
||||
2, 6, 10, 14, 18, 22, 26, 30,
|
||||
3, 7, 11, 15, 19, 23, 27, 31,
|
||||
4, 8, 12, 16, 20, 24, 28, 32
|
||||
]
|
||||
);
|
||||
|
||||
println!("mat1: {:?}, mat2: {:?}", mat1, mat2);
|
||||
|
||||
assert!(mat1 == mat2);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue