Skip to content

Commit

Permalink
Add Mat2::from_mat3_minor and Mat3::from_mat4_minor methods (#543)
Browse files Browse the repository at this point in the history
Fixes #325
  • Loading branch information
bitshifter committed Aug 2, 2024
1 parent 0e98fbe commit c367df8
Show file tree
Hide file tree
Showing 53 changed files with 984 additions and 299 deletions.
66 changes: 66 additions & 0 deletions codegen/templates/macros.rs.tera
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,69 @@
{%- endfor -%}
)
{% endmacro make_tuple_t %}

{% macro impl_mat3_minor(mat3_t, align="") %}
/// Creates a 2x2 matrix from the minor of the given 3x3 matrix, discarding the `i`th column
/// and `j`th row.
///
/// # Panics
///
/// Panics if `i` or `j` is greater than 2.
#[inline]
#[must_use]
pub fn from_mat3{{ align }}_minor(m: {{ mat3_t }}, i: usize, j: usize) -> Self {
match (i, j) {
(0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()),
(0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()),
(0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()),
(1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()),
(1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()),
(1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()),
(2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()),
(2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()),
(2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()),
_ => panic!("index out of bounds"),
}
}
{% endmacro impl_mat3_minor %}

{% macro impl_mat4_minor(mat4_t, vec3_t) %}
{% if vec3_t == "Vec3A" %}
{% set w = "w" %}
{% set b = "Vec3A::from_vec4(" %}
{% set e = ")" %}
{% else %}
{% set w = "" %}
{% set b = "" %}
{% set e = "" %}
{% endif %}
/// Creates a 3x3 matrix from the minor of the given 4x4 matrix, discarding the `i`th column
/// and `j`th row.
///
/// # Panics
///
/// Panics if `i` or `j` is greater than 3.
#[inline]
#[must_use]
pub fn from_mat4_minor(m: {{ mat4_t }}, i: usize, j: usize) -> Self {
match (i, j) {
(0, 0) => Self::from_cols({{ b }}m.y_axis.yzw{{ w }}(){{ e }}, {{ b }}m.z_axis.yzw{{ w }}(){{ e }}, {{ b }}m.w_axis.yzw{{ w }}(){{ e }}),
(0, 1) => Self::from_cols({{ b }}m.y_axis.xzw{{ w }}(){{ e }}, {{ b }}m.z_axis.xzw{{ w }}(){{ e }}, {{ b }}m.w_axis.xzw{{ w }}(){{ e }}),
(0, 2) => Self::from_cols({{ b }}m.y_axis.xyw{{ w }}(){{ e }}, {{ b }}m.z_axis.xyw{{ w }}(){{ e }}, {{ b }}m.w_axis.xyw{{ w }}(){{ e }}),
(0, 3) => Self::from_cols({{ b }}m.y_axis.xyz{{ w }}(){{ e }}, {{ b }}m.z_axis.xyz{{ w }}(){{ e }}, {{ b }}m.w_axis.xyz{{ w }}(){{ e }}),
(1, 0) => Self::from_cols({{ b }}m.x_axis.yzw{{ w }}(){{ e }}, {{ b }}m.z_axis.yzw{{ w }}(){{ e }}, {{ b }}m.w_axis.yzw{{ w }}(){{ e }}),
(1, 1) => Self::from_cols({{ b }}m.x_axis.xzw{{ w }}(){{ e }}, {{ b }}m.z_axis.xzw{{ w }}(){{ e }}, {{ b }}m.w_axis.xzw{{ w }}(){{ e }}),
(1, 2) => Self::from_cols({{ b }}m.x_axis.xyw{{ w }}(){{ e }}, {{ b }}m.z_axis.xyw{{ w }}(){{ e }}, {{ b }}m.w_axis.xyw{{ w }}(){{ e }}),
(1, 3) => Self::from_cols({{ b }}m.x_axis.xyz{{ w }}(){{ e }}, {{ b }}m.z_axis.xyz{{ w }}(){{ e }}, {{ b }}m.w_axis.xyz{{ w }}(){{ e }}),
(2, 0) => Self::from_cols({{ b }}m.x_axis.yzw{{ w }}(){{ e }}, {{ b }}m.y_axis.yzw{{ w }}(){{ e }}, {{ b }}m.w_axis.yzw{{ w }}(){{ e }}),
(2, 1) => Self::from_cols({{ b }}m.x_axis.xzw{{ w }}(){{ e }}, {{ b }}m.y_axis.xzw{{ w }}(){{ e }}, {{ b }}m.w_axis.xzw{{ w }}(){{ e }}),
(2, 2) => Self::from_cols({{ b }}m.x_axis.xyw{{ w }}(){{ e }}, {{ b }}m.y_axis.xyw{{ w }}(){{ e }}, {{ b }}m.w_axis.xyw{{ w }}(){{ e }}),
(2, 3) => Self::from_cols({{ b }}m.x_axis.xyz{{ w }}(){{ e }}, {{ b }}m.y_axis.xyz{{ w }}(){{ e }}, {{ b }}m.w_axis.xyz{{ w }}(){{ e }}),
(3, 0) => Self::from_cols({{ b }}m.x_axis.yzw{{ w }}(){{ e }}, {{ b }}m.y_axis.yzw{{ w }}(){{ e }}, {{ b }}m.z_axis.yzw{{ w }}(){{ e }}),
(3, 1) => Self::from_cols({{ b }}m.x_axis.xzw{{ w }}(){{ e }}, {{ b }}m.y_axis.xzw{{ w }}(){{ e }}, {{ b }}m.z_axis.xzw{{ w }}(){{ e }}),
(3, 2) => Self::from_cols({{ b }}m.x_axis.xyw{{ w }}(){{ e }}, {{ b }}m.y_axis.xyw{{ w }}(){{ e }}, {{ b }}m.z_axis.xyw{{ w }}(){{ e }}),
(3, 3) => Self::from_cols({{ b }}m.x_axis.xyz{{ w }}(){{ e }}, {{ b }}m.y_axis.xyz{{ w }}(){{ e }}, {{ b }}m.z_axis.xyz{{ w }}(){{ e }}),
_ => panic!("index out of bounds"),
}
}
{% endmacro impl_mat4_minor %}
7 changes: 7 additions & 0 deletions codegen/templates/mat.rs.tera
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{% import "macros.rs.tera" as macros %}
{% import "coresimd.rs.tera" as coresimd %}
{% import "neon.rs.tera" as neon %}
{% import "sse2.rs.tera" as sse2 %}
Expand Down Expand Up @@ -437,6 +438,8 @@ impl {{ self_t }} {
Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
}

