column major

This commit is contained in:
Quaternions 2024-09-26 15:06:01 -07:00
parent e46f4fb900
commit 8d97ffba92
4 changed files with 49 additions and 42 deletions

View File

@ -4,18 +4,18 @@ macro_rules! impl_matrix {
() => { () => {
impl<const X:usize,const Y:usize,T> Matrix<X,Y,T>{ impl<const X:usize,const Y:usize,T> Matrix<X,Y,T>{
#[inline(always)] #[inline(always)]
pub const fn new(array:[[T;X];Y])->Self{ pub const fn new(array:[[T;Y];X])->Self{
Self{array} Self{array}
} }
#[inline(always)] #[inline(always)]
pub fn to_array(self)->[[T;X];Y]{ pub fn to_array(self)->[[T;Y];X]{
self.array self.array
} }
#[inline] #[inline]
pub fn from_rows(rows:[Vector<X,T>;Y])->Self pub fn from_cols(cols:[Vector<Y,T>;X])->Self
{ {
Matrix::new( Matrix::new(
rows.map(|row|row.array), cols.map(|col|col.array),
) )
} }
#[inline] #[inline]
@ -40,38 +40,45 @@ macro_rules! impl_matrix {
) )
} }
#[inline] #[inline]
// MatY<VecX>.MatX<VecZ> = MatY<VecZ> // old (list of rows) MatY<VecX>.MatX<VecZ> = MatY<VecZ>
// new (list of columns) MatX<VecY>.MatZ<VecX> = MatZ<VecY>
pub fn dot<const Z:usize,U,V>(self,rhs:Matrix<Z,X,U>)->Matrix<Z,Y,V> pub fn dot<const Z:usize,U,V>(self,rhs:Matrix<Z,X,U>)->Matrix<Z,Y,V>
where where
T:core::ops::Mul<U,Output=V>+Copy, T:core::ops::Mul<U,Output=V>+Copy,
V:core::iter::Sum, V:core::iter::Sum,
U:Copy, U:Copy,
{ {
let mut array_of_iterators=rhs.array.map(|axis|axis.into_iter().cycle()); let mut array_of_iterators=self.array.map(|axis|axis.into_iter().cycle());
Matrix::new( Matrix{
self.array.map(|axis| array:rhs.array.map(|rhs_axis|
core::array::from_fn(|_| core::array::from_fn(|_|
// axis dot product with transposed rhs array array_of_iterators
axis.iter().zip( .iter_mut()
array_of_iterators.iter_mut() .zip(rhs_axis.iter())
).map(|(&lhs_value,rhs_iter)| .map(|(lhs_iter,&rhs_value)|
lhs_value*rhs_iter.next().unwrap() lhs_iter.next().unwrap()*rhs_value
).sum() ).sum()
) )
) )
) }
} }
#[inline] #[inline]
// MatY<VecX>.VecX = VecY // MatX<VecY>.VecY = VecX
pub fn transform_vector<U,V>(self,rhs:Vector<X,U>)->Vector<Y,V> pub fn transform_vector<U,V>(self,rhs:Vector<X,U>)->Vector<Y,V>
where where
T:core::ops::Mul<U,Output=V>, T:core::ops::Mul<U,Output=V>,
V:core::iter::Sum, V:core::iter::Sum,
U:Copy, U:Copy,
{ {
let mut array_of_iterators=self.array.map(|axis|axis.into_iter());
Vector::new( Vector::new(
self.array.map(|axis| core::array::from_fn(|_|
Vector::new(axis).dot(rhs) array_of_iterators
.iter_mut()
.zip(rhs.array.iter())
.map(|(lhs_iter,&rhs_value)|
lhs_iter.next().unwrap()*rhs_value
).sum()
) )
) )
} }
@ -82,7 +89,7 @@ macro_rules! impl_matrix {
{ {
#[inline(always)] #[inline(always)]
pub const fn from_value(value:T)->Self{ pub const fn from_value(value:T)->Self{
Self::new([[value;X];Y]) Self::new([[value;Y];X])
} }
} }
@ -98,13 +105,13 @@ macro_rules! impl_matrix {
impl<const X:usize,const Y:usize,T:core::fmt::Display> core::fmt::Display for Matrix<X,Y,T>{ impl<const X:usize,const Y:usize,T:core::fmt::Display> core::fmt::Display for Matrix<X,Y,T>{
#[inline] #[inline]
fn fmt(&self,f:&mut core::fmt::Formatter)->Result<(),core::fmt::Error>{ fn fmt(&self,f:&mut core::fmt::Formatter)->Result<(),core::fmt::Error>{
for row in &self.array[0..Y]{ for col in &self.array[0..X]{
core::write!(f,"\n")?; core::write!(f,"\n")?;
for elem in &row[0..X-1]{ for elem in &col[0..Y-1]{
core::write!(f,"{}, ",elem)?; core::write!(f,"{}, ",elem)?;
} }
// assume we will be using matrices of size 1x1 or greater // assume we will be using matrices of size 1x1 or greater
core::write!(f,"{}",row.last().unwrap())?; core::write!(f,"{}",col.last().unwrap())?;
} }
Ok(()) Ok(())
} }
@ -166,14 +173,14 @@ macro_rules! impl_matrix_extend {
( $x: expr, $y: expr ) => { ( $x: expr, $y: expr ) => {
impl<T> Matrix<$x,$y,T>{ impl<T> Matrix<$x,$y,T>{
#[inline] #[inline]
pub fn extend_row(self,value:Vector<$x,T>)->Matrix<$x,{$y+1},T>{ pub fn extend_column(self,value:Vector<$y,T>)->Matrix<{$x+1},$y,T>{
let mut iter=self.array.into_iter().chain(core::iter::once(value.array)); let mut iter=self.array.into_iter().chain(core::iter::once(value.array));
Matrix::new( Matrix::new(
core::array::from_fn(|_|iter.next().unwrap()), core::array::from_fn(|_|iter.next().unwrap()),
) )
} }
#[inline] #[inline]
pub fn extend_column(self,value:Vector<$y,T>)->Matrix<{$x+1},$y,T>{ pub fn extend_row(self,value:Vector<$x,T>)->Matrix<$x,{$y+1},T>{
let mut iter_rows=value.array.into_iter(); let mut iter_rows=value.array.into_iter();
Matrix::new( Matrix::new(
self.array.map(|axis|{ self.array.map(|axis|{

View File

@ -2,7 +2,7 @@ use crate::vector::Vector;
#[derive(Clone,Copy,Debug,Hash,Eq,PartialEq)] #[derive(Clone,Copy,Debug,Hash,Eq,PartialEq)]
pub struct Matrix<const X:usize,const Y:usize,T>{ pub struct Matrix<const X:usize,const Y:usize,T>{
pub(crate) array:[[T;X];Y], pub(crate) array:[[T;Y];X],
} }
crate::impl_matrix!(); crate::impl_matrix!();

View File

@ -1,4 +1,4 @@
use crate::types::{Matrix3,Matrix2x3,Matrix4x3,Matrix2x4,Vector3}; use crate::types::{Matrix3,Matrix3x2,Matrix3x4,Matrix4x2,Vector3};
type Planar64=fixed_wide::types::I32F32; type Planar64=fixed_wide::types::I32F32;
type Planar64Wide1=fixed_wide::types::I64F64; type Planar64Wide1=fixed_wide::types::I64F64;
@ -37,28 +37,28 @@ fn wide_vec3_length_squared(){
#[test] #[test]
fn wide_matrix_dot(){ fn wide_matrix_dot(){
let lhs=Matrix4x3::new([ let lhs=Matrix3x4::new([
[Planar64::from(1),Planar64::from(2),Planar64::from(3),Planar64::from(4)], [Planar64::from(1),Planar64::from(2),Planar64::from(3),Planar64::from(4)],
[Planar64::from(5),Planar64::from(6),Planar64::from(7),Planar64::from(8)], [Planar64::from(5),Planar64::from(6),Planar64::from(7),Planar64::from(8)],
[Planar64::from(9),Planar64::from(10),Planar64::from(11),Planar64::from(12)], [Planar64::from(9),Planar64::from(10),Planar64::from(11),Planar64::from(12)],
]); ]).transpose();
let rhs=Matrix2x4::new([ let rhs=Matrix4x2::new([
[Planar64::from(1),Planar64::from(2)], [Planar64::from(1),Planar64::from(2)],
[Planar64::from(3),Planar64::from(4)], [Planar64::from(3),Planar64::from(4)],
[Planar64::from(5),Planar64::from(6)], [Planar64::from(5),Planar64::from(6)],
[Planar64::from(7),Planar64::from(8)], [Planar64::from(7),Planar64::from(8)],
]); ]).transpose();
// Mat3<Vec4>.dot(Mat4<Vec2>) -> Mat3<Vec2> // Mat3<Vec4>.dot(Mat4<Vec2>) -> Mat3<Vec2>
let m_dot=lhs*rhs; let m_dot=lhs*rhs;
//In[1]:= {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}} . {{1, 2}, {3, 4}, {5, 6}, {7, 8}} //In[1]:= {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}} . {{1, 2}, {3, 4}, {5, 6}, {7, 8}}
//Out[1]= {{50, 60}, {114, 140}, {178, 220}} //Out[1]= {{50, 60}, {114, 140}, {178, 220}}
assert_eq!( assert_eq!(
m_dot.array, m_dot.array,
Matrix2x3::new([ Matrix3x2::new([
[Planar64Wide1::from(50),Planar64Wide1::from(60)], [Planar64Wide1::from(50),Planar64Wide1::from(60)],
[Planar64Wide1::from(114),Planar64Wide1::from(140)], [Planar64Wide1::from(114),Planar64Wide1::from(140)],
[Planar64Wide1::from(178),Planar64Wide1::from(220)], [Planar64Wide1::from(178),Planar64Wide1::from(220)],
]).array ]).transpose().array
); );
} }

View File

@ -1,4 +1,4 @@
use crate::types::{Vector2,Vector3,Matrix4x3,Matrix2x4,Matrix2x3,Matrix3x2}; use crate::types::{Vector2,Vector3,Matrix3x4,Matrix4x2,Matrix3x2,Matrix2x3};
#[test] #[test]
fn test_bool(){ fn test_bool(){
@ -21,10 +21,10 @@ fn test_arithmetic(){
#[test] #[test]
fn matrix_transform_vector(){ fn matrix_transform_vector(){
let m=Matrix3x2::new([ let m=Matrix2x3::new([
[1,2,3], [1,2,3],
[4,5,6], [4,5,6],
]); ]).transpose();
let v=Vector3::new([1,2,3]); let v=Vector3::new([1,2,3]);
let transformed=m*v; let transformed=m*v;
assert_eq!(transformed.array,Vector2::new([14,32]).array); assert_eq!(transformed.array,Vector2::new([14,32]).array);
@ -32,28 +32,28 @@ fn matrix_transform_vector(){
#[test] #[test]
fn matrix_dot(){ fn matrix_dot(){
// All this code was written row major and I converted the lib to colum major
let rhs=Matrix2x4::new([ let rhs=Matrix4x2::new([
[ 1.0, 2.0], [ 1.0, 2.0],
[ 3.0, 4.0], [ 3.0, 4.0],
[ 5.0, 6.0], [ 5.0, 6.0],
[ 7.0, 8.0], [ 7.0, 8.0],
]); // | | | ]).transpose(); // | | |
let lhs=Matrix4x3::new([ // | | | let lhs=Matrix3x4::new([ // | | |
[1.0, 2.0, 3.0, 4.0],// [ 50.0, 60.0], [1.0, 2.0, 3.0, 4.0],// [ 50.0, 60.0],
[5.0, 6.0, 7.0, 8.0],// [114.0,140.0], [5.0, 6.0, 7.0, 8.0],// [114.0,140.0],
[9.0,10.0,11.0,12.0],// [178.0,220.0], [9.0,10.0,11.0,12.0],// [178.0,220.0],
]); ]).transpose();
// Mat3<Vec4>.dot(Mat4<Vec2>) -> Mat3<Vec2> // Mat3<Vec4>.dot(Mat4<Vec2>) -> Mat3<Vec2>
let m_dot=lhs*rhs; let m_dot=lhs*rhs;
//In[1]:= {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}} . {{1, 2}, {3, 4}, {5, 6}, {7, 8}} //In[1]:= {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}} . {{1, 2}, {3, 4}, {5, 6}, {7, 8}}
//Out[1]= {{50, 60}, {114, 140}, {178, 220}} //Out[1]= {{50, 60}, {114, 140}, {178, 220}}
assert_eq!( assert_eq!(
m_dot.array, m_dot.array,
Matrix2x3::new([ Matrix3x2::new([
[50.0,60.0], [50.0,60.0],
[114.0,140.0], [114.0,140.0],
[178.0,220.0], [178.0,220.0],
]).array ]).transpose().array
); );
} }