Repository: bitshifter/glam-rs
Pull request #488 (2024-03-10 09:36:00)

Add From BVecN and BVecNA for all vector types.


Patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index a346f4e..a56554a 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -50,7 +50,7 @@ jobs:
     strategy:
       matrix:
         os: [ubuntu-latest, macos-latest, windows-latest]
-        toolchain: [1.66.1]
+        toolchain: [1.68.2]
     runs-on: ${{ matrix.os }}
     steps:
       - uses: actions/checkout@v4
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 457fe88..b418eff 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,8 +9,8 @@ The format is based on [Keep a Changelog], and this project adheres to
 
 ### Breaking changes
 
-* Minimum Supported Version of Rust bumped to 1.66.1 for `saturating_add_signed`
-  support.
+* Minimum Supported Rust Version bumped to 1.68.2 for
+ `impl From<bool> for {f32,f64}` support.
 
 ### Fixed
 
@@ -35,6 +35,8 @@ The format is based on [Keep a Changelog], and this project adheres to
  * Added `normalize_or` method to vector types that returns the specified value
    if normalization failed.
 
+ * Added `From<BVecN>` support for all vector types.
+
 ## [0.25.0] - 2023-12-19
 
 ### Breaking changes
diff --git a/Cargo.toml b/Cargo.toml
index fc14fd8..038782a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -9,7 +9,7 @@ readme = "README.md"
 license = "MIT OR Apache-2.0"
 keywords = ["gamedev", "math", "matrix", "vector", "quaternion"]
 categories = ["game-engines", "no-std"]
-rust-version = "1.66.1"
+rust-version = "1.68.2"
 
 [badges]
 maintenance = { status = "actively-developed" }
diff --git a/README.md b/README.md
index c4c9ac8..53feaa6 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
 
 [![Build Status]][github-ci] [![Coverage Status]][coveralls.io]
 [![Latest Version]][crates.io] [![docs]][docs.rs]
-[![Minimum Supported Rust Version]][Rust 1.66.1]
+[![Minimum Supported Rust Version]][Rust 1.68.2]
 
 A simple and fast 3D math library for games and graphics.
 
@@ -140,7 +140,7 @@ glam = { version = "0.25", default-features = false }
 
 ### Minimum Supported Rust Version (MSRV)
 
-The minimum supported version of Rust for `glam` is `1.66.1`.
+The minimum supported version of Rust for `glam` is `1.68.2`.
 
 ## Conventions
 
@@ -262,5 +262,5 @@ See [ATTRIBUTION.md] for details.
 [crates.io]: https://crates.io/crates/glam/
 [docs]: https://docs.rs/glam/badge.svg
 [docs.rs]: https://docs.rs/glam/
-[Minimum Supported Rust Version]: https://img.shields.io/badge/Rust-1.66.1-blue?color=fc8d62&logo=rust
-[Rust 1.66.1]: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1661-2023-01-10
+[Minimum Supported Rust Version]: https://img.shields.io/badge/Rust-1.68.2-blue?color=fc8d62&logo=rust
+[Rust 1.68.2]: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1682-2023-03-28
diff --git a/build_all_msrv.sh b/build_all_msrv.sh
index e01efbc..7963f7d 100755
--- a/build_all_msrv.sh
+++ b/build_all_msrv.sh
@@ -2,7 +2,7 @@
 
 set -e
 
-CARGO='rustup run 1.66.1 cargo'
+CARGO='rustup run 1.68.2 cargo'
 $CARGO check --features "bytemuck mint rand serde debug-glam-assert" && \
 $CARGO check --features "scalar-math bytemuck mint rand serde debug-glam-assert" && \
 $CARGO check --no-default-features --features "libm scalar-math bytemuck mint rand serde debug-glam-assert"
diff --git a/clippy.toml b/clippy.toml
index e3cc142..0c4b858 100644
--- a/clippy.toml
+++ b/clippy.toml
@@ -1,1 +1,1 @@
-msrv = "1.66.1"
+msrv = "1.68.2"
diff --git a/codegen/templates/vec.rs.tera b/codegen/templates/vec.rs.tera
index d39e0e9..1149948 100644
--- a/codegen/templates/vec.rs.tera
+++ b/codegen/templates/vec.rs.tera
@@ -98,6 +98,10 @@
     {% set from_types = ["U16Vec" ~ dim, "UVec" ~ dim] %}
     {% set try_from_types = ["I16Vec" ~ dim, "IVec" ~ dim, "I64Vec" ~ dim] %}
 {% endif %}
+{% set bvec_from_type = "BVec" ~ dim %}
+{% if dim > 2 %}
+    {% set bveca_from_type = "BVec" ~ dim ~ "A" %}
+{% endif %}
 
 {% if dim == 2 %}
     {% if scalar_t == "i16" or scalar_t == "u16" %}
@@ -128,15 +132,23 @@
     {% set zero = "0" %}
 {% endif %}
 