{{ macros::impl_mat3_minor(mat3_t=mat3_t) }}

{% if scalar_t == "f32" %}
/// Creates a {{ nxn }} matrix from a 3x3 matrix, discarding the 2nd row and column.
#[inline]
Expand All @@ -445,6 +448,8 @@ impl {{ self_t }} {
{# TODO: SIMD optimise #}
Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
}

{{ macros::impl_mat3_minor(mat3_t="Mat3A", align="a") }}
{% endif %}

{% elif dim == 3 %}
Expand All @@ -459,6 +464,8 @@ impl {{ self_t }} {
)
}

{{ macros::impl_mat4_minor(mat4_t=mat4_t, vec3_t=col_t) }}

/// Creates a 3D rotation matrix from the given quaternion.
///
/// # Panics
Expand Down
6 changes: 3 additions & 3 deletions codegen/templates/swizzle_impl.rs.tera
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ impl Vec{{ dim }}Swizzles for {{ self_t }} {
{% for j0 in indices | slice(end=dim) %}
{% for j1 in indices | slice(end=dim) %}
{% if i == 2 %}
{% set skip = dim == 2 and j0 == "x" and j1 == "y" %}
{% set skip = dim == 2 and j0 == 0 and j1 == 1 %}
{% if not skip %}
#[inline]
#[must_use]
Expand All @@ -64,7 +64,7 @@ impl Vec{{ dim }}Swizzles for {{ self_t }} {
{% else %}
{% for j2 in indices | slice(end=dim) %}
{% if i == 3 %}
{% set skip = dim == 3 and j0 == "x" and j1 == "y" and j2 == "z" %}
{% set skip = dim == 3 and j0 == 0 and j1 == 1 and j2 == 2 %}
{% if not skip %}
#[inline]
#[must_use]
Expand All @@ -82,7 +82,7 @@ impl Vec{{ dim }}Swizzles for {{ self_t }} {
{% endif %}
{% else %}
{% for j3 in indices | slice(end=dim) %}
{% set skip = dim == 4 and j0 == "x" and j1 == "y" and j2 == "z" and j3 == "w" %}
{% set skip = dim == 4 and j0 == 0 and j1 == 1 and j2 == 2 and j3 == 3 %}
{% if not skip %}
#[inline]
#[must_use]
Expand Down
46 changes: 46 additions & 0 deletions src/f32/coresimd/mat2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,13 +114,59 @@ impl Mat2 {
Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
}

/// Creates a 2x2 matrix from the minor of the given 3x3 matrix, discarding the `i`th column
/// and `j`th row.
///
/// # Panics
///
/// Panics if `i` or `j` is greater than 2.
#[inline]
#[must_use]
pub fn from_mat3_minor(m: Mat3, i: usize, j: usize) -> Self {
match (i, j) {
(0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()),
(0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()),
(0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()),
(1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()),
(1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()),
(1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()),
(2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()),
(2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()),
(2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()),
_ => panic!("index out of bounds"),
}
}

/// Creates a 2x2 matrix from a 3x3 matrix, discarding the 2nd row and column.
#[inline]
#[must_use]
pub fn from_mat3a(m: Mat3A) -> Self {
Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
}

/// Creates a 2x2 matrix from the minor of the given 3x3 matrix, discarding the `i`th column
/// and `j`th row.
///
/// # Panics
///
/// Panics if `i` or `j` is greater than 2.
#[inline]
#[must_use]
pub fn from_mat3a_minor(m: Mat3A, i: usize, j: usize) -> Self {
match (i, j) {
(0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()),
(0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()),
(0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()),
(1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()),
(1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()),
(1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()),
(2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()),
(2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()),
(2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()),
_ => panic!("index out of bounds"),
}
}

/// Creates a 2x2 matrix from the first 4 values in `slice`.
///
/// # Panics
Expand Down
94 changes: 94 additions & 0 deletions src/f32/coresimd/mat3a.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,100 @@ impl Mat3A {
)
}

/// Creates a 3x3 matrix from the minor of the given 4x4 matrix, discarding the `i`th column
/// and `j`th row.
///
/// # Panics
///
/// Panics if `i` or `j` is greater than 3.
#[inline]
#[must_use]
pub fn from_mat4_minor(m: Mat4, i: usize, j: usize) -> Self {
match (i, j) {
(0, 0) => Self::from_cols(
Vec3A::from_vec4(m.y_axis.yzww()),
Vec3A::from_vec4(m.z_axis.yzww()),
Vec3A::from_vec4(m.w_axis.yzww()),
),
(0, 1) => Self::from_cols(
Vec3A::from_vec4(m.y_axis.xzww()),
Vec3A::from_vec4(m.z_axis.xzww()),
Vec3A::from_vec4(m.w_axis.xzww()),
),
(0, 2) => Self::from_cols(
Vec3A::from_vec4(m.y_axis.xyww()),
Vec3A::from_vec4(m.z_axis.xyww()),
Vec3A::from_vec4(m.w_axis.xyww()),
),
(0, 3) => Self::from_cols(
Vec3A::from_vec4(m.y_axis.xyzw()),
Vec3A::from_vec4(m.z_axis.xyzw()),
Vec3A::from_vec4(m.w_axis.xyzw()),
),
(1, 0) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.yzww()),
Vec3A::from_vec4(m.z_axis.yzww()),
Vec3A::from_vec4(m.w_axis.yzww()),
),
(1, 1) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xzww()),
Vec3A::from_vec4(m.z_axis.xzww()),
Vec3A::from_vec4(m.w_axis.xzww()),
),
(1, 2) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xyww()),
Vec3A::from_vec4(m.z_axis.xyww()),
Vec3A::from_vec4(m.w_axis.xyww()),
),
(1, 3) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xyzw()),
Vec3A::from_vec4(m.z_axis.xyzw()),
Vec3A::from_vec4(m.w_axis.xyzw()),
),
(2, 0) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.yzww()),
Vec3A::from_vec4(m.y_axis.yzww()),
Vec3A::from_vec4(m.w_axis.yzww()),
),
(2, 1) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xzww()),
Vec3A::from_vec4(m.y_axis.xzww()),
Vec3A::from_vec4(m.w_axis.xzww()),
),
(2, 2) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xyww()),
Vec3A::from_vec4(m.y_axis.xyww()),
Vec3A::from_vec4(m.w_axis.xyww()),
),
(2, 3) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xyzw()),
Vec3A::from_vec4(m.y_axis.xyzw()),
Vec3A::from_vec4(m.w_axis.xyzw()),
),
(3, 0) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.yzww()),
Vec3A::from_vec4(m.y_axis.yzww()),
Vec3A::from_vec4(m.z_axis.yzww()),
),
(3, 1) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xzww()),
Vec3A::from_vec4(m.y_axis.xzww()),
Vec3A::from_vec4(m.z_axis.xzww()),
),
(3, 2) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xyww()),
Vec3A::from_vec4(m.y_axis.xyww()),
Vec3A::from_vec4(m.z_axis.xyww()),
),
(3, 3) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xyzw()),
Vec3A::from_vec4(m.y_axis.xyzw()),
Vec3A::from_vec4(m.z_axis.xyzw()),
),
_ => panic!("index out of bounds"),
}
}

