use super::*;
#[repr(C)]
#[derive(Copy, Clone, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Mat2x2f {
columns: [Vec2f; 2],
}
#[repr(C)]
#[derive(Copy, Clone, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Mat2x3f {
columns: [Vec3f; 2],
}
#[repr(C)]
#[derive(Copy, Clone, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Mat2x4f {
columns: [Vec4f; 2],
}
#[repr(C)]
#[derive(Copy, Clone, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Mat3x2f {
columns: [Vec2f; 3],
}
#[repr(C)]
#[derive(Copy, Clone, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Mat3x3f {
columns: [Vec3f; 3],
}
#[repr(C)]
#[derive(Copy, Clone, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Mat3x4f {
columns: [Vec4f; 3],
}
#[repr(C)]
#[derive(Copy, Clone, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Mat4x2f {
columns: [Vec2f; 4],
}
#[repr(C)]
#[derive(Copy, Clone, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Mat4x3f {
columns: [Vec3f; 4],
}
#[repr(C)]
#[derive(Copy, Clone, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Mat4x4f {
columns: [Vec4f; 4],
}
pub type Mat2f = Mat2x2f;
pub type Mat3f = Mat3x3f;
pub type Mat4f = Mat4x4f;
macro_rules! impl_matrix_wgsl {
($t:ty, $cols:expr, $rows:expr) => {
impl Wgsl for $t {
fn to_ir() -> wgsl_rs_ir::Type {
wgsl_rs_ir::Type::Matrix {
columns: $cols,
rows: $rows,
scalar_ty: Some(wgsl_rs_ir::ScalarType::F32),
}
}
}
};
}
impl_matrix_wgsl!(Mat2x2f, 2, 2);
impl_matrix_wgsl!(Mat2x3f, 2, 3);
impl_matrix_wgsl!(Mat2x4f, 2, 4);
impl_matrix_wgsl!(Mat3x2f, 3, 2);
impl_matrix_wgsl!(Mat3x3f, 3, 3);
impl_matrix_wgsl!(Mat3x4f, 3, 4);
impl_matrix_wgsl!(Mat4x2f, 4, 2);
impl_matrix_wgsl!(Mat4x3f, 4, 3);
impl_matrix_wgsl!(Mat4x4f, 4, 4);
pub const fn mat2x2f(x_axis: Vec2f, y_axis: Vec2f) -> Mat2x2f {
Mat2x2f {
columns: [x_axis, y_axis],
}
}
pub const fn mat2x3f(x_axis: Vec3f, y_axis: Vec3f) -> Mat2x3f {
Mat2x3f {
columns: [x_axis, y_axis],
}
}
pub const fn mat2x4f(x_axis: Vec4f, y_axis: Vec4f) -> Mat2x4f {
Mat2x4f {
columns: [x_axis, y_axis],
}
}
pub const fn mat3x2f(x_axis: Vec2f, y_axis: Vec2f, z_axis: Vec2f) -> Mat3x2f {
Mat3x2f {
columns: [x_axis, y_axis, z_axis],
}
}
pub const fn mat3x3f(x_axis: Vec3f, y_axis: Vec3f, z_axis: Vec3f) -> Mat3x3f {
Mat3x3f {
columns: [x_axis, y_axis, z_axis],
}
}
pub const fn mat3x4f(x_axis: Vec4f, y_axis: Vec4f, z_axis: Vec4f) -> Mat3x4f {
Mat3x4f {
columns: [x_axis, y_axis, z_axis],
}
}
pub const fn mat4x2f(x_axis: Vec2f, y_axis: Vec2f, z_axis: Vec2f, w_axis: Vec2f) -> Mat4x2f {
Mat4x2f {
columns: [x_axis, y_axis, z_axis, w_axis],
}
}
pub const fn mat4x3f(x_axis: Vec3f, y_axis: Vec3f, z_axis: Vec3f, w_axis: Vec3f) -> Mat4x3f {
Mat4x3f {
columns: [x_axis, y_axis, z_axis, w_axis],
}
}
pub const fn mat4x4f(x_axis: Vec4f, y_axis: Vec4f, z_axis: Vec4f, w_axis: Vec4f) -> Mat4x4f {
Mat4x4f {
columns: [x_axis, y_axis, z_axis, w_axis],
}
}
macro_rules! impl_mat_index {
($mat:ty, $col_ty:ty) => {
impl std::ops::Index<usize> for $mat {
type Output = $col_ty;
fn index(&self, index: usize) -> &$col_ty {
&self.columns[index]
}
}
impl std::ops::IndexMut<usize> for $mat {
fn index_mut(&mut self, index: usize) -> &mut $col_ty {
&mut self.columns[index]
}
}
impl std::ops::Index<u32> for $mat {
type Output = $col_ty;
fn index(&self, index: u32) -> &$col_ty {
&self.columns[index as usize]
}
}
impl std::ops::IndexMut<u32> for $mat {
fn index_mut(&mut self, index: u32) -> &mut $col_ty {
&mut self.columns[index as usize]
}
}
};
}
impl_mat_index!(Mat2x2f, Vec2f);
impl_mat_index!(Mat2x3f, Vec3f);
impl_mat_index!(Mat2x4f, Vec4f);
impl_mat_index!(Mat3x2f, Vec2f);
impl_mat_index!(Mat3x3f, Vec3f);
impl_mat_index!(Mat3x4f, Vec4f);
impl_mat_index!(Mat4x2f, Vec2f);
impl_mat_index!(Mat4x3f, Vec3f);
impl_mat_index!(Mat4x4f, Vec4f);
impl From<glam::Mat2> for Mat2x2f {
fn from(m: glam::Mat2) -> Self {
Mat2x2f {
columns: [m.x_axis.into(), m.y_axis.into()],
}
}
}
impl From<Mat2x2f> for glam::Mat2 {
fn from(m: Mat2x2f) -> Self {
glam::Mat2::from_cols(m.columns[0].into(), m.columns[1].into())
}
}
impl From<glam::Mat3> for Mat3x3f {
fn from(m: glam::Mat3) -> Self {
Mat3x3f {
columns: [m.x_axis.into(), m.y_axis.into(), m.z_axis.into()],
}
}
}
impl From<Mat3x3f> for glam::Mat3 {
fn from(m: Mat3x3f) -> Self {
glam::Mat3::from_cols(
m.columns[0].into(),
m.columns[1].into(),
m.columns[2].into(),
)
}
}
impl From<glam::Mat4> for Mat4x4f {
fn from(m: glam::Mat4) -> Self {
Mat4x4f {
columns: [
m.x_axis.into(),
m.y_axis.into(),
m.z_axis.into(),
m.w_axis.into(),
],
}
}
}
impl From<Mat4x4f> for glam::Mat4 {
fn from(m: Mat4x4f) -> Self {
glam::Mat4::from_cols(
m.columns[0].into(),
m.columns[1].into(),
m.columns[2].into(),
m.columns[3].into(),
)
}
}
macro_rules! impl_mat_vec_mul {
($mat:ty, $vec_in:ty, $vec_out:ty, $c:tt) => {
impl std::ops::Mul<$vec_in> for $mat {
type Output = $vec_out;
fn mul(self, rhs: $vec_in) -> $vec_out {
let cols = self.columns;
impl_mat_vec_mul!(@combine $c, cols, rhs)
}
}
};
(@combine 2, $cols:ident, $v:ident) => {
$cols[0] * $v.x + $cols[1] * $v.y
};
(@combine 3, $cols:ident, $v:ident) => {
$cols[0] * $v.x + $cols[1] * $v.y + $cols[2] * $v.z
};
(@combine 4, $cols:ident, $v:ident) => {
$cols[0] * $v.x + $cols[1] * $v.y + $cols[2] * $v.z + $cols[3] * $v.w
};
}
impl_mat_vec_mul!(Mat2x2f, Vec2f, Vec2f, 2);
impl_mat_vec_mul!(Mat2x3f, Vec2f, Vec3f, 2);
impl_mat_vec_mul!(Mat2x4f, Vec2f, Vec4f, 2);
impl_mat_vec_mul!(Mat3x2f, Vec3f, Vec2f, 3);
impl_mat_vec_mul!(Mat3x3f, Vec3f, Vec3f, 3);
impl_mat_vec_mul!(Mat3x4f, Vec3f, Vec4f, 3);
impl_mat_vec_mul!(Mat4x2f, Vec4f, Vec2f, 4);
impl_mat_vec_mul!(Mat4x3f, Vec4f, Vec3f, 4);
impl_mat_vec_mul!(Mat4x4f, Vec4f, Vec4f, 4);
macro_rules! impl_vec_mat_mul {
($vec:ty, $mat:ty, $vec_out:ty, $c:tt, $r:tt) => {
impl std::ops::Mul<$mat> for $vec {
type Output = $vec_out;
fn mul(self, rhs: $mat) -> $vec_out {
let cols = rhs.columns;
let s = self;
impl_vec_mat_mul!(@col $c, $r, cols, s)
}
}
};
(@col 2, $r:tt, $cols:ident, $s:ident) => {
Vec2 {
x: impl_vec_mat_mul!(@dot $r, $s, $cols[0]),
y: impl_vec_mat_mul!(@dot $r, $s, $cols[1]),
}
};
(@col 3, $r:tt, $cols:ident, $s:ident) => {
Vec3 {
x: impl_vec_mat_mul!(@dot $r, $s, $cols[0]),
y: impl_vec_mat_mul!(@dot $r, $s, $cols[1]),
z: impl_vec_mat_mul!(@dot $r, $s, $cols[2]),
}
};
(@col 4, $r:tt, $cols:ident, $s:ident) => {
Vec4 {
x: impl_vec_mat_mul!(@dot $r, $s, $cols[0]),
y: impl_vec_mat_mul!(@dot $r, $s, $cols[1]),
z: impl_vec_mat_mul!(@dot $r, $s, $cols[2]),
w: impl_vec_mat_mul!(@dot $r, $s, $cols[3]),
}
};
(@dot 2, $s:ident, $col:expr) => {
$s.x * $col.x + $s.y * $col.y
};
(@dot 3, $s:ident, $col:expr) => {
$s.x * $col.x + $s.y * $col.y + $s.z * $col.z
};
(@dot 4, $s:ident, $col:expr) => {
$s.x * $col.x + $s.y * $col.y + $s.z * $col.z + $s.w * $col.w
};
}
impl_vec_mat_mul!(Vec2f, Mat2x2f, Vec2f, 2, 2);
impl_vec_mat_mul!(Vec2f, Mat3x2f, Vec3f, 3, 2);
impl_vec_mat_mul!(Vec2f, Mat4x2f, Vec4f, 4, 2);
impl_vec_mat_mul!(Vec3f, Mat2x3f, Vec2f, 2, 3);
impl_vec_mat_mul!(Vec3f, Mat3x3f, Vec3f, 3, 3);
impl_vec_mat_mul!(Vec3f, Mat4x3f, Vec4f, 4, 3);
impl_vec_mat_mul!(Vec4f, Mat2x4f, Vec2f, 2, 4);
impl_vec_mat_mul!(Vec4f, Mat3x4f, Vec3f, 3, 4);
impl_vec_mat_mul!(Vec4f, Mat4x4f, Vec4f, 4, 4);
macro_rules! impl_mat_mat_mul {
($a:ty, $b:ty, $out:ty, $c:tt) => {
impl std::ops::Mul<$b> for $a {
type Output = $out;
fn mul(self, rhs: $b) -> $out {
type Out = $out;
let cols = rhs.columns;
Out {
columns: impl_mat_mat_mul!(@cols $c, self, cols),
}
}
}
};
(@cols 2, $self:ident, $cols:ident) => {
[$self * $cols[0], $self * $cols[1]]
};
(@cols 3, $self:ident, $cols:ident) => {
[$self * $cols[0], $self * $cols[1], $self * $cols[2]]
};
(@cols 4, $self:ident, $cols:ident) => {
[
$self * $cols[0],
$self * $cols[1],
$self * $cols[2],
$self * $cols[3],
]
};
}
impl_mat_mat_mul!(Mat2x2f, Mat2x2f, Mat2x2f, 2);
impl_mat_mat_mul!(Mat2x2f, Mat3x2f, Mat3x2f, 3);
impl_mat_mat_mul!(Mat2x2f, Mat4x2f, Mat4x2f, 4);
impl_mat_mat_mul!(Mat2x3f, Mat2x2f, Mat2x3f, 2);
impl_mat_mat_mul!(Mat2x3f, Mat3x2f, Mat3x3f, 3);
impl_mat_mat_mul!(Mat2x3f, Mat4x2f, Mat4x3f, 4);
impl_mat_mat_mul!(Mat2x4f, Mat2x2f, Mat2x4f, 2);
impl_mat_mat_mul!(Mat2x4f, Mat3x2f, Mat3x4f, 3);
impl_mat_mat_mul!(Mat2x4f, Mat4x2f, Mat4x4f, 4);
impl_mat_mat_mul!(Mat3x2f, Mat2x3f, Mat2x2f, 2);
impl_mat_mat_mul!(Mat3x2f, Mat3x3f, Mat3x2f, 3);
impl_mat_mat_mul!(Mat3x2f, Mat4x3f, Mat4x2f, 4);
impl_mat_mat_mul!(Mat3x3f, Mat2x3f, Mat2x3f, 2);
impl_mat_mat_mul!(Mat3x3f, Mat3x3f, Mat3x3f, 3);
impl_mat_mat_mul!(Mat3x3f, Mat4x3f, Mat4x3f, 4);
impl_mat_mat_mul!(Mat3x4f, Mat2x3f, Mat2x4f, 2);
impl_mat_mat_mul!(Mat3x4f, Mat3x3f, Mat3x4f, 3);
impl_mat_mat_mul!(Mat3x4f, Mat4x3f, Mat4x4f, 4);
impl_mat_mat_mul!(Mat4x2f, Mat2x4f, Mat2x2f, 2);
impl_mat_mat_mul!(Mat4x2f, Mat3x4f, Mat3x2f, 3);
impl_mat_mat_mul!(Mat4x2f, Mat4x4f, Mat4x2f, 4);
impl_mat_mat_mul!(Mat4x3f, Mat2x4f, Mat2x3f, 2);
impl_mat_mat_mul!(Mat4x3f, Mat3x4f, Mat3x3f, 3);
impl_mat_mat_mul!(Mat4x3f, Mat4x4f, Mat4x3f, 4);
impl_mat_mat_mul!(Mat4x4f, Mat2x4f, Mat2x4f, 2);
impl_mat_mat_mul!(Mat4x4f, Mat3x4f, Mat3x4f, 3);
impl_mat_mat_mul!(Mat4x4f, Mat4x4f, Mat4x4f, 4);
impl std::ops::Mul<f32> for Mat2x2f {
type Output = Mat2x2f;
fn mul(self, rhs: f32) -> Mat2x2f {
let g: glam::Mat2 = self.into();
(g * rhs).into()
}
}
impl std::ops::Mul<Mat2x2f> for f32 {
type Output = Mat2x2f;
fn mul(self, rhs: Mat2x2f) -> Mat2x2f {
let g: glam::Mat2 = rhs.into();
(self * g).into()
}
}
impl std::ops::Mul<f32> for Mat3x3f {
type Output = Mat3x3f;
fn mul(self, rhs: f32) -> Mat3x3f {
let g: glam::Mat3 = self.into();
(g * rhs).into()
}
}
impl std::ops::Mul<Mat3x3f> for f32 {
type Output = Mat3x3f;
fn mul(self, rhs: Mat3x3f) -> Mat3x3f {
let g: glam::Mat3 = rhs.into();
(self * g).into()
}
}
impl std::ops::Mul<f32> for Mat4x4f {
type Output = Mat4x4f;
fn mul(self, rhs: f32) -> Mat4x4f {
let g: glam::Mat4 = self.into();
(g * rhs).into()
}
}
impl std::ops::Mul<Mat4x4f> for f32 {
type Output = Mat4x4f;
fn mul(self, rhs: Mat4x4f) -> Mat4x4f {
let g: glam::Mat4 = rhs.into();
(self * g).into()
}
}
macro_rules! impl_mat_scalar_mul {
($mat:ty) => {
impl std::ops::Mul<f32> for $mat {
type Output = $mat;
fn mul(self, rhs: f32) -> $mat {
type Out = $mat;
let cols = self.columns;
Out {
columns: cols.map(|c| c * rhs),
}
}
}
impl std::ops::Mul<$mat> for f32 {
type Output = $mat;
fn mul(self, rhs: $mat) -> $mat {
rhs * self
}
}
};
}
impl_mat_scalar_mul!(Mat2x3f);
impl_mat_scalar_mul!(Mat2x4f);
impl_mat_scalar_mul!(Mat3x2f);
impl_mat_scalar_mul!(Mat3x4f);
impl_mat_scalar_mul!(Mat4x2f);
impl_mat_scalar_mul!(Mat4x3f);
macro_rules! impl_mat_scalar_mul_assign {
($mat:ty) => {
impl std::ops::MulAssign<f32> for $mat {
fn mul_assign(&mut self, rhs: f32) {
*self = *self * rhs;
}
}
};
}
impl_mat_scalar_mul_assign!(Mat2x2f);
impl_mat_scalar_mul_assign!(Mat2x3f);
impl_mat_scalar_mul_assign!(Mat2x4f);
impl_mat_scalar_mul_assign!(Mat3x2f);
impl_mat_scalar_mul_assign!(Mat3x3f);
impl_mat_scalar_mul_assign!(Mat3x4f);
impl_mat_scalar_mul_assign!(Mat4x2f);
impl_mat_scalar_mul_assign!(Mat4x3f);
impl_mat_scalar_mul_assign!(Mat4x4f);
macro_rules! impl_mat_add_sub {
($mat:ty) => {
impl std::ops::Add for $mat {
type Output = $mat;
fn add(self, rhs: $mat) -> $mat {
type Out = $mat;
let cols = self.columns;
let rhs_cols = rhs.columns;
Out {
columns: std::array::from_fn(|i| cols[i] + rhs_cols[i]),
}
}
}
impl std::ops::Sub for $mat {
type Output = $mat;
fn sub(self, rhs: $mat) -> $mat {
type Out = $mat;
let cols = self.columns;
let rhs_cols = rhs.columns;
Out {
columns: std::array::from_fn(|i| cols[i] - rhs_cols[i]),
}
}
}
};
}
macro_rules! impl_mat_add_sub_assign {
($mat:ty) => {
impl std::ops::AddAssign for $mat {
fn add_assign(&mut self, rhs: $mat) {
*self = *self + rhs;
}
}
impl std::ops::SubAssign for $mat {
fn sub_assign(&mut self, rhs: $mat) {
*self = *self - rhs;
}
}
};
}
macro_rules! impl_mat_mat_mul_assign {
($mat:ty) => {
impl std::ops::MulAssign for $mat {
fn mul_assign(&mut self, rhs: $mat) {
*self = *self * rhs;
}
}
};
}
impl_mat_add_sub!(Mat2x2f);
impl_mat_add_sub!(Mat2x3f);
impl_mat_add_sub!(Mat2x4f);
impl_mat_add_sub!(Mat3x2f);
impl_mat_add_sub!(Mat3x3f);
impl_mat_add_sub!(Mat3x4f);
impl_mat_add_sub!(Mat4x2f);
impl_mat_add_sub!(Mat4x3f);
impl_mat_add_sub!(Mat4x4f);
impl_mat_add_sub_assign!(Mat2x2f);
impl_mat_add_sub_assign!(Mat2x3f);
impl_mat_add_sub_assign!(Mat2x4f);
impl_mat_add_sub_assign!(Mat3x2f);
impl_mat_add_sub_assign!(Mat3x3f);
impl_mat_add_sub_assign!(Mat3x4f);
impl_mat_add_sub_assign!(Mat4x2f);
impl_mat_add_sub_assign!(Mat4x3f);
impl_mat_add_sub_assign!(Mat4x4f);
impl_mat_mat_mul_assign!(Mat2x2f);
impl_mat_mat_mul_assign!(Mat3x3f);
impl_mat_mat_mul_assign!(Mat4x4f);
pub trait NumericBuiltinDeterminant {
type Scalar;
fn determinant(self) -> Self::Scalar;
}
pub fn determinant<T: NumericBuiltinDeterminant>(e: T) -> T::Scalar {
<T as NumericBuiltinDeterminant>::determinant(e)
}
impl NumericBuiltinDeterminant for Mat2x2f {
type Scalar = f32;
fn determinant(self) -> f32 {
let g: glam::Mat2 = self.into();
g.determinant()
}
}
impl NumericBuiltinDeterminant for Mat3x3f {
type Scalar = f32;
fn determinant(self) -> f32 {
let g: glam::Mat3 = self.into();
g.determinant()
}
}
impl NumericBuiltinDeterminant for Mat4x4f {
type Scalar = f32;
fn determinant(self) -> f32 {
let g: glam::Mat4 = self.into();
g.determinant()
}
}
pub trait NumericBuiltinTranspose {
type Output;
fn transpose(self) -> Self::Output;
}
pub fn transpose<T: NumericBuiltinTranspose>(e: T) -> T::Output {
<T as NumericBuiltinTranspose>::transpose(e)
}
impl NumericBuiltinTranspose for Mat2x2f {
type Output = Mat2x2f;
fn transpose(self) -> Mat2x2f {
let g: glam::Mat2 = self.into();
g.transpose().into()
}
}
impl NumericBuiltinTranspose for Mat3x3f {
type Output = Mat3x3f;
fn transpose(self) -> Mat3x3f {
let g: glam::Mat3 = self.into();
g.transpose().into()
}
}
impl NumericBuiltinTranspose for Mat4x4f {
type Output = Mat4x4f;
fn transpose(self) -> Mat4x4f {
let g: glam::Mat4 = self.into();
g.transpose().into()
}
}
impl NumericBuiltinTranspose for Mat2x3f {
type Output = Mat3x2f;
fn transpose(self) -> Mat3x2f {
let [c0, c1] = self.columns;
Mat3x2f {
columns: [vec2f(c0.x, c1.x), vec2f(c0.y, c1.y), vec2f(c0.z, c1.z)],
}
}
}
impl NumericBuiltinTranspose for Mat3x2f {
type Output = Mat2x3f;
fn transpose(self) -> Mat2x3f {
let [c0, c1, c2] = self.columns;
Mat2x3f {
columns: [vec3f(c0.x, c1.x, c2.x), vec3f(c0.y, c1.y, c2.y)],
}
}
}
impl NumericBuiltinTranspose for Mat4x3f {
type Output = Mat3x4f;
fn transpose(self) -> Mat3x4f {
let [c0, c1, c2, c3] = self.columns;
Mat3x4f {
columns: [
vec4f(c0.x, c1.x, c2.x, c3.x),
vec4f(c0.y, c1.y, c2.y, c3.y),
vec4f(c0.z, c1.z, c2.z, c3.z),
],
}
}
}
impl NumericBuiltinTranspose for Mat3x4f {
type Output = Mat4x3f;
fn transpose(self) -> Mat4x3f {
let [c0, c1, c2] = self.columns;
Mat4x3f {
columns: [
vec3f(c0.x, c1.x, c2.x),
vec3f(c0.y, c1.y, c2.y),
vec3f(c0.z, c1.z, c2.z),
vec3f(c0.w, c1.w, c2.w),
],
}
}
}
impl NumericBuiltinTranspose for Mat4x2f {
type Output = Mat2x4f;
fn transpose(self) -> Mat2x4f {
let [c0, c1, c2, c3] = self.columns;
Mat2x4f {
columns: [vec4f(c0.x, c1.x, c2.x, c3.x), vec4f(c0.y, c1.y, c2.y, c3.y)],
}
}
}
impl NumericBuiltinTranspose for Mat2x4f {
type Output = Mat4x2f;
fn transpose(self) -> Mat4x2f {
let [c0, c1] = self.columns;
Mat4x2f {
columns: [
vec2f(c0.x, c1.x),
vec2f(c0.y, c1.y),
vec2f(c0.z, c1.z),
vec2f(c0.w, c1.w),
],
}
}
}
#[crate::wgsl(crate_path = crate)]
pub mod builtin_matrix_constants {
#[crate::wgsl_ignore]
use crate::std::*;
impl Mat2x2f {
pub const ZERO: Mat2x2f = mat2x2f(vec2f(0.0, 0.0), vec2f(0.0, 0.0));
pub const IDENTITY: Mat2x2f = mat2x2f(vec2f(1.0, 0.0), vec2f(0.0, 1.0));
}
impl Mat2x3f {
pub const ZERO: Mat2x3f = mat2x3f(vec3f(0.0, 0.0, 0.0), vec3f(0.0, 0.0, 0.0));
}
impl Mat2x4f {
pub const ZERO: Mat2x4f = mat2x4f(vec4f(0.0, 0.0, 0.0, 0.0), vec4f(0.0, 0.0, 0.0, 0.0));
}
impl Mat3x2f {
pub const ZERO: Mat3x2f = mat3x2f(vec2f(0.0, 0.0), vec2f(0.0, 0.0), vec2f(0.0, 0.0));
}
impl Mat3x3f {
pub const ZERO: Mat3x3f = mat3x3f(
vec3f(0.0, 0.0, 0.0),
vec3f(0.0, 0.0, 0.0),
vec3f(0.0, 0.0, 0.0),
);
pub const IDENTITY: Mat3x3f = mat3x3f(
vec3f(1.0, 0.0, 0.0),
vec3f(0.0, 1.0, 0.0),
vec3f(0.0, 0.0, 1.0),
);
}
impl Mat3x4f {
pub const ZERO: Mat3x4f = mat3x4f(
vec4f(0.0, 0.0, 0.0, 0.0),
vec4f(0.0, 0.0, 0.0, 0.0),
vec4f(0.0, 0.0, 0.0, 0.0),
);
}
impl Mat4x2f {
pub const ZERO: Mat4x2f = mat4x2f(
vec2f(0.0, 0.0),
vec2f(0.0, 0.0),
vec2f(0.0, 0.0),
vec2f(0.0, 0.0),
);
}
impl Mat4x3f {
pub const ZERO: Mat4x3f = mat4x3f(
vec3f(0.0, 0.0, 0.0),
vec3f(0.0, 0.0, 0.0),
vec3f(0.0, 0.0, 0.0),
vec3f(0.0, 0.0, 0.0),
);
}
impl Mat4x4f {
pub const ZERO: Mat4x4f = mat4x4f(
vec4f(0.0, 0.0, 0.0, 0.0),
vec4f(0.0, 0.0, 0.0, 0.0),
vec4f(0.0, 0.0, 0.0, 0.0),
vec4f(0.0, 0.0, 0.0, 0.0),
);
pub const IDENTITY: Mat4x4f = mat4x4f(
vec4f(1.0, 0.0, 0.0, 0.0),
vec4f(0.0, 1.0, 0.0, 0.0),
vec4f(0.0, 0.0, 1.0, 0.0),
vec4f(0.0, 0.0, 0.0, 1.0),
);
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn mul_assign_scales_all_columns() {
let mut m = mat2x2f(vec2f(1.0, 2.0), vec2f(3.0, 4.0));
m *= 2.0;
assert_eq!(m.columns[0].to_array(), [2.0, 4.0]);
assert_eq!(m.columns[1].to_array(), [6.0, 8.0]);
}
#[test]
fn mul_assign_non_square_matrix() {
let mut m = mat4x3f(
vec3f(1.0, 0.0, 0.0),
vec3f(0.0, 1.0, 0.0),
vec3f(0.0, 0.0, 1.0),
vec3f(1.0, 1.0, 1.0),
);
m *= 0.5;
assert_eq!(m.columns[3].to_array(), [0.5, 0.5, 0.5]);
}
#[test]
fn add_sub_assign_matches_binary_ops() {
let a = mat2x2f(vec2f(1.0, 2.0), vec2f(3.0, 4.0));
let b = mat2x2f(vec2f(0.5, 1.0), vec2f(1.5, 2.0));
let mut sum = a;
sum += b;
assert_eq!(sum.columns[0].to_array(), [1.5, 3.0]);
assert_eq!(sum.columns[1].to_array(), [4.5, 6.0]);
let mut diff = sum;
diff -= b;
assert_eq!(diff.columns[0].to_array(), [1.0, 2.0]);
assert_eq!(diff.columns[1].to_array(), [3.0, 4.0]);
let mut n = mat4x3f(
vec3f(1.0, 0.0, 0.0),
vec3f(0.0, 1.0, 0.0),
vec3f(0.0, 0.0, 1.0),
vec3f(1.0, 1.0, 1.0),
);
n += n;
assert_eq!(n.columns[3].to_array(), [2.0, 2.0, 2.0]);
let mut sq = mat2x2f(vec2f(1.0, 0.0), vec2f(0.0, 1.0));
sq *= mat2x2f(vec2f(2.0, 0.0), vec2f(0.0, 2.0));
assert_eq!(sq.columns[0].to_array(), [2.0, 0.0]);
assert_eq!(sq.columns[1].to_array(), [0.0, 2.0]);
}
#[test]
fn can_compile_module_with_matrix_compound_assignment() {
#[crate::wgsl(crate_path = crate)]
mod compound_assign {
use crate::std::*;
pub fn _main() {
let mut _m = mat2x2f(vec2f(1.0, 2.0), vec2f(3.0, 4.0));
let _n = mat2x2f(vec2f(0.5, 1.0), vec2f(1.5, 2.0));
_m *= 2.0;
_m *= _n;
_m += _n;
_m -= _n;
}
}
let src = compound_assign::WGSL_SOURCE.wgsl_source().unwrap();
assert!(src.contains("*="));
assert!(src.contains("+="));
assert!(src.contains("-="));
#[cfg(feature = "validation")]
compound_assign::WGSL_SOURCE.validate().unwrap();
}
#[test]
fn sanity_determinant_mat2() {
let m = mat2x2f(vec2f(1.0, 0.0), vec2f(0.0, 1.0));
assert_eq!(determinant(m), 1.0);
let m2 = mat2x2f(vec2f(2.0, 1.0), vec2f(1.0, 3.0));
assert!((determinant(m2) - 5.0).abs() < 1e-6);
}
#[test]
fn sanity_determinant_mat3() {
let m = mat3x3f(
vec3f(1.0, 0.0, 0.0),
vec3f(0.0, 1.0, 0.0),
vec3f(0.0, 0.0, 1.0),
);
assert_eq!(determinant(m), 1.0);
}
#[test]
fn sanity_determinant_mat4() {
let m = mat4x4f(
vec4f(1.0, 0.0, 0.0, 0.0),
vec4f(0.0, 1.0, 0.0, 0.0),
vec4f(0.0, 0.0, 1.0, 0.0),
vec4f(0.0, 0.0, 0.0, 1.0),
);
assert_eq!(determinant(m), 1.0);
}
#[test]
fn sanity_transpose_mat2() {
let m = mat2x2f(vec2f(1.0, 2.0), vec2f(3.0, 4.0));
let t = transpose(m);
assert_eq!(t.columns[0].to_array(), [1.0, 3.0]);
assert_eq!(t.columns[1].to_array(), [2.0, 4.0]);
}
#[test]
fn sanity_transpose_mat3() {
let m = mat3x3f(
vec3f(1.0, 2.0, 3.0),
vec3f(4.0, 5.0, 6.0),
vec3f(7.0, 8.0, 9.0),
);
let t = transpose(m);
assert_eq!(t.columns[0].to_array(), [1.0, 4.0, 7.0]);
assert_eq!(t.columns[1].to_array(), [2.0, 5.0, 8.0]);
assert_eq!(t.columns[2].to_array(), [3.0, 6.0, 9.0]);
}
#[test]
fn sanity_transpose_mat4() {
let m = mat4x4f(
vec4f(1.0, 2.0, 3.0, 4.0),
vec4f(5.0, 6.0, 7.0, 8.0),
vec4f(9.0, 10.0, 11.0, 12.0),
vec4f(13.0, 14.0, 15.0, 16.0),
);
let t = transpose(m);
assert_eq!(t.columns[0].to_array(), [1.0, 5.0, 9.0, 13.0]);
}
#[test]
fn sanity_transpose_mat2x3() {
let m = mat2x3f(vec3f(1.0, 2.0, 3.0), vec3f(4.0, 5.0, 6.0));
let t: Mat3x2f = transpose(m);
assert_eq!(t.columns[0].to_array(), [1.0, 4.0]);
assert_eq!(t.columns[1].to_array(), [2.0, 5.0]);
assert_eq!(t.columns[2].to_array(), [3.0, 6.0]);
}
#[test]
fn sanity_transpose_mat3x2() {
let m = mat3x2f(vec2f(1.0, 2.0), vec2f(3.0, 4.0), vec2f(5.0, 6.0));
let t: Mat2x3f = transpose(m);
assert_eq!(t.columns[0].to_array(), [1.0, 3.0, 5.0]);
assert_eq!(t.columns[1].to_array(), [2.0, 4.0, 6.0]);
}
#[test]
fn sanity_transpose_roundtrip() {
let m = mat2x3f(vec3f(1.0, 2.0, 3.0), vec3f(4.0, 5.0, 6.0));
let roundtrip = transpose(transpose(m));
assert_eq!(roundtrip.columns[0].to_array(), m.columns[0].to_array());
assert_eq!(roundtrip.columns[1].to_array(), m.columns[1].to_array());
}
#[test]
fn sanity_transpose_mat4x3() {
let m = mat4x3f(
vec3f(1.0, 2.0, 3.0),
vec3f(4.0, 5.0, 6.0),
vec3f(7.0, 8.0, 9.0),
vec3f(10.0, 11.0, 12.0),
);
let t: Mat3x4f = transpose(m);
assert_eq!(t.columns[0].to_array(), [1.0, 4.0, 7.0, 10.0]);
assert_eq!(t.columns[1].to_array(), [2.0, 5.0, 8.0, 11.0]);
assert_eq!(t.columns[2].to_array(), [3.0, 6.0, 9.0, 12.0]);
}
#[test]
fn sanity_transpose_mat4x2() {
let m = mat4x2f(
vec2f(1.0, 2.0),
vec2f(3.0, 4.0),
vec2f(5.0, 6.0),
vec2f(7.0, 8.0),
);
let t: Mat2x4f = transpose(m);
assert_eq!(t.columns[0].to_array(), [1.0, 3.0, 5.0, 7.0]);
assert_eq!(t.columns[1].to_array(), [2.0, 4.0, 6.0, 8.0]);
}
#[test]
fn sanity_transpose_mat2x4() {
let m = mat2x4f(vec4f(1.0, 2.0, 3.0, 4.0), vec4f(5.0, 6.0, 7.0, 8.0));
let t: Mat4x2f = transpose(m);
assert_eq!(t.columns[0].to_array(), [1.0, 5.0]);
assert_eq!(t.columns[1].to_array(), [2.0, 6.0]);
assert_eq!(t.columns[2].to_array(), [3.0, 7.0]);
assert_eq!(t.columns[3].to_array(), [4.0, 8.0]);
}
#[test]
fn sanity_transpose_mat3x4() {
let m = mat3x4f(
vec4f(1.0, 2.0, 3.0, 4.0),
vec4f(5.0, 6.0, 7.0, 8.0),
vec4f(9.0, 10.0, 11.0, 12.0),
);
let t: Mat4x3f = transpose(m);
assert_eq!(t.columns[0].to_array(), [1.0, 5.0, 9.0]);
assert_eq!(t.columns[1].to_array(), [2.0, 6.0, 10.0]);
assert_eq!(t.columns[2].to_array(), [3.0, 7.0, 11.0]);
assert_eq!(t.columns[3].to_array(), [4.0, 8.0, 12.0]);
}
#[test]
fn sanity_index_usize() {
let m = mat3x3f(
vec3f(1.0, 2.0, 3.0),
vec3f(4.0, 5.0, 6.0),
vec3f(7.0, 8.0, 9.0),
);
assert_eq!(m[0usize].x, 1.0);
assert_eq!(m[1usize].y, 5.0);
assert_eq!(m[2usize].z, 9.0);
}
#[test]
fn sanity_index_u32() {
let m = mat2x2f(vec2f(1.0, 2.0), vec2f(3.0, 4.0));
assert_eq!(m[0u32].x, 1.0);
assert_eq!(m[1u32].y, 4.0);
}
#[test]
fn sanity_index_mut() {
let mut m = mat2x2f(vec2f(1.0, 2.0), vec2f(3.0, 4.0));
m[0usize].x = 10.0;
assert_eq!(m[0usize].x, 10.0);
}
#[test]
fn module_modify_mat4() {
#[crate::wgsl(crate_path = crate)]
pub mod mat {
#![allow(dead_code)]
use crate::std::*;
#[derive(Wgsl)]
#[wgsl_path(crate)]
pub struct Uniforms {
pub projection: Mat4f,
pub modelview: Mat4f,
}
uniform!(group(0), binding(0), UNIFORMS: Uniforms);
pub struct VertexInput {
#[location(0)]
pub position: Vec3f,
}
pub struct VertexOutput {
#[builtin(position)]
pub clip_position: Vec4f,
}
#[vertex]
pub fn vs_main(input: VertexInput) -> VertexOutput {
let projection = get!(UNIFORMS).projection;
let mut modelview = get!(UNIFORMS).modelview;
modelview[0u32].y += 10.0;
VertexOutput {
clip_position: projection
* modelview
* vec4f(input.position.x, input.position.y, input.position.z, 1.0),
}
}
}
}
#[test]
fn mat2x2_mul_vec2() {
let m = mat2x2f(vec2f(1.0, 2.0), vec2f(3.0, 4.0));
let v = vec2f(5.0, 6.0);
let out: Vec2f = m * v;
assert_eq!(out.to_array(), [23.0, 34.0]);
}
#[test]
fn mat2x3_mul_vec2() {
let m = mat2x3f(vec3f(1.0, 2.0, 3.0), vec3f(4.0, 5.0, 6.0));
let v = vec2f(7.0, 8.0);
let out: Vec3f = m * v;
assert_eq!(out.to_array(), [39.0, 54.0, 69.0]);
}
#[test]
fn mat3x2_mul_vec3() {
let m = mat3x2f(vec2f(1.0, 2.0), vec2f(3.0, 4.0), vec2f(5.0, 6.0));
let v = vec3f(7.0, 8.0, 9.0);
let out: Vec2f = m * v;
assert_eq!(out.to_array(), [76.0, 100.0]);
}
#[test]
fn mat2x4_mul_vec2() {
let m = mat2x4f(vec4f(1.0, 2.0, 3.0, 4.0), vec4f(5.0, 6.0, 7.0, 8.0));
let v = vec2f(9.0, 10.0);
let out: Vec4f = m * v;
assert_eq!(out.to_array(), [59.0, 78.0, 97.0, 116.0]);
}
#[test]
fn mat4x2_mul_vec4() {
let m = mat4x2f(
vec2f(1.0, 2.0),
vec2f(3.0, 4.0),
vec2f(5.0, 6.0),
vec2f(7.0, 8.0),
);
let v = vec4f(9.0, 10.0, 11.0, 12.0);
let out: Vec2f = m * v;
assert_eq!(out.to_array(), [178.0, 220.0]);
}
#[test]
fn mat3x4_mul_vec3() {
let m = mat3x4f(
vec4f(1.0, 2.0, 3.0, 4.0),
vec4f(5.0, 6.0, 7.0, 8.0),
vec4f(9.0, 10.0, 11.0, 12.0),
);
let v = vec3f(13.0, 14.0, 15.0);
let out: Vec4f = m * v;
assert_eq!(out.to_array(), [218.0, 260.0, 302.0, 344.0]);
}
#[test]
fn mat4x3_mul_vec4() {
let m = mat4x3f(
vec3f(1.0, 2.0, 3.0),
vec3f(4.0, 5.0, 6.0),
vec3f(7.0, 8.0, 9.0),
vec3f(10.0, 11.0, 12.0),
);
let v = vec4f(13.0, 14.0, 15.0, 16.0);
let out: Vec3f = m * v;
assert_eq!(out.to_array(), [334.0, 392.0, 450.0]);
}
#[test]
fn vec2_mul_mat2x2() {
let v = vec2f(5.0, 6.0);
let m = mat2x2f(vec2f(1.0, 2.0), vec2f(3.0, 4.0));
let out: Vec2f = v * m;
assert_eq!(out.to_array(), [17.0, 39.0]);
}
#[test]
fn vec3_mul_mat2x3() {
let v = vec3f(9.0, 8.0, 7.0);
let m = mat2x3f(vec3f(1.0, 2.0, 3.0), vec3f(4.0, 5.0, 6.0));
let out: Vec2f = v * m;
assert_eq!(out.to_array(), [46.0, 118.0]);
}
#[test]
fn vec2_mul_mat3x2() {
let v = vec2f(7.0, 8.0);
let m = mat3x2f(vec2f(1.0, 2.0), vec2f(3.0, 4.0), vec2f(5.0, 6.0));
let out: Vec3f = v * m;
assert_eq!(out.to_array(), [23.0, 53.0, 83.0]);
}
#[test]
fn vec4_mul_mat2x4() {
let v = vec4f(9.0, 10.0, 11.0, 12.0);
let m = mat2x4f(vec4f(1.0, 2.0, 3.0, 4.0), vec4f(5.0, 6.0, 7.0, 8.0));
let out: Vec2f = v * m;
assert_eq!(out.to_array(), [110.0, 278.0]);
}
#[test]
fn vec3_mul_mat4x3() {
let v = vec3f(13.0, 14.0, 15.0);
let m = mat4x3f(
vec3f(1.0, 2.0, 3.0),
vec3f(4.0, 5.0, 6.0),
vec3f(7.0, 8.0, 9.0),
vec3f(10.0, 11.0, 12.0),
);
let out: Vec4f = v * m;
assert_eq!(out.to_array(), [86.0, 212.0, 338.0, 464.0]);
}
#[test]
fn vec_mul_mat_matches_transpose_mat_mul_vec() {
{
let v = vec2f(1.5, -2.5);
let m = mat3x2f(vec2f(0.5, 1.0), vec2f(-1.5, 2.5), vec2f(3.0, -0.5));
let lhs: Vec3f = v * m;
let mt: Mat2x3f = transpose(m);
let rhs: Vec3f = mt * v;
assert_eq!(lhs.to_array(), rhs.to_array());
}
{
let v = vec3f(1.0, 2.0, 3.0);
let m = mat2x3f(vec3f(4.0, 5.0, 6.0), vec3f(7.0, 8.0, 9.0));
let lhs: Vec2f = v * m;
let mt: Mat3x2f = transpose(m);
let rhs: Vec2f = mt * v;
assert_eq!(lhs.to_array(), rhs.to_array());
}
{
let v = vec4f(1.0, 2.0, 3.0, 4.0);
let m = mat2x4f(vec4f(5.0, 6.0, 7.0, 8.0), vec4f(9.0, 10.0, 11.0, 12.0));
let lhs: Vec2f = v * m;
let mt: Mat4x2f = transpose(m);
let rhs: Vec2f = mt * v;
assert_eq!(lhs.to_array(), rhs.to_array());
}
}
#[test]
fn mat2x2_mul_mat2x2() {
let a = mat2x2f(vec2f(1.0, 2.0), vec2f(3.0, 4.0));
let b = mat2x2f(vec2f(5.0, 6.0), vec2f(7.0, 8.0));
let out: Mat2x2f = a * b;
assert_eq!(out.columns[0].to_array(), [23.0, 34.0]);
assert_eq!(out.columns[1].to_array(), [31.0, 46.0]);
}
#[test]
fn mat2x3_mul_mat3x2() {
let a = mat2x3f(vec3f(1.0, 2.0, 3.0), vec3f(4.0, 5.0, 6.0));
let b = mat3x2f(vec2f(7.0, 8.0), vec2f(9.0, 10.0), vec2f(11.0, 12.0));
let out: Mat3x3f = a * b;
assert_eq!(out.columns[0].to_array(), [39.0, 54.0, 69.0]);
assert_eq!(out.columns[1].to_array(), [49.0, 68.0, 87.0]);
assert_eq!(out.columns[2].to_array(), [59.0, 82.0, 105.0]);
}
#[test]
fn mat3x2_mul_mat2x3() {
let a = mat3x2f(vec2f(1.0, 2.0), vec2f(3.0, 4.0), vec2f(5.0, 6.0));
let b = mat2x3f(vec3f(7.0, 8.0, 9.0), vec3f(10.0, 11.0, 12.0));
let out: Mat2x2f = a * b;
assert_eq!(out.columns[0].to_array(), [76.0, 100.0]);
assert_eq!(out.columns[1].to_array(), [103.0, 136.0]);
}
#[test]
fn mat2x3_mul_mat4x2() {
let a = mat2x3f(vec3f(1.0, 2.0, 3.0), vec3f(4.0, 5.0, 6.0));
let b = mat4x2f(
vec2f(7.0, 8.0),
vec2f(9.0, 10.0),
vec2f(11.0, 12.0),
vec2f(13.0, 14.0),
);
let out: Mat4x3f = a * b;
assert_eq!(out.columns[0].to_array(), [39.0, 54.0, 69.0]);
assert_eq!(out.columns[1].to_array(), [49.0, 68.0, 87.0]);
assert_eq!(out.columns[2].to_array(), [59.0, 82.0, 105.0]);
assert_eq!(out.columns[3].to_array(), [69.0, 96.0, 123.0]);
}
#[test]
fn mat3x4_mul_mat2x3() {
let a = mat3x4f(
vec4f(1.0, 2.0, 3.0, 4.0),
vec4f(5.0, 6.0, 7.0, 8.0),
vec4f(9.0, 10.0, 11.0, 12.0),
);
let b = mat2x3f(vec3f(13.0, 14.0, 15.0), vec3f(16.0, 17.0, 18.0));
let out: Mat2x4f = a * b;
assert_eq!(out.columns[0].to_array(), [218.0, 260.0, 302.0, 344.0]);
assert_eq!(out.columns[1].to_array(), [263.0, 314.0, 365.0, 416.0]);
}
#[test]
fn mat4x4_mul_mat4x4() {
let a = mat4x4f(
vec4f(1.0, 0.0, 0.0, 0.0),
vec4f(0.0, 1.0, 0.0, 0.0),
vec4f(0.0, 0.0, 1.0, 0.0),
vec4f(0.0, 0.0, 0.0, 1.0),
);
let b = mat4x4f(
vec4f(2.0, 3.0, 4.0, 5.0),
vec4f(6.0, 7.0, 8.0, 9.0),
vec4f(10.0, 11.0, 12.0, 13.0),
vec4f(14.0, 15.0, 16.0, 17.0),
);
let out: Mat4x4f = a * b;
assert_eq!(out.columns[0].to_array(), [2.0, 3.0, 4.0, 5.0]);
assert_eq!(out.columns[1].to_array(), [6.0, 7.0, 8.0, 9.0]);
assert_eq!(out.columns[2].to_array(), [10.0, 11.0, 12.0, 13.0]);
assert_eq!(out.columns[3].to_array(), [14.0, 15.0, 16.0, 17.0]);
}
#[test]
fn mat2x4_mul_mat4x2() {
let a = mat2x4f(vec4f(1.0, 2.0, 3.0, 4.0), vec4f(5.0, 6.0, 7.0, 8.0));
let b = mat4x2f(
vec2f(9.0, 10.0),
vec2f(11.0, 12.0),
vec2f(13.0, 14.0),
vec2f(15.0, 16.0),
);
let out: Mat4x4f = a * b;
assert_eq!(out.columns[0].to_array(), [59.0, 78.0, 97.0, 116.0]);
assert_eq!(out.columns[1].to_array(), [71.0, 94.0, 117.0, 140.0]);
assert_eq!(out.columns[2].to_array(), [83.0, 110.0, 137.0, 164.0]);
assert_eq!(out.columns[3].to_array(), [95.0, 126.0, 157.0, 188.0]);
}
#[test]
fn mat2x3_scalar_mul() {
let m = mat2x3f(vec3f(1.0, 2.0, 3.0), vec3f(4.0, 5.0, 6.0));
let out: Mat2x3f = m * 2.0;
assert_eq!(out.columns[0].to_array(), [2.0, 4.0, 6.0]);
assert_eq!(out.columns[1].to_array(), [8.0, 10.0, 12.0]);
let out2: Mat2x3f = 2.0 * m;
assert_eq!(out2.columns[0].to_array(), [2.0, 4.0, 6.0]);
assert_eq!(out2.columns[1].to_array(), [8.0, 10.0, 12.0]);
}
#[test]
fn mat4x2_scalar_mul() {
let m = mat4x2f(
vec2f(1.0, 2.0),
vec2f(3.0, 4.0),
vec2f(5.0, 6.0),
vec2f(7.0, 8.0),
);
let out: Mat4x2f = m * 3.0;
assert_eq!(out.columns[0].to_array(), [3.0, 6.0]);
assert_eq!(out.columns[3].to_array(), [21.0, 24.0]);
}
#[test]
fn module_vec_mat_mul_compiles() {
#[crate::wgsl(crate_path = crate)]
pub mod vec_mat {
#![allow(dead_code)]
use crate::std::*;
pub fn vec_times_mat(v: Vec3f, m: Mat2x3f) -> Vec2f {
v * m
}
pub fn mat_times_vec(m: Mat2x3f, v: Vec2f) -> Vec3f {
m * v
}
pub fn mat_times_mat(a: Mat2x3f, b: Mat3x2f) -> Mat3x3f {
a * b
}
}
}
#[test]
fn can_compile_module_with_all_matrix_consts() {
#[crate::wgsl(crate_path = crate)]
mod matrices {
use crate::std::*;
pub fn _main() {
let _mat2x2f_zero = Mat2x2f::ZERO;
let _mat2x2f_identity = Mat2x2f::IDENTITY;
let _mat2x3f_zero = Mat2x3f::ZERO;
let _mat2x4f_zero = Mat2x4f::ZERO;
let _mat3x2f_zero = Mat3x2f::ZERO;
let _mat3x3f_zero = Mat3x3f::ZERO;
let _mat3x3f_identity = Mat3x3f::IDENTITY;
let _mat3x4f_zero = Mat3x4f::ZERO;
let _mat4x2f_zero = Mat4x2f::ZERO;
let _mat4x3f_zero = Mat4x3f::ZERO;
let _mat4x4f_zero = Mat4x4f::ZERO;
let _mat4x4f_identity = Mat4x4f::IDENTITY;
}
}
}
}