-{% if mask_t == "BVec4A" and scalar_t == "f32"  and is_scalar %}
-    #[cfg(feature = "scalar-math")]
-    use crate::BVec4 as BVec4A;
+{% if bveca_from_type and bveca_from_type == "BVec4A" and is_scalar %}
+    {% if scalar_t == "f32" %}
+        #[cfg(feature = "scalar-math")]
+        use crate::BVec4 as BVec4A;
+    {% endif %}
     #[cfg(not(feature = "scalar-math"))]
     use crate::BVec4A;
     use crate::{
+        {% if bveca_from_type and bveca_from_type != mask_t %}
+            {{ mask_t }},
+        {% endif %}
 {% else %}
     use crate::{
         {{ mask_t }},
+        {% if bveca_from_type and bveca_from_type != mask_t %}
+            {{ bveca_from_type }},
+        {% endif %}
 {% endif %}
     {% if self_t != vec2_t %}
         {{ vec2_t }},
@@ -170,6 +182,9 @@
             {{ ty }},
         {% endfor %}
     {% endif %}
+    {% if bvec_from_type != mask_t %}
+        {{ bvec_from_type }},
+    {% endif %}
 };
 
 #[cfg(not(target_arch = "spirv"))]
@@ -3225,3 +3240,31 @@ impl DerefMut for {{ self_t }} {
     }
     {% endfor %}
 {% endif %}
+
+impl From<{{ bvec_from_type }}> for {{ self_t }} {
+    #[inline]
+    fn from(v: {{ bvec_from_type }}) -> Self {
+        Self::new(
+            {% for c in components %}
+                {{ scalar_t }}::from(v.{{ c }}),
+            {% endfor %}
+        )
+    }
+}
+
+{% if bveca_from_type %}
+    {% if bveca_from_type == "BVec4A" %}
+    #[cfg(not(feature = "scalar-math"))]
+    {% endif %}
+    impl From<{{ bveca_from_type }}> for {{ self_t }} {
+        #[inline]
+        fn from(v: {{ bveca_from_type }}) -> Self {
+            let bool_array: [bool; {{ dim }}] = v.into();
+            Self::new(
+                {% for c in components %}
+                    {{ scalar_t }}::from(bool_array[{{ loop.index0 }}]),
+                {% endfor %}
+            )
+        }
+    }
+{% endif %}
diff --git a/src/f32/coresimd/vec3a.rs b/src/f32/coresimd/vec3a.rs
index dfe0105..338b6a1 100644
--- a/src/f32/coresimd/vec3a.rs
+++ b/src/f32/coresimd/vec3a.rs
@@ -1,6 +1,6 @@
 // Generated from vec.rs.tera template. Edit the template, not the generated file.
 
-use crate::{coresimd::*, f32::math, BVec3A, Vec2, Vec3, Vec4};
+use crate::{coresimd::*, f32::math, BVec3, BVec3A, Vec2, Vec3, Vec4};
 
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
@@ -1259,3 +1259,22 @@ impl DerefMut for Vec3A {
         unsafe { &mut *(self as *mut Self).cast() }
     }
 }
+
+impl From<BVec3> for Vec3A {
+    #[inline]
+    fn from(v: BVec3) -> Self {
+        Self::new(f32::from(v.x), f32::from(v.y), f32::from(v.z))
+    }
+}
+
+impl From<BVec3A> for Vec3A {
+    #[inline]
+    fn from(v: BVec3A) -> Self {
+        let bool_array: [bool; 3] = v.into();
+        Self::new(
+            f32::from(bool_array[0]),
+            f32::from(bool_array[1]),
+            f32::from(bool_array[2]),
+        )
+    }
+}
diff --git a/src/f32/coresimd/vec4.rs b/src/f32/coresimd/vec4.rs
index aed9d5a..57dd9a7 100644
--- a/src/f32/coresimd/vec4.rs
+++ b/src/f32/coresimd/vec4.rs
@@ -1,6 +1,6 @@
 // Generated from vec.rs.tera template. Edit the template, not the generated file.
 
-use crate::{coresimd::*, f32::math, BVec4A, Vec2, Vec3, Vec3A};
+use crate::{coresimd::*, f32::math, BVec4, BVec4A, Vec2, Vec3, Vec3A};
 
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
@@ -1182,3 +1182,30 @@ impl DerefMut for Vec4 {
         unsafe { &mut *(self as *mut Self).cast() }
     }
 }
+
+impl From<BVec4> for Vec4 {
+    #[inline]
+    fn from(v: BVec4) -> Self {
+        Self::new(
+            f32::from(v.x),
+            f32::from(v.y),
+            f32::from(v.z),
+            f32::from(v.w),
+        )
+    }
+}
+
+#[cfg(not(feature = "scalar-math"))]
+
+impl From<BVec4A> for Vec4 {
+    #[inline]
+    fn from(v: BVec4A) -> Self {
+        let bool_array: [bool; 4] = v.into();
+        Self::new(
+            f32::from(bool_array[0]),
+            f32::from(bool_array[1]),
+            f32::from(bool_array[2]),
+            f32::from(bool_array[3]),
+        )
+    }
+}
diff --git a/src/f32/scalar/vec3a.rs b/src/f32/scalar/vec3a.rs
index 0dac019..324c023 100644
--- a/src/f32/scalar/vec3a.rs
+++ b/src/f32/scalar/vec3a.rs
@@ -1,6 +1,6 @@
 // Generated from vec.rs.tera template. Edit the template, not the generated file.
 
-use crate::{f32::math, BVec3A, Vec2, Vec3, Vec4};
+use crate::{f32::math, BVec3, BVec3A, Vec2, Vec3, Vec4};
 
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
@@ -1370,3 +1370,22 @@ impl From<(Vec2, f32)> for Vec3A {
         Self::new(v.x, v.y, z)
     }
 }
+
+impl From<BVec3> for Vec3A {
+    #[inline]
+    fn from(v: BVec3) -> Self {
+        Self::new(f32::from(v.x), f32::from(v.y), f32::from(v.z))
+    }
+}
+
+impl From<BVec3A> for Vec3A {
+    #[inline]
+    fn from(v: BVec3A) -> Self {
+        let bool_array: [bool; 3] = v.into();
+        Self::new(
+            f32::from(bool_array[0]),
+            f32::from(bool_array[1]),
+            f32::from(bool_array[2]),
+        )
+    }
+}
diff --git a/src/f32/scalar/vec4.rs b/src/f32/scalar/vec4.rs
index cb2c202..b30bcc3 100644
--- a/src/f32/scalar/vec4.rs
+++ b/src/f32/scalar/vec4.rs
@@ -2,9 +2,10 @@
 
 #[cfg(feature = "scalar-math")]
 use crate::BVec4 as BVec4A;
+
 #[cfg(not(feature = "scalar-math"))]
 use crate::BVec4A;
-use crate::{f32::math, Vec2, Vec3, Vec3A};
+use crate::{f32::math, BVec4, Vec2, Vec3, Vec3A};
 
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
@@ -1381,3 +1382,30 @@ impl From<(Vec2, Vec2)> for Vec4 {
         Self::new(v.x, v.y, u.x, u.y)
     }
 }