/// Creates a 3D rotation matrix from the given quaternion.
///
/// # Panics
Expand Down
30 changes: 30 additions & 0 deletions src/f32/mat3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,36 @@ impl Mat3 {
)
}

/// Creates a 3x3 matrix from the minor of the given 4x4 matrix, discarding the `i`th column
/// and `j`th row.
///
/// # Panics
///
/// Panics if `i` or `j` is greater than 3.
#[inline]
#[must_use]
pub fn from_mat4_minor(m: Mat4, i: usize, j: usize) -> Self {
match (i, j) {
(0, 0) => Self::from_cols(m.y_axis.yzw(), m.z_axis.yzw(), m.w_axis.yzw()),
(0, 1) => Self::from_cols(m.y_axis.xzw(), m.z_axis.xzw(), m.w_axis.xzw()),
(0, 2) => Self::from_cols(m.y_axis.xyw(), m.z_axis.xyw(), m.w_axis.xyw()),
(0, 3) => Self::from_cols(m.y_axis.xyz(), m.z_axis.xyz(), m.w_axis.xyz()),
(1, 0) => Self::from_cols(m.x_axis.yzw(), m.z_axis.yzw(), m.w_axis.yzw()),
(1, 1) => Self::from_cols(m.x_axis.xzw(), m.z_axis.xzw(), m.w_axis.xzw()),
(1, 2) => Self::from_cols(m.x_axis.xyw(), m.z_axis.xyw(), m.w_axis.xyw()),
(1, 3) => Self::from_cols(m.x_axis.xyz(), m.z_axis.xyz(), m.w_axis.xyz()),
(2, 0) => Self::from_cols(m.x_axis.yzw(), m.y_axis.yzw(), m.w_axis.yzw()),
(2, 1) => Self::from_cols(m.x_axis.xzw(), m.y_axis.xzw(), m.w_axis.xzw()),
(2, 2) => Self::from_cols(m.x_axis.xyw(), m.y_axis.xyw(), m.w_axis.xyw()),
(2, 3) => Self::from_cols(m.x_axis.xyz(), m.y_axis.xyz(), m.w_axis.xyz()),
(3, 0) => Self::from_cols(m.x_axis.yzw(), m.y_axis.yzw(), m.z_axis.yzw()),
(3, 1) => Self::from_cols(m.x_axis.xzw(), m.y_axis.xzw(), m.z_axis.xzw()),
(3, 2) => Self::from_cols(m.x_axis.xyw(), m.y_axis.xyw(), m.z_axis.xyw()),
(3, 3) => Self::from_cols(m.x_axis.xyz(), m.y_axis.xyz(), m.z_axis.xyz()),
_ => panic!("index out of bounds"),
}
}