+
+impl From<BVec4> for Vec4 {
+    #[inline]
+    fn from(v: BVec4) -> Self {
+        Self::new(
+            f32::from(v.x),
+            f32::from(v.y),
+            f32::from(v.z),
+            f32::from(v.w),
+        )
+    }
+}
+
+#[cfg(not(feature = "scalar-math"))]
+
+impl From<BVec4A> for Vec4 {
+    #[inline]
+    fn from(v: BVec4A) -> Self {
+        let bool_array: [bool; 4] = v.into();
+        Self::new(
+            f32::from(bool_array[0]),
+            f32::from(bool_array[1]),
+            f32::from(bool_array[2]),
+            f32::from(bool_array[3]),
+        )
+    }
+}
diff --git a/src/f32/sse2/vec3a.rs b/src/f32/sse2/vec3a.rs
index 2a0a8a1..dffe0d7 100644
--- a/src/f32/sse2/vec3a.rs
+++ b/src/f32/sse2/vec3a.rs
@@ -1,6 +1,6 @@
 // Generated from vec.rs.tera template. Edit the template, not the generated file.
 
-use crate::{f32::math, sse2::*, BVec3A, Vec2, Vec3, Vec4};
+use crate::{f32::math, sse2::*, BVec3, BVec3A, Vec2, Vec3, Vec4};
 
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
@@ -1347,3 +1347,22 @@ impl DerefMut for Vec3A {
         unsafe { &mut *(self as *mut Self).cast() }
     }
 }
+
+impl From<BVec3> for Vec3A {
+    #[inline]
+    fn from(v: BVec3) -> Self {
+        Self::new(f32::from(v.x), f32::from(v.y), f32::from(v.z))
+    }
+}
+
+impl From<BVec3A> for Vec3A {
+    #[inline]
+    fn from(v: BVec3A) -> Self {
+        let bool_array: [bool; 3] = v.into();
+        Self::new(
+            f32::from(bool_array[0]),
+            f32::from(bool_array[1]),
+            f32::from(bool_array[2]),
+        )
+    }
+}
diff --git a/src/f32/sse2/vec4.rs b/src/f32/sse2/vec4.rs
index 1b2e3ab..e724ff8 100644
--- a/src/f32/sse2/vec4.rs
+++ b/src/f32/sse2/vec4.rs
@@ -1,6 +1,6 @@
 // Generated from vec.rs.tera template. Edit the template, not the generated file.
 
-use crate::{f32::math, sse2::*, BVec4A, Vec2, Vec3, Vec3A};
+use crate::{f32::math, sse2::*, BVec4, BVec4A, Vec2, Vec3, Vec3A};
 
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
@@ -1268,3 +1268,30 @@ impl DerefMut for Vec4 {
         unsafe { &mut *(self as *mut Self).cast() }
     }
 }
+
+impl From<BVec4> for Vec4 {
+    #[inline]
+    fn from(v: BVec4) -> Self {
+        Self::new(
+            f32::from(v.x),
+            f32::from(v.y),
+            f32::from(v.z),
+            f32::from(v.w),
+        )
+    }
+}
+
+#[cfg(not(feature = "scalar-math"))]
+
+impl From<BVec4A> for Vec4 {
+    #[inline]
+    fn from(v: BVec4A) -> Self {
+        let bool_array: [bool; 4] = v.into();
+        Self::new(
+            f32::from(bool_array[0]),
+            f32::from(bool_array[1]),
+            f32::from(bool_array[2]),
+            f32::from(bool_array[3]),
+        )
+    }
+}
diff --git a/src/f32/vec2.rs b/src/f32/vec2.rs
index bd57c42..e826170 100644
--- a/src/f32/vec2.rs
+++ b/src/f32/vec2.rs
@@ -1232,3 +1232,10 @@ impl From<Vec2> for (f32, f32) {
         (v.x, v.y)
     }
 }
+
+impl From<BVec2> for Vec2 {
+    #[inline]
+    fn from(v: BVec2) -> Self {
+        Self::new(f32::from(v.x), f32::from(v.y))
+    }
+}
diff --git a/src/f32/vec3.rs b/src/f32/vec3.rs
index 8f0c202..a5f0248 100644
--- a/src/f32/vec3.rs
+++ b/src/f32/vec3.rs
@@ -1,6 +1,6 @@
 // Generated from vec.rs.tera template. Edit the template, not the generated file.
 
-use crate::{f32::math, BVec3, Vec2, Vec4};
+use crate::{f32::math, BVec3, BVec3A, Vec2, Vec4};
 
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
@@ -1329,3 +1329,22 @@ impl From<(Vec2, f32)> for Vec3 {
         Self::new(v.x, v.y, z)
     }
 }
+
+impl From<BVec3> for Vec3 {
+    #[inline]
+    fn from(v: BVec3) -> Self {
+        Self::new(f32::from(v.x), f32::from(v.y), f32::from(v.z))
+    }
+}
+
+impl From<BVec3A> for Vec3 {
+    #[inline]
+    fn from(v: BVec3A) -> Self {
+        let bool_array: [bool; 3] = v.into();
+        Self::new(
+            f32::from(bool_array[0]),
+            f32::from(bool_array[1]),
+            f32::from(bool_array[2]),
+        )
+    }
+}
diff --git a/src/f32/wasm32/vec3a.rs b/src/f32/wasm32/vec3a.rs
index 352a9ca..22a9e14 100644
--- a/src/f32/wasm32/vec3a.rs
+++ b/src/f32/wasm32/vec3a.rs
@@ -1,6 +1,6 @@
 // Generated from vec.rs.tera template. Edit the template, not the generated file.
 
-use crate::{f32::math, wasm32::*, BVec3A, Vec2, Vec3, Vec4};
+use crate::{f32::math, wasm32::*, BVec3, BVec3A, Vec2, Vec3, Vec4};
 
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
@@ -1293,3 +1293,22 @@ impl DerefMut for Vec3A {
         unsafe { &mut *(self as *mut Self).cast() }
     }
 }
+
+impl From<BVec3> for Vec3A {
+    #[inline]
+    fn from(v: BVec3) -> Self {
+        Self::new(f32::from(v.x), f32::from(v.y), f32::from(v.z))
+    }
+}
+
+impl From<BVec3A> for Vec3A {
+    #[inline]
+    fn from(v: BVec3A) -> Self {
+        let bool_array: [bool; 3] = v.into();
+        Self::new(
+            f32::from(bool_array[0]),
+            f32::from(bool_array[1]),
+            f32::from(bool_array[2]),
+        )
+    }
+}
diff --git a/src/f32/wasm32/vec4.rs b/src/f32/wasm32/vec4.rs
index c728cc3..58be199 100644
--- a/src/f32/wasm32/vec4.rs
+++ b/src/f32/wasm32/vec4.rs
@@ -1,6 +1,6 @@
 // Generated from vec.rs.tera template. Edit the template, not the generated file.
 
-use crate::{f32::math, wasm32::*, BVec4A, Vec2, Vec3, Vec3A};
+use crate::{f32::math, wasm32::*, BVec4, BVec4A, Vec2, Vec3, Vec3A};
 
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
@@ -1227,3 +1227,30 @@ impl DerefMut for Vec4 {
         unsafe { &mut *(self as *mut Self).cast() }
     }
 }
+
+impl From<BVec4> for Vec4 {
+    #[inline]
+    fn from(v: BVec4) -> Self {
+        Self::new(
+            f32::from(v.x),
+            f32::from(v.y),
+            f32::from(v.z),
+            f32::from(v.w),
+        )
+    }
+}
+
+#[cfg(not(feature = "scalar-math"))]
+
+impl From<BVec4A> for Vec4 {
+    #[inline]
+    fn from(v: BVec4A) -> Self {
+        let bool_array: [bool; 4] = v.into();
+        Self::new(
+            f32::from(bool_array[0]),
+            f32::from(bool_array[1]),
+            f32::from(bool_array[2]),
+            f32::from(bool_array[3]),
+        )
+    }
+}
diff --git a/src/f64/dvec2.rs b/src/f64/dvec2.rs
index 98f92f1..ecd27a1 100644
--- a/src/f64/dvec2.rs
+++ b/src/f64/dvec2.rs
@@ -1253,3 +1253,10 @@ impl From<UVec2> for DVec2 {
         Self::new(f64::from(v.x), f64::from(v.y))
     }
 }
+
+impl From<BVec2> for DVec2 {
+    #[inline]
+    fn from(v: BVec2) -> Self {
+        Self::new(f64::from(v.x), f64::from(v.y))
+    }
+}
diff --git a/src/f64/dvec3.rs b/src/f64/dvec3.rs
index d121395..aedcbc1 100644
--- a/src/f64/dvec3.rs
+++ b/src/f64/dvec3.rs
@@ -1,6 +1,6 @@
 // Generated from vec.rs.tera template. Edit the template, not the generated file.
 
-use crate::{f64::math, BVec3, DVec2, DVec4, IVec3, UVec3, Vec3};
+use crate::{f64::math, BVec3, BVec3A, DVec2, DVec4, IVec3, UVec3, Vec3};
 
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
@@ -1357,3 +1357,22 @@ impl From<UVec3> for DVec3 {
         Self::new(f64::from(v.x), f64::from(v.y), f64::from(v.z))
     }
 }
+
+impl From<BVec3> for DVec3 {
+    #[inline]
+    fn from(v: BVec3) -> Self {
+        Self::new(f64::from(v.x), f64::from(v.y), f64::from(v.z))
+    }
+}
+
+impl From<BVec3A> for DVec3 {
+    #[inline]
+    fn from(v: BVec3A) -> Self {
+        let bool_array: [bool; 3] = v.into();
+        Self::new(
+            f64::from(bool_array[0]),
+            f64::from(bool_array[1]),
+            f64::from(bool_array[2]),
+        )
+    }
+}
diff --git a/src/f64/dvec4.rs b/src/f64/dvec4.rs
index ea878ba..4a5d06c 100644
--- a/src/f64/dvec4.rs
+++ b/src/f64/dvec4.rs
@@ -1,5 +1,7 @@
 // Generated from vec.rs.tera template. Edit the template, not the generated file.
 
+#[cfg(not(feature = "scalar-math"))]
+use crate::BVec4A;
 use crate::{f64::math, BVec4, DVec2, DVec3, IVec4, UVec4, Vec4};
 
 #[cfg(not(target_arch = "spirv"))]
@@ -1391,3 +1393,30 @@ impl From<UVec4> for DVec4 {
         )
     }
 }
+
+impl From<BVec4> for DVec4 {
+    #[inline]
+    fn from(v: BVec4) -> Self {
+        Self::new(
+            f64::from(v.x),
+            f64::from(v.y),
+            f64::from(v.z),
+            f64::from(v.w),
+        )
+    }
+}
+
+#[cfg(not(feature = "scalar-math"))]
+
+impl From<BVec4A> for DVec4 {
+    #[inline]
+    fn from(v: BVec4A) -> Self {
+        let bool_array: [bool; 4] = v.into();
+        Self::new(
+            f64::from(bool_array[0]),
+            f64::from(bool_array[1]),
+            f64::from(bool_array[2]),
+            f64::from(bool_array[3]),
+        )
+    }
+}
diff --git a/src/i16/i16vec2.rs b/src/i16/i16vec2.rs
index 58f2442..57d1dbe 100644
--- a/src/i16/i16vec2.rs
+++ b/src/i16/i16vec2.rs
@@ -1307,3 +1307,10 @@ impl TryFrom<U64Vec2> for I16Vec2 {
         Ok(Self::new(i16::try_from(v.x)?, i16::try_from(v.y)?))
     }
 }
+
+impl From<BVec2> for I16Vec2 {
+    #[inline]
+    fn from(v: BVec2) -> Self {
+        Self::new(i16::from(v.x), i16::from(v.y))
+    }
+}
diff --git a/src/i16/i16vec3.rs b/src/i16/i16vec3.rs
index 2717065..79e7d23 100644
--- a/src/i16/i16vec3.rs
+++ b/src/i16/i16vec3.rs
@@ -1,6 +1,6 @@
 // Generated from vec.rs.tera template. Edit the template, not the generated file.
 
-use crate::{BVec3, I16Vec2, I16Vec4, I64Vec3, IVec3, U16Vec3, U64Vec3, UVec3};
+use crate::{BVec3, BVec3A, I16Vec2, I16Vec4, I64Vec3, IVec3, U16Vec3, U64Vec3, UVec3};
 
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
@@ -1431,3 +1431,22 @@ impl TryFrom<U64Vec3> for I16Vec3 {
         ))
     }
 }