/// Creates a 3D rotation matrix from the given quaternion.
///
/// # Panics
Expand Down
46 changes: 46 additions & 0 deletions src/f32/neon/mat2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,13 +130,59 @@ impl Mat2 {
Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
}

/// Creates a 2x2 matrix from the minor of the given 3x3 matrix, discarding the `i`th column
/// and `j`th row.
///
/// # Panics
///
/// Panics if `i` or `j` is greater than 2.
#[inline]
#[must_use]
pub fn from_mat3_minor(m: Mat3, i: usize, j: usize) -> Self {
match (i, j) {
(0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()),
(0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()),
(0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()),
(1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()),
(1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()),
(1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()),
(2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()),
(2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()),
(2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()),
_ => panic!("index out of bounds"),
}
}

/// Creates a 2x2 matrix from a 3x3 matrix, discarding the 2nd row and column.
#[inline]
#[must_use]
pub fn from_mat3a(m: Mat3A) -> Self {
Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
}

/// Creates a 2x2 matrix from the minor of the given 3x3 matrix, discarding the `i`th column
/// and `j`th row.
///
/// # Panics
///
/// Panics if `i` or `j` is greater than 2.
#[inline]
#[must_use]
pub fn from_mat3a_minor(m: Mat3A, i: usize, j: usize) -> Self {
match (i, j) {
(0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()),
(0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()),
(0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()),
(1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()),
(1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()),
(1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()),
(2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()),
(2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()),
(2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()),
_ => panic!("index out of bounds"),
}
}

/// Creates a 2x2 matrix from the first 4 values in `slice`.
///
/// # Panics
Expand Down
Loading

0 comments on commit c367df8

Please sign in to comment.