+
+impl From<BVec3> for I16Vec3 {
+    #[inline]
+    fn from(v: BVec3) -> Self {
+        Self::new(i16::from(v.x), i16::from(v.y), i16::from(v.z))
+    }
+}
+
+impl From<BVec3A> for I16Vec3 {
+    #[inline]
+    fn from(v: BVec3A) -> Self {
+        let bool_array: [bool; 3] = v.into();
+        Self::new(
+            i16::from(bool_array[0]),
+            i16::from(bool_array[1]),
+            i16::from(bool_array[2]),
+        )
+    }
+}
diff --git a/src/i16/i16vec4.rs b/src/i16/i16vec4.rs
index 9b23b91..9cf1e81 100644
--- a/src/i16/i16vec4.rs
+++ b/src/i16/i16vec4.rs
@@ -1,5 +1,7 @@
 // Generated from vec.rs.tera template. Edit the template, not the generated file.
 
+#[cfg(not(feature = "scalar-math"))]
+use crate::BVec4A;
 use crate::{BVec4, I16Vec2, I16Vec3, I64Vec4, IVec4, U16Vec4, U64Vec4, UVec4};
 
 #[cfg(not(target_arch = "spirv"))]
@@ -1543,3 +1545,30 @@ impl TryFrom<U64Vec4> for I16Vec4 {
         ))
     }
 }
+
+impl From<BVec4> for I16Vec4 {
+    #[inline]
+    fn from(v: BVec4) -> Self {
+        Self::new(
+            i16::from(v.x),
+            i16::from(v.y),
+            i16::from(v.z),
+            i16::from(v.w),
+        )
+    }
+}
+
+#[cfg(not(feature = "scalar-math"))]
+
+impl From<BVec4A> for I16Vec4 {
+    #[inline]
+    fn from(v: BVec4A) -> Self {
+        let bool_array: [bool; 4] = v.into();
+        Self::new(
+            i16::from(bool_array[0]),
+            i16::from(bool_array[1]),
+            i16::from(bool_array[2]),
+            i16::from(bool_array[3]),
+        )
+    }
+}
diff --git a/src/i32/ivec2.rs b/src/i32/ivec2.rs
index 49d81d3..5a5e958 100644
--- a/src/i32/ivec2.rs
+++ b/src/i32/ivec2.rs
@@ -1303,3 +1303,10 @@ impl TryFrom<U64Vec2> for IVec2 {
         Ok(Self::new(i32::try_from(v.x)?, i32::try_from(v.y)?))
     }
 }
+
+impl From<BVec2> for IVec2 {
+    #[inline]
+    fn from(v: BVec2) -> Self {
+        Self::new(i32::from(v.x), i32::from(v.y))
+    }
+}
diff --git a/src/i32/ivec3.rs b/src/i32/ivec3.rs
index dde78ca..5107a7a 100644
--- a/src/i32/ivec3.rs
+++ b/src/i32/ivec3.rs
@@ -1,6 +1,6 @@
 // Generated from vec.rs.tera template. Edit the template, not the generated file.
 
-use crate::{BVec3, I16Vec3, I64Vec3, IVec2, IVec4, U16Vec3, U64Vec3, UVec3};
+use crate::{BVec3, BVec3A, I16Vec3, I64Vec3, IVec2, IVec4, U16Vec3, U64Vec3, UVec3};
 
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
@@ -1419,3 +1419,22 @@ impl TryFrom<U64Vec3> for IVec3 {
         ))
     }
 }
+
+impl From<BVec3> for IVec3 {
+    #[inline]
+    fn from(v: BVec3) -> Self {
+        Self::new(i32::from(v.x), i32::from(v.y), i32::from(v.z))
+    }
+}
+
+impl From<BVec3A> for IVec3 {
+    #[inline]
+    fn from(v: BVec3A) -> Self {
+        let bool_array: [bool; 3] = v.into();
+        Self::new(
+            i32::from(bool_array[0]),
+            i32::from(bool_array[1]),
+            i32::from(bool_array[2]),
+        )
+    }
+}
diff --git a/src/i32/ivec4.rs b/src/i32/ivec4.rs
index 48bff1e..4f132c2 100644
--- a/src/i32/ivec4.rs
+++ b/src/i32/ivec4.rs
@@ -1,5 +1,7 @@
 // Generated from vec.rs.tera template. Edit the template, not the generated file.
 
+#[cfg(not(feature = "scalar-math"))]
+use crate::BVec4A;
 use crate::{BVec4, I16Vec4, I64Vec4, IVec2, IVec3, U16Vec4, U64Vec4, UVec4};
 
 #[cfg(not(target_arch = "spirv"))]
@@ -1539,3 +1541,30 @@ impl TryFrom<U64Vec4> for IVec4 {
         ))
     }
 }
+
+impl From<BVec4> for IVec4 {
+    #[inline]
+    fn from(v: BVec4) -> Self {
+        Self::new(
+            i32::from(v.x),
+            i32::from(v.y),
+            i32::from(v.z),
+            i32::from(v.w),
+        )
+    }
+}
+
+#[cfg(not(feature = "scalar-math"))]
+
+impl From<BVec4A> for IVec4 {
+    #[inline]
+    fn from(v: BVec4A) -> Self {
+        let bool_array: [bool; 4] = v.into();
+        Self::new(
+            i32::from(bool_array[0]),
+            i32::from(bool_array[1]),
+            i32::from(bool_array[2]),
+            i32::from(bool_array[3]),
+        )
+    }
+}
diff --git a/src/i64/i64vec2.rs b/src/i64/i64vec2.rs
index 335d452..d5338fe 100644
--- a/src/i64/i64vec2.rs
+++ b/src/i64/i64vec2.rs
@@ -1299,3 +1299,10 @@ impl TryFrom<U64Vec2> for I64Vec2 {
         Ok(Self::new(i64::try_from(v.x)?, i64::try_from(v.y)?))
     }
 }
+
+impl From<BVec2> for I64Vec2 {
+    #[inline]
+    fn from(v: BVec2) -> Self {
+        Self::new(i64::from(v.x), i64::from(v.y))
+    }
+}
diff --git a/src/i64/i64vec3.rs b/src/i64/i64vec3.rs
index 8ac88c3..7106e21 100644
--- a/src/i64/i64vec3.rs
+++ b/src/i64/i64vec3.rs
@@ -1,6 +1,6 @@
 // Generated from vec.rs.tera template. Edit the template, not the generated file.
 
-use crate::{BVec3, I16Vec3, I64Vec2, I64Vec4, IVec3, U16Vec3, U64Vec3, UVec3};
+use crate::{BVec3, BVec3A, I16Vec3, I64Vec2, I64Vec4, IVec3, U16Vec3, U64Vec3, UVec3};
 
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
@@ -1407,3 +1407,22 @@ impl TryFrom<U64Vec3> for I64Vec3 {
         ))
     }
 }
+
+impl From<BVec3> for I64Vec3 {
+    #[inline]
+    fn from(v: BVec3) -> Self {
+        Self::new(i64::from(v.x), i64::from(v.y), i64::from(v.z))
+    }
+}
+
+impl From<BVec3A> for I64Vec3 {
+    #[inline]
+    fn from(v: BVec3A) -> Self {
+        let bool_array: [bool; 3] = v.into();
+        Self::new(
+            i64::from(bool_array[0]),
+            i64::from(bool_array[1]),
+            i64::from(bool_array[2]),
+        )
+    }
+}
diff --git a/src/i64/i64vec4.rs b/src/i64/i64vec4.rs
index 4456cc0..5835130 100644
--- a/src/i64/i64vec4.rs
+++ b/src/i64/i64vec4.rs
@@ -1,5 +1,7 @@
 // Generated from vec.rs.tera template. Edit the template, not the generated file.
 
+#[cfg(not(feature = "scalar-math"))]
+use crate::BVec4A;
 use crate::{BVec4, I16Vec4, I64Vec2, I64Vec3, IVec4, U16Vec4, U64Vec4, UVec4};
 
 #[cfg(not(target_arch = "spirv"))]
@@ -1535,3 +1537,30 @@ impl TryFrom<U64Vec4> for I64Vec4 {
         ))
     }
 }
+
+impl From<BVec4> for I64Vec4 {
+    #[inline]
+    fn from(v: BVec4) -> Self {
+        Self::new(
+            i64::from(v.x),
+            i64::from(v.y),
+            i64::from(v.z),
+            i64::from(v.w),
+        )
+    }
+}
+
+#[cfg(not(feature = "scalar-math"))]
+
+impl From<BVec4A> for I64Vec4 {
+    #[inline]
+    fn from(v: BVec4A) -> Self {
+        let bool_array: [bool; 4] = v.into();
+        Self::new(
+            i64::from(bool_array[0]),
+            i64::from(bool_array[1]),
+            i64::from(bool_array[2]),
+            i64::from(bool_array[3]),
+        )
+    }
+}
diff --git a/src/lib.rs b/src/lib.rs
index 50eb97c..1c1e14a 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -248,7 +248,7 @@ and benchmarks.
 
 ## Minimum Supported Rust Version (MSRV)
 
-The minimum supported Rust version is `1.66.1`.
+The minimum supported Rust version is `1.68.2`.
 
 */
 #![doc(html_root_url = "https://docs.rs/glam/0.25.0")]
diff --git a/src/u16/u16vec2.rs b/src/u16/u16vec2.rs
index 46fe28b..687f9cf 100644
--- a/src/u16/u16vec2.rs
+++ b/src/u16/u16vec2.rs
@@ -1167,3 +1167,10 @@ impl TryFrom<U64Vec2> for U16Vec2 {
         Ok(Self::new(u16::try_from(v.x)?, u16::try_from(v.y)?))
     }
 }
+
+impl From<BVec2> for U16Vec2 {
+    #[inline]
+    fn from(v: BVec2) -> Self {
+        Self::new(u16::from(v.x), u16::from(v.y))
+    }
+}
diff --git a/src/u16/u16vec3.rs b/src/u16/u16vec3.rs
index 7e5db69..b2ffaec 100644
--- a/src/u16/u16vec3.rs
+++ b/src/u16/u16vec3.rs
@@ -1,6 +1,6 @@
 // Generated from vec.rs.tera template. Edit the template, not the generated file.
 
-use crate::{BVec3, I16Vec3, I64Vec3, IVec3, U16Vec2, U16Vec4, U64Vec3, UVec3};
+use crate::{BVec3, BVec3A, I16Vec3, I64Vec3, IVec3, U16Vec2, U16Vec4, U64Vec3, UVec3};
 
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
@@ -1306,3 +1306,22 @@ impl TryFrom<U64Vec3> for U16Vec3 {
         ))
     }
 }
+
+impl From<BVec3> for U16Vec3 {
+    #[inline]
+    fn from(v: BVec3) -> Self {
+        Self::new(u16::from(v.x), u16::from(v.y), u16::from(v.z))
+    }
+}
+
+impl From<BVec3A> for U16Vec3 {
+    #[inline]
+    fn from(v: BVec3A) -> Self {
+        let bool_array: [bool; 3] = v.into();
+        Self::new(
+            u16::from(bool_array[0]),
+            u16::from(bool_array[1]),
+            u16::from(bool_array[2]),
+        )
+    }
+}
diff --git a/src/u16/u16vec4.rs b/src/u16/u16vec4.rs
index a6390ac..f816f9f 100644
--- a/src/u16/u16vec4.rs
+++ b/src/u16/u16vec4.rs
@@ -1,5 +1,7 @@
 // Generated from vec.rs.tera template. Edit the template, not the generated file.
 
+#[cfg(not(feature = "scalar-math"))]
+use crate::BVec4A;
 use crate::{BVec4, I16Vec4, I64Vec4, IVec4, U16Vec2, U16Vec3, U64Vec4, UVec4};
 
 #[cfg(not(target_arch = "spirv"))]
@@ -1407,3 +1409,30 @@ impl TryFrom<U64Vec4> for U16Vec4 {
         ))
     }
 }
+
+impl From<BVec4> for U16Vec4 {
+    #[inline]
+    fn from(v: BVec4) -> Self {
+        Self::new(
+            u16::from(v.x),
+            u16::from(v.y),
+            u16::from(v.z),
+            u16::from(v.w),
+        )
+    }
+}
+
+#[cfg(not(feature = "scalar-math"))]
+
+impl From<BVec4A> for U16Vec4 {
+    #[inline]
+    fn from(v: BVec4A) -> Self {
+        let bool_array: [bool; 4] = v.into();
+        Self::new(
+            u16::from(bool_array[0]),
+            u16::from(bool_array[1]),
+            u16::from(bool_array[2]),
+            u16::from(bool_array[3]),
+        )
+    }
+}
diff --git a/src/u32/uvec2.rs b/src/u32/uvec2.rs
index 70510de..26a38be 100644
--- a/src/u32/uvec2.rs
+++ b/src/u32/uvec2.rs
@@ -1165,3 +1165,10 @@ impl TryFrom<U64Vec2> for UVec2 {
         Ok(Self::new(u32::try_from(v.x)?, u32::try_from(v.y)?))
     }
 }
+
+impl From<BVec2> for UVec2 {
+    #[inline]
+    fn from(v: BVec2) -> Self {
+        Self::new(u32::from(v.x), u32::from(v.y))
+    }
+}
diff --git a/src/u32/uvec3.rs b/src/u32/uvec3.rs
index 3dadd7c..5407062 100644
--- a/src/u32/uvec3.rs
+++ b/src/u32/uvec3.rs
@@ -1,6 +1,6 @@
 // Generated from vec.rs.tera template. Edit the template, not the generated file.
 
-use crate::{BVec3, I16Vec3, I64Vec3, IVec3, U16Vec3, U64Vec3, UVec2, UVec4};
+use crate::{BVec3, BVec3A, I16Vec3, I64Vec3, IVec3, U16Vec3, U64Vec3, UVec2, UVec4};
 
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
@@ -1300,3 +1300,22 @@ impl TryFrom<U64Vec3> for UVec3 {
         ))
     }
 }
+
+impl From<BVec3> for UVec3 {
+    #[inline]
+    fn from(v: BVec3) -> Self {
+        Self::new(u32::from(v.x), u32::from(v.y), u32::from(v.z))
+    }
+}
+
+impl From<BVec3A> for UVec3 {
+    #[inline]
+    fn from(v: BVec3A) -> Self {
+        let bool_array: [bool; 3] = v.into();
+        Self::new(
+            u32::from(bool_array[0]),
+            u32::from(bool_array[1]),
+            u32::from(bool_array[2]),
+        )
+    }
+}
diff --git a/src/u32/uvec4.rs b/src/u32/uvec4.rs
index 5158c93..0fce573 100644
--- a/src/u32/uvec4.rs
+++ b/src/u32/uvec4.rs
@@ -1,5 +1,7 @@
 // Generated from vec.rs.tera template. Edit the template, not the generated file.
 
+#[cfg(not(feature = "scalar-math"))]
+use crate::BVec4A;
 use crate::{BVec4, I16Vec4, I64Vec4, IVec4, U16Vec4, U64Vec4, UVec2, UVec3};
 
 #[cfg(not(target_arch = "spirv"))]
@@ -1405,3 +1407,30 @@ impl TryFrom<U64Vec4> for UVec4 {
         ))
     }
 }
+
+impl From<BVec4> for UVec4 {
+    #[inline]
+    fn from(v: BVec4) -> Self {
+        Self::new(
+            u32::from(v.x),
+            u32::from(v.y),
+            u32::from(v.z),
+            u32::from(v.w),
+        )
+    }
+}
+
+#[cfg(not(feature = "scalar-math"))]
+
+impl From<BVec4A> for UVec4 {
+    #[inline]
+    fn from(v: BVec4A) -> Self {
+        let bool_array: [bool; 4] = v.into();
+        Self::new(
+            u32::from(bool_array[0]),
+            u32::from(bool_array[1]),
+            u32::from(bool_array[2]),
+            u32::from(bool_array[3]),
+        )
+    }
+}
diff --git a/src/u64/u64vec2.rs b/src/u64/u64vec2.rs
index 56bb4d4..987b95f 100644
--- a/src/u64/u64vec2.rs
+++ b/src/u64/u64vec2.rs
@@ -1163,3 +1163,10 @@ impl TryFrom<I64Vec2> for U64Vec2 {
         Ok(Self::new(u64::try_from(v.x)?, u64::try_from(v.y)?))
     }
 }
+
+impl From<BVec2> for U64Vec2 {
+    #[inline]
+    fn from(v: BVec2) -> Self {
+        Self::new(u64::from(v.x), u64::from(v.y))
+    }
+}
diff --git a/src/u64/u64vec3.rs b/src/u64/u64vec3.rs
index 72ba129..86b8747 100644
--- a/src/u64/u64vec3.rs
+++ b/src/u64/u64vec3.rs
@@ -1,6 +1,6 @@
 // Generated from vec.rs.tera template. Edit the template, not the generated file.
 
-use crate::{BVec3, I16Vec3, I64Vec3, IVec3, U16Vec3, U64Vec2, U64Vec4, UVec3};
+use crate::{BVec3, BVec3A, I16Vec3, I64Vec3, IVec3, U16Vec3, U64Vec2, U64Vec4, UVec3};
 
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
@@ -1294,3 +1294,22 @@ impl TryFrom<I64Vec3> for U64Vec3 {
         ))
     }
 }
+
+impl From<BVec3> for U64Vec3 {
+    #[inline]
+    fn from(v: BVec3) -> Self {
+        Self::new(u64::from(v.x), u64::from(v.y), u64::from(v.z))
+    }
+}
+
+impl From<BVec3A> for U64Vec3 {
+    #[inline]
+    fn from(v: BVec3A) -> Self {
+        let bool_array: [bool; 3] = v.into();
+        Self::new(
+            u64::from(bool_array[0]),
+            u64::from(bool_array[1]),
+            u64::from(bool_array[2]),
+        )
+    }
+}
diff --git a/src/u64/u64vec4.rs b/src/u64/u64vec4.rs
index 5674314..f47c103 100644
--- a/src/u64/u64vec4.rs
+++ b/src/u64/u64vec4.rs
@@ -1,5 +1,7 @@
 // Generated from vec.rs.tera template. Edit the template, not the generated file.
 
+#[cfg(not(feature = "scalar-math"))]
+use crate::BVec4A;
 use crate::{BVec4, I16Vec4, I64Vec4, IVec4, U16Vec4, U64Vec2, U64Vec3, UVec4};
 
 #[cfg(not(target_arch = "spirv"))]
@@ -1403,3 +1405,30 @@ impl TryFrom<I64Vec4> for U64Vec4 {
         ))
     }
 }
+
+impl From<BVec4> for U64Vec4 {
+    #[inline]
+    fn from(v: BVec4) -> Self {
+        Self::new(
+            u64::from(v.x),
+            u64::from(v.y),
+            u64::from(v.z),
+            u64::from(v.w),
+        )
+    }
+}
+
+#[cfg(not(feature = "scalar-math"))]
+
+impl From<BVec4A> for U64Vec4 {
+    #[inline]
+    fn from(v: BVec4A) -> Self {
+        let bool_array: [bool; 4] = v.into();
+        Self::new(
+            u64::from(bool_array[0]),
+            u64::from(bool_array[1]),
+            u64::from(bool_array[2]),
+            u64::from(bool_array[3]),
+        )
+    }
+}


Test patch:
diff --git a/tests/vec2.rs b/tests/vec2.rs
index fd176c9..f36f883 100644
--- a/tests/vec2.rs
+++ b/tests/vec2.rs
@@ -48,6 +48,9 @@ macro_rules! impl_vec2_tests {
             let v = $vec2::new(t.0, t.1);
             assert_eq!(t, v.into());
 
+            assert_eq!($vec2::new(1 as $t, 0 as $t), BVec2::new(true, false).into());
+            assert_eq!($vec2::new(0 as $t, 1 as $t), BVec2::new(false, true).into());
+
             assert_eq!($vec2::new(1 as $t, 0 as $t), $vec2::X);
             assert_eq!($vec2::new(0 as $t, 1 as $t), $vec2::Y);
         });
diff --git a/tests/vec3.rs b/tests/vec3.rs
index 89e4f22..108d499 100644
--- a/tests/vec3.rs
+++ b/tests/vec3.rs
@@ -50,6 +50,31 @@ macro_rules! impl_vec3_tests {
             let v = $vec3::new(t.0, t.1, t.2);
             assert_eq!(t, v.into());
 
+            assert_eq!(
+                $vec3::new(1 as $t, 0 as $t, 0 as $t),
+                glam::BVec3::new(true, false, false).into()
+            );
+            assert_eq!(
+                $vec3::new(0 as $t, 1 as $t, 0 as $t),
+                glam::BVec3::new(false, true, false).into()
+            );
+            assert_eq!(
+                $vec3::new(0 as $t, 0 as $t, 1 as $t),
+                glam::BVec3::new(false, false, true).into()
+            );
+            assert_eq!(
+                $vec3::new(1 as $t, 0 as $t, 0 as $t),
+                glam::BVec3A::new(true, false, false).into()
+            );
+            assert_eq!(
+                $vec3::new(0 as $t, 1 as $t, 0 as $t),
+                glam::BVec3A::new(false, true, false).into()
+            );
+            assert_eq!(
+                $vec3::new(0 as $t, 0 as $t, 1 as $t),
+                glam::BVec3A::new(false, false, true).into()
+            );
+
             assert_eq!($vec3::new(1 as $t, 0 as $t, 0 as $t), $vec3::X);
             assert_eq!($vec3::new(0 as $t, 1 as $t, 0 as $t), $vec3::Y);
             assert_eq!($vec3::new(0 as $t, 0 as $t, 1 as $t), $vec3::Z);
diff --git a/tests/vec4.rs b/tests/vec4.rs
index 917eb4b..29fdbac 100644
--- a/tests/vec4.rs
+++ b/tests/vec4.rs
@@ -52,6 +52,43 @@ macro_rules! impl_vec4_tests {
             let v = $vec4::new(t.0, t.1, t.2, t.3);
             assert_eq!(t, v.into());
 
+            assert_eq!(
+                $vec4::new(1 as $t, 0 as $t, 0 as $t, 0 as $t),
+                glam::BVec4::new(true, false, false, false).into()
+            );
+            assert_eq!(
+                $vec4::new(0 as $t, 1 as $t, 0 as $t, 0 as $t),
+                glam::BVec4::new(false, true, false, false).into()
+            );
+            assert_eq!(
+                $vec4::new(0 as $t, 0 as $t, 1 as $t, 0 as $t),
+                glam::BVec4::new(false, false, true, false).into()
+            );
+
+            #[cfg(not(feature = "scalar-math"))]
+            {
+                assert_eq!(
+                    $vec4::new(0 as $t, 0 as $t, 0 as $t, 1 as $t),
+                    glam::BVec4::new(false, false, false, true).into()
+                );
+                assert_eq!(
+                    $vec4::new(1 as $t, 0 as $t, 0 as $t, 0 as $t),
+                    glam::BVec4A::new(true, false, false, false).into()
+                );
+                assert_eq!(
+                    $vec4::new(0 as $t, 1 as $t, 0 as $t, 0 as $t),
+                    glam::BVec4A::new(false, true, false, false).into()
+                );
+                assert_eq!(
+                    $vec4::new(0 as $t, 0 as $t, 1 as $t, 0 as $t),
+                    glam::BVec4A::new(false, false, true, false).into()
+                );
+                assert_eq!(
+                    $vec4::new(0 as $t, 0 as $t, 0 as $t, 1 as $t),
+                    glam::BVec4A::new(false, false, false, true).into()
+                );
+            }
+
             assert_eq!($vec4::new(1 as $t, 0 as $t, 0 as $t, 0 as $t), $vec4::X);
             assert_eq!($vec4::new(0 as $t, 1 as $t, 0 as $t, 0 as $t), $vec4::Y);
             assert_eq!($vec4::new(0 as $t, 0 as $t, 1 as $t, 0 as $t), $vec4::Z);