Snap for 11421525 from 18bdbf00dc7d41bf4549b0542ced9c11d813e9b9 to simpleperf-release

Change-Id: I5683e0ee4352eb4c9aa41785575aa10d0e271a10
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 335c2d2..1991595 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -26,6 +26,11 @@
       - name: codegen
         run: cargo run --release -p codegen -- --check
 
+      - name: Build-test documentation
+        env:
+          RUSTDOCFLAGS: -Dwarnings
+        run: cargo doc --all --all-features --no-deps --document-private-items --features rkyv/size_32
+
   test:
     name: Test
     strategy:
diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml
index 6ed2dcb..e93e9c4 100644
--- a/.github/workflows/coverage.yml
+++ b/.github/workflows/coverage.yml
@@ -9,11 +9,11 @@
     steps:
       - uses: actions/checkout@v2
 
-      # - name: Install tarpaulin
-      #   run: cargo install cargo-tarpaulin
+      - name: Update nightly
+        run: rustup update nightly
 
       - name: Generate code coverage
-        run: cargo +nightly tarpaulin --timeout 120 --out Lcov --output-dir ./coverage
+        run: cargo +nightly tarpaulin --timeout 120 --out lcov --output-dir ./coverage
 
       - name: Upload to coveralls.io
         uses: coverallsapp/github-action@master
diff --git a/.gitignore b/.gitignore
index 63827e1..3da98e9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
 **/target
+*.json
 *.swp
 **/*.rs.bk
 Cargo.lock
diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md
index cee12dd..f632b7a 100644
--- a/ARCHITECTURE.md
+++ b/ARCHITECTURE.md
@@ -81,4 +81,6 @@
 
 ## Code generation
 
-See [codegen/README.md] for information on `glam`'s code generation process.
+See the [codegen README] for information on `glam`'s code generation process.
+
+[codegen README]: codegen/README.md
diff --git a/Android.bp b/Android.bp
index d0aeb60..cdf2aea 100644
--- a/Android.bp
+++ b/Android.bp
@@ -43,7 +43,7 @@
     name: "libglam",
     crate_name: "glam",
     cargo_env_compat: true,
-    cargo_pkg_version: "0.23.0",
+    cargo_pkg_version: "0.25.0",
     srcs: ["src/lib.rs"],
     edition: "2021",
     features: [
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 858f3b1..e0ff2f2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,107 @@
 The format is based on [Keep a Changelog], and this project adheres to
 [Semantic Versioning].
 
+## [0.25.0] - 2023-12-19
+
+### Breaking changes
+
+* Changed `Vec4` to always used `BVec4A` as a mask type, regardless if the
+  target architecture has SIMD support in glam. Previously this was inconsistent
+  on different hardware like ARM. This will have a slight performance cost when
+  SIMD is not available. `Vec4` will continue to use `BVec4` as a mask type when
+  the `scalar-math` feature is used.
+
+### Fixed
+
+* Made `Affine2` implement the `bytemuck::AnyBitPattern` trait instead of
+  `bytemuck::Pod` as it contains internal padding due to `Mat2` being 16 byte
+  aligned.
+
+* Updated the `core-simd` implementation to build on latest nightly.
+
+### Added
+
+* Added `to_angle` method to 2D vectors.
+
+* Added `FloatExt` trait which adds `lerp`, `inverse_lerp` and `remap` methods
+  to `f32` and `f64` types.
+
+* Added `i16` and `u16` vector types, `I16Vec2`, `I16Vec3`, `I16Vec4`,
+  `U16Vec2`, `U16Vec3` and `U16Vec4`.
+
+### Changed
+
+* Renamed `Quat::as_f64()` to `Quat::as_dquat()` and `DQuat::as_f32()` to
+  `DQuat::as_quat()` to be consistent with other types. The old methods have
+  been deprecated.
+
+* Added the `#[must_use]` attribute to all pure functions following the
+  guidelines for the Rust standard library.
+
+## [0.24.2] - 2023-09-23
+
+### Fixed
+
+* Fixed singularities in `Quat::to_euler`.
+
+### Added
+
+* Added `div_euclid` and `rem_euclid` to integer vector types.
+
+* Added wrapping and saturating arithmetic operations to integer vector types.
+
+* Added `to_scale_angle_translation` to 2D affine types.
+
+* Added `mul_assign` ops to affine types.
+
+### Changed
+
+* Disable default features on optional `rkyv` dependency.
+
+## [0.24.1] - 2023-06-24
+
+### Added
+
+* Implemented missing `bytemuck`, `mint`, `rand`, `rkyv` and `serde` traits for
+  `i64` and `u64` types.
+
+* Added missing safe `From` conversions from `f32` vectors to `f64` vectors.
+
+* Added `TryFrom` implementations between different vector types.
+
+* Added `test` and `set` methods to `bool` vector types for testing and setting
+  individual mask elements.
+
+* Added `MIN`, `MAX`, `INFINITY` and `NEG_INFINITY` vector constants.
+
+## [0.24.0] - 2023-04-24
+
+### Breaking changes
+
+* Enabling `libm` in a `std` build now overrides the `std` math functions. This
+  is unlikely to break anything but it is a change in behavior.
+
+### Added
+
+* Added `i64` and `u64` vector types; `I64Vec2`, `I64Vec3`, `I64Vec4`,
+  `U64Vec2`, `U64Vec3` and `U64Vec4`.
+
+* Added `length_squared` method on signed and unsigned integer vector types.
+
+* Added `distance_squared` method on signed integer vector types.
+
+* Implemented the `bytemuck` `AnyBitPattern` trait on `Vec3A`, `Mat3A` and
+  `Affine3A`.
+
+### Changed
+
+* Changed quaternion `to_axis_angle` for improved numerical stability.
+
+### Removed
+
+* Removed dependency on `serde_derive` for improved compile times when using
+  `serde`.
+
 ## [0.23.0] - 2023-02-22
 
 ### Breaking changes
@@ -371,7 +472,7 @@
 * Removed deprecated `zero()`, `one()`, `unit_x()`, `unit_y()`, `unit_z()`,
   `unit_w()`, `identity()` and `Mat2::scale()` methods.
 * Remove problematic `Quat` `From` trait conversions which would allow creating
-  a non-uniform quaternion without necessarily realising, including from
+  a non-uniform quaternion without necessarily realizing, including from
   `Vec4`, `(x, y, z, w)` and `[f32; 4]`.
 
 ### Added
@@ -900,7 +1001,11 @@
 
 [Keep a Changelog]: https://keepachangelog.com/
 [Semantic Versioning]: https://semver.org/spec/v2.0.0.html
-[Unreleased]: https://github.com/bitshifter/glam-rs/compare/0.23.0...HEAD
+[Unreleased]: https://github.com/bitshifter/glam-rs/compare/0.25.0...HEAD
+[0.25.0]: https://github.com/bitshifter/glam-rs/compare/0.24.2...0.25.0
+[0.24.2]: https://github.com/bitshifter/glam-rs/compare/0.24.1...0.24.2
+[0.24.1]: https://github.com/bitshifter/glam-rs/compare/0.24.0...0.24.1
+[0.24.0]: https://github.com/bitshifter/glam-rs/compare/0.23.0...0.24.0
 [0.23.0]: https://github.com/bitshifter/glam-rs/compare/0.22.0...0.23.0
 [0.22.0]: https://github.com/bitshifter/glam-rs/compare/0.21.3...0.22.0
 [0.21.3]: https://github.com/bitshifter/glam-rs/compare/0.21.2...0.21.3
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index c3d8086..571df3e 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -55,5 +55,4 @@
 [open an issue]: https://GitHub.com/bitshifter/glam-rs/issues/new
 [ask a question]: https://github.com/bitshifter/glam-rs/discussions/new?category=q-a
 [suggest a new feature]: https://github.com/bitshifter/glam-rs/discussions/new?category=ideas
-[ARCHITECTURE]: ARCHITECTURE.md
 [codegen README]: codegen/README.md
diff --git a/Cargo.toml b/Cargo.toml
index 4c95345..c34920a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,7 +13,7 @@
 edition = "2021"
 rust-version = "1.58.1"
 name = "glam"
-version = "0.23.0"
+version = "0.25.0"
 authors = ["Cameron Hart <cameron.hart@gmail.com>"]
 description = "A simple and fast 3D math library for games and graphics"
 readme = "README.md"
@@ -89,7 +89,12 @@
 default-features = false
 
 [dependencies.bytemuck]
-version = "1.5"
+version = "1.9"
+optional = true
+default-features = false
+
+[dependencies.libm]
+version = "0.2"
 optional = true
 default-features = false
 
@@ -98,11 +103,6 @@
 optional = true
 default-features = false
 
-[dependencies.num-traits]
-version = "0.2.14"
-optional = true
-default-features = false
-
 [dependencies.rand]
 version = "0.8"
 optional = true
@@ -111,16 +111,20 @@
 [dependencies.rkyv]
 version = "0.7"
 optional = true
+default-features = false
 
 [dependencies.serde]
 version = "1.0"
-features = ["derive"]
 optional = true
 default-features = false
 
 [dev-dependencies.rand_xoshiro]
 version = "0.6"
 
+[dev-dependencies.rkyv]
+version = "0.7"
+features = ["size_32"]
+
 [dev-dependencies.serde_json]
 version = "1.0"
 
@@ -131,7 +135,6 @@
 default = ["std"]
 fast-math = []
 glam-assert = []
-libm = ["num-traits/libm"]
 scalar-math = []
 std = []
 
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 15c69e1..9d8a713 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,6 +1,6 @@
 [package]
 name = "glam"
-version = "0.23.0" # remember to update html_root_url
+version = "0.25.0" # remember to update html_root_url
 edition = "2021"
 authors = ["Cameron Hart <cameron.hart@gmail.com>"]
 description = "A simple and fast 3D math library for games and graphics"
@@ -28,9 +28,6 @@
 # this is primarily for testing the fallback implementation
 scalar-math = []
 
-# libm is required when building no_std
-libm = ["num-traits/libm"]
-
 # align types to match CUDA requirements
 cuda = []
 
@@ -46,17 +43,19 @@
 
 [dependencies]
 approx = { version = "0.5", optional = true, default-features = false }
-bytemuck = { version = "1.5", optional = true, default-features = false }
+bytemuck = { version = "1.9", optional = true, default-features = false }
 mint = { version = "0.5.8", optional = true, default-features = false }
-num-traits = { version = "0.2.14", optional = true, default-features = false }
 rand = { version = "0.8", optional = true, default-features = false }
-serde = { version = "1.0", optional = true, default-features = false, features = ["derive"] }
-rkyv = { version = "0.7", optional = true }
-bytecheck = { version = "0.6", optional = true, default-features = false}
+serde = { version = "1.0", optional = true, default-features = false }
+rkyv = { version = "0.7", optional = true, default-features = false }
+bytecheck = { version = "0.6", optional = true, default-features = false }
+libm = { version = "0.2", optional = true, default-features = false}
 
 [dev-dependencies]
 # rand_xoshiro is required for tests if rand is enabled
 rand_xoshiro = "0.6"
+# Set a size_xx feature so that this crate compiles properly with --all-targets --all-features
+rkyv = { version = "0.7", features = ["size_32"] }
 serde_json = "1.0"
 
 [target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies]
diff --git a/METADATA b/METADATA
index 2e939a8..6eaa697 100644
--- a/METADATA
+++ b/METADATA
@@ -1,23 +1,20 @@
 # This project was upgraded with external_updater.
-# Usage: tools/external_updater/updater.sh update rust/crates/glam
-# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md
+# Usage: tools/external_updater/updater.sh update external/rust/crates/glam
+# For more info, check https://cs.android.com/android/platform/superproject/+/main:tools/external_updater/README.md
 
 name: "glam"
 description: "A simple and fast 3D math library for games and graphics"
 third_party {
-  url {
-    type: HOMEPAGE
-    value: "https://crates.io/crates/glam"
-  }
-  url {
-    type: ARCHIVE
-    value: "https://static.crates.io/crates/glam/glam-0.23.0.crate"
-  }
-  version: "0.23.0"
   license_type: NOTICE
   last_upgrade_date {
-    year: 2023
-    month: 3
-    day: 6
+    year: 2024
+    month: 2
+    day: 1
+  }
+  homepage: "https://crates.io/crates/glam"
+  identifier {
+    type: "Archive"
+    value: "https://static.crates.io/crates/glam/glam-0.25.0.crate"
+    version: "0.25.0"
   }
 }
diff --git a/README.md b/README.md
index 037bfb7..a6d9613 100644
--- a/README.md
+++ b/README.md
@@ -23,10 +23,18 @@
   * square matrices: `DMat2`, `DMat3` and `DMat4`
   * a quaternion type: `DQuat`
   * affine transformation types: `DAffine2` and `DAffine3`
+* `i16` types
+  * vectors: `I16Vec2`, `I16Vec3` and `I16Vec4`
+* `u16` types
+  * vectors: `U16Vec2`, `U16Vec3` and `U16Vec4`
 * `i32` types
   * vectors: `IVec2`, `IVec3` and `IVec4`
 * `u32` types
   * vectors: `UVec2`, `UVec3` and `UVec4`
+* `i64` types
+  * vectors: `I64Vec2`, `I64Vec3` and `I64Vec4`
+* `u64` types
+  * vectors: `U64Vec2`, `U64Vec3` and `U64Vec4`
 * `bool` types
   * vectors: `BVec2`, `BVec3` and `BVec4`
 
@@ -70,7 +78,7 @@
 
 ```toml
 [dependencies]
-glam = { version = "0.23", default-features = false, features = ["libm"] }
+glam = { version = "0.25", default-features = false, features = ["libm"] }
 ```
 
 To support both `std` and `no_std` builds in project, you can use the following
@@ -84,32 +92,30 @@
 libm = ["glam/libm"]
 
 [dependencies]
-glam = { version = "0.23", default-features = false }
+glam = { version = "0.25", default-features = false }
 ```
 
 ### Optional features
 
 * [`approx`] - traits and macros for approximate float comparisons
 * [`bytemuck`] - for casting into slices of bytes
-* [`libm`] - required to compile with `no_std`
+* [`libm`] - uses `libm` math functions instead of `std`, required to compile
+  with `no_std`
 * [`mint`] - for interoperating with other 3D math libraries
-* [`num-traits`] - required to compile `no_std`, will be included when enabling
-  the `libm` feature
 * [`rand`] - implementations of `Distribution` trait for all `glam` types.
 * [`serde`] - implementations of `Serialize` and `Deserialize` for all `glam`
   types. Note that serialization should work between builds of `glam` with and
   without SIMD enabled
-* [`rkyv`] - implementations of `Archive`, `Serialize` and `Deserialize` for all
-  `glam` types. Note that serialization is not interoperable with and without the
-  `scalar-math` feature. It should work between all other builds of `glam`.
-  Endian conversion is currently not supported
+* [`rkyv`] - implementations of `Archive`, `Serialize` and `Deserialize` for
+  all `glam` types. Note that serialization is not interoperable with and
+  without the `scalar-math` feature. It should work between all other builds of
+  `glam`.  Endian conversion is currently not supported
 * [`bytecheck`] - to perform archive validation when using the `rkyv` feature
 
 [`approx`]: https://docs.rs/approx
 [`bytemuck`]: https://docs.rs/bytemuck
 [`libm`]: https://github.com/rust-lang/libm
 [`mint`]: https://github.com/kvark/mint
-[`num-traits`]: https://github.com/rust-num/num-traits
 [`rand`]: https://github.com/rust-random/rand
 [`serde`]: https://serde.rs
 [`rkyv`]: https://github.com/rkyv/rkyv
@@ -213,23 +219,26 @@
 for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
 dual licensed as above, without any additional terms or conditions.
 
-Thank you to all of the `glam` [contributors]!
-
-[Code of Conduct]: https://www.rust-lang.org/en-US/conduct.html
-[contributors]: https://github.com/bitshifter/glam-rs/graphs/contributors
-
-## Support
-
 If you are interested in contributing or have a request or suggestion
 [start a discussion] on GitHub. See [CONTRIBUTING.md] for more information for
 contributors.
 
+Most code in `glam` is generated, see the [codegen README] for details.
+
+Thank you to all of the `glam` [contributors]!
+
+[Code of Conduct]: https://www.rust-lang.org/en-US/conduct.html
+[start a discussion]: https://github.com/bitshifter/glam-rs/discussions
+[CONTRIBUTING.md]: CONTRIBUTING.md
+[codegen README]: codegen/README.md
+[contributors]: https://github.com/bitshifter/glam-rs/graphs/contributors
+
+## Support
+
 The [Game Development in Rust Discord] and [Bevy Engine Discord] servers are
 not official support channels but can be good places to ask for help with
 `glam`.
 
-[start a discussion]: https://github.com/bitshifter/glam-rs/discussions
-[CONTRIBUTING.md]: CONTRIBUTING.md
 [Game Development in Rust Discord]: https://discord.gg/yNtPTb2
 [Bevy Engine Discord]: https://discord.gg/gMUk5Ph
 
diff --git a/build_and_test_features.sh b/build_and_test_features.sh
index 47d82a5..98c39a6 100755
--- a/build_and_test_features.sh
+++ b/build_and_test_features.sh
@@ -10,6 +10,8 @@
   "std scalar-math approx bytemuck mint rand serde debug-glam-assert"
   "std cuda"
   "std scalar-math cuda"
+  "std libm"
+  "std scalar-math libm"
   # no_std
   "libm"
   "libm scalar-math approx bytemuck mint rand serde debug-glam-assert"
@@ -26,4 +28,4 @@
 
 RUSTFLAGS='-C target-feature=+fma' cargo check
 
-cargo check -p glam-no_std
\ No newline at end of file
+cargo check -p glam-no_std
diff --git a/src/bool/bvec2.rs b/src/bool/bvec2.rs
index e69fcfc..e4fe0c0 100644
--- a/src/bool/bvec2.rs
+++ b/src/bool/bvec2.rs
@@ -23,12 +23,14 @@
 
     /// Creates a new vector mask.
     #[inline(always)]
+    #[must_use]
     pub const fn new(x: bool, y: bool) -> Self {
         Self { x, y }
     }
 
     /// Creates a vector with all elements set to `v`.
     #[inline]
+    #[must_use]
     pub const fn splat(v: bool) -> Self {
         Self::new(v, v)
     }
@@ -38,28 +40,58 @@
     /// A true element results in a `1` bit and a false element in a `0` bit.  Element `x` goes
     /// into the first lowest bit, element `y` into the second, etc.
     #[inline]
+    #[must_use]
     pub fn bitmask(self) -> u32 {
         (self.x as u32) | (self.y as u32) << 1
     }
 
     /// Returns true if any of the elements are true, false otherwise.
     #[inline]
+    #[must_use]
     pub fn any(self) -> bool {
         self.x || self.y
     }
 
     /// Returns true if all the elements are true, false otherwise.
     #[inline]
+    #[must_use]
     pub fn all(self) -> bool {
         self.x && self.y
     }
 
+    /// Tests the value at `index`.
+    ///
+    /// Panics if `index` is greater than 1.
     #[inline]
+    #[must_use]
+    pub fn test(&self, index: usize) -> bool {
+        match index {
+            0 => self.x,
+            1 => self.y,
+            _ => panic!("index out of bounds"),
+        }
+    }
+
+    /// Sets the element at `index`.
+    ///
+    /// Panics if `index` is greater than 1.
+    #[inline]
+    pub fn set(&mut self, index: usize, value: bool) {
+        match index {
+            0 => self.x = value,
+            1 => self.y = value,
+            _ => panic!("index out of bounds"),
+        }
+    }
+
+    #[inline]
+    #[must_use]
     fn into_bool_array(self) -> [bool; 2] {
         [self.x, self.y]
     }
 
     #[inline]
+    #[must_use]
     fn into_u32_array(self) -> [u32; 2] {
         [MASK[self.x as usize], MASK[self.y as usize]]
     }
diff --git a/src/bool/bvec3.rs b/src/bool/bvec3.rs
index 91331e2..983cd3f 100644
--- a/src/bool/bvec3.rs
+++ b/src/bool/bvec3.rs
@@ -24,12 +24,14 @@
 
     /// Creates a new vector mask.
     #[inline(always)]
+    #[must_use]
     pub const fn new(x: bool, y: bool, z: bool) -> Self {
         Self { x, y, z }
     }
 
     /// Creates a vector with all elements set to `v`.
     #[inline]
+    #[must_use]
     pub const fn splat(v: bool) -> Self {
         Self::new(v, v, v)
     }
@@ -39,28 +41,60 @@
     /// A true element results in a `1` bit and a false element in a `0` bit.  Element `x` goes
     /// into the first lowest bit, element `y` into the second, etc.
     #[inline]
+    #[must_use]
     pub fn bitmask(self) -> u32 {
         (self.x as u32) | (self.y as u32) << 1 | (self.z as u32) << 2
     }
 
     /// Returns true if any of the elements are true, false otherwise.
     #[inline]
+    #[must_use]
     pub fn any(self) -> bool {
         self.x || self.y || self.z
     }
 
     /// Returns true if all the elements are true, false otherwise.
     #[inline]
+    #[must_use]
     pub fn all(self) -> bool {
         self.x && self.y && self.z
     }
 
+    /// Tests the value at `index`.
+    ///
+    /// Panics if `index` is greater than 2.
     #[inline]
+    #[must_use]
+    pub fn test(&self, index: usize) -> bool {
+        match index {
+            0 => self.x,
+            1 => self.y,
+            2 => self.z,
+            _ => panic!("index out of bounds"),
+        }
+    }
+
+    /// Sets the element at `index`.
+    ///
+    /// Panics if `index` is greater than 2.
+    #[inline]
+    pub fn set(&mut self, index: usize, value: bool) {
+        match index {
+            0 => self.x = value,
+            1 => self.y = value,
+            2 => self.z = value,
+            _ => panic!("index out of bounds"),
+        }
+    }
+
+    #[inline]
+    #[must_use]
     fn into_bool_array(self) -> [bool; 3] {
         [self.x, self.y, self.z]
     }
 
     #[inline]
+    #[must_use]
     fn into_u32_array(self) -> [u32; 3] {
         [
             MASK[self.x as usize],
diff --git a/src/bool/bvec4.rs b/src/bool/bvec4.rs
index 7754cd4..b1e9144 100644
--- a/src/bool/bvec4.rs
+++ b/src/bool/bvec4.rs
@@ -25,12 +25,14 @@
 
     /// Creates a new vector mask.
     #[inline(always)]
+    #[must_use]
     pub const fn new(x: bool, y: bool, z: bool, w: bool) -> Self {
         Self { x, y, z, w }
     }
 
     /// Creates a vector with all elements set to `v`.
     #[inline]
+    #[must_use]
     pub const fn splat(v: bool) -> Self {
         Self::new(v, v, v, v)
     }
@@ -40,28 +42,62 @@
     /// A true element results in a `1` bit and a false element in a `0` bit.  Element `x` goes
     /// into the first lowest bit, element `y` into the second, etc.
     #[inline]
+    #[must_use]
     pub fn bitmask(self) -> u32 {
         (self.x as u32) | (self.y as u32) << 1 | (self.z as u32) << 2 | (self.w as u32) << 3
     }
 
     /// Returns true if any of the elements are true, false otherwise.
     #[inline]
+    #[must_use]
     pub fn any(self) -> bool {
         self.x || self.y || self.z || self.w
     }
 
     /// Returns true if all the elements are true, false otherwise.
     #[inline]
+    #[must_use]
     pub fn all(self) -> bool {
         self.x && self.y && self.z && self.w
     }
 
+    /// Tests the value at `index`.
+    ///
+    /// Panics if `index` is greater than 3.
     #[inline]
+    #[must_use]
+    pub fn test(&self, index: usize) -> bool {
+        match index {
+            0 => self.x,
+            1 => self.y,
+            2 => self.z,
+            3 => self.w,
+            _ => panic!("index out of bounds"),
+        }
+    }
+
+    /// Sets the element at `index`.
+    ///
+    /// Panics if `index` is greater than 3.
+    #[inline]
+    pub fn set(&mut self, index: usize, value: bool) {
+        match index {
+            0 => self.x = value,
+            1 => self.y = value,
+            2 => self.z = value,
+            3 => self.w = value,
+            _ => panic!("index out of bounds"),
+        }
+    }
+
+    #[inline]
+    #[must_use]
     fn into_bool_array(self) -> [bool; 4] {
         [self.x, self.y, self.z, self.w]
     }
 
     #[inline]
+    #[must_use]
     fn into_u32_array(self) -> [u32; 4] {
         [
             MASK[self.x as usize],
diff --git a/src/bool/coresimd/bvec3a.rs b/src/bool/coresimd/bvec3a.rs
index 79f3a57..5167672 100644
--- a/src/bool/coresimd/bvec3a.rs
+++ b/src/bool/coresimd/bvec3a.rs
@@ -6,6 +6,7 @@
 
 use core::simd::*;
 
+#[repr(C)]
 union UnionCast {
     a: [u32; 4],
     v: BVec3A,
@@ -13,8 +14,7 @@
 
 /// A 3-dimensional SIMD vector mask.
 ///
-/// This type is 16 byte aligned and is backed by a SIMD vector. If SIMD is not available
-/// `BVec3A` will be a type alias for `BVec3`.
+/// This type is 16 byte aligned.
 #[derive(Clone, Copy)]
 #[repr(transparent)]
 pub struct BVec3A(pub(crate) mask32x4);
@@ -30,6 +30,7 @@
 
     /// Creates a new vector mask.
     #[inline(always)]
+    #[must_use]
     pub const fn new(x: bool, y: bool, z: bool) -> Self {
         unsafe {
             UnionCast {
@@ -41,6 +42,7 @@
 
     /// Creates a vector with all elements set to `v`.
     #[inline]
+    #[must_use]
     pub const fn splat(v: bool) -> Self {
         Self::new(v, v, v)
     }
@@ -50,29 +52,51 @@
     /// A true element results in a `1` bit and a false element in a `0` bit.  Element `x` goes
     /// into the first lowest bit, element `y` into the second, etc.
     #[inline]
+    #[must_use]
     pub fn bitmask(self) -> u32 {
         (self.0.to_bitmask() & 0x7) as u32
     }
 
     /// Returns true if any of the elements are true, false otherwise.
     #[inline]
+    #[must_use]
     pub fn any(self) -> bool {
         self.bitmask() != 0
     }
 
     /// Returns true if all the elements are true, false otherwise.
     #[inline]
+    #[must_use]
     pub fn all(self) -> bool {
         self.bitmask() == 0x7
     }
 
+    /// Tests the value at `index`.
+    ///
+    /// Panics if `index` is greater than 2.
     #[inline]
+    #[must_use]
+    pub fn test(&self, index: usize) -> bool {
+        self.0.test(index)
+    }
+
+    /// Sets the element at `index`.
+    ///
+    /// Panics if `index` is greater than 2.
+    #[inline]
+    pub fn set(&mut self, index: usize, value: bool) {
+        self.0.set(index, value)
+    }
+
+    #[inline]
+    #[must_use]
     fn into_bool_array(self) -> [bool; 3] {
         let bitmask = self.bitmask();
         [(bitmask & 1) != 0, (bitmask & 2) != 0, (bitmask & 4) != 0]
     }
 
     #[inline]
+    #[must_use]
     fn into_u32_array(self) -> [u32; 3] {
         let bitmask = self.bitmask();
         [
diff --git a/src/bool/coresimd/bvec4a.rs b/src/bool/coresimd/bvec4a.rs
index 381ee0b..123a003 100644
--- a/src/bool/coresimd/bvec4a.rs
+++ b/src/bool/coresimd/bvec4a.rs
@@ -6,6 +6,7 @@
 
 use core::simd::*;
 
+#[repr(C)]
 union UnionCast {
     a: [u32; 4],
     v: BVec4A,
@@ -13,8 +14,7 @@
 
 /// A 4-dimensional SIMD vector mask.
 ///
-/// This type is 16 byte aligned and is backed by a SIMD vector. If SIMD is not available
-/// `BVec4A` will be a type alias for `BVec4`.
+/// This type is 16 byte aligned.
 #[derive(Clone, Copy)]
 #[repr(transparent)]
 pub struct BVec4A(pub(crate) mask32x4);
@@ -30,6 +30,7 @@
 
     /// Creates a new vector mask.
     #[inline(always)]
+    #[must_use]
     pub const fn new(x: bool, y: bool, z: bool, w: bool) -> Self {
         unsafe {
             UnionCast {
@@ -46,6 +47,7 @@
 
     /// Creates a vector with all elements set to `v`.
     #[inline]
+    #[must_use]
     pub const fn splat(v: bool) -> Self {
         Self::new(v, v, v, v)
     }
@@ -55,23 +57,44 @@
     /// A true element results in a `1` bit and a false element in a `0` bit.  Element `x` goes
     /// into the first lowest bit, element `y` into the second, etc.
     #[inline]
+    #[must_use]
     pub fn bitmask(self) -> u32 {
         self.0.to_bitmask() as u32
     }
 
     /// Returns true if any of the elements are true, false otherwise.
     #[inline]
+    #[must_use]
     pub fn any(self) -> bool {
         self.bitmask() != 0
     }
 
     /// Returns true if all the elements are true, false otherwise.
     #[inline]
+    #[must_use]
     pub fn all(self) -> bool {
         self.bitmask() == 0xf
     }
 
+    /// Tests the value at `index`.
+    ///
+    /// Panics if `index` is greater than 3.
     #[inline]
+    #[must_use]
+    pub fn test(&self, index: usize) -> bool {
+        self.0.test(index)
+    }
+
+    /// Sets the element at `index`.
+    ///
+    /// Panics if `index` is greater than 3.
+    #[inline]
+    pub fn set(&mut self, index: usize, value: bool) {
+        self.0.set(index, value)
+    }
+
+    #[inline]
+    #[must_use]
     fn into_bool_array(self) -> [bool; 4] {
         let bitmask = self.bitmask();
         [
@@ -83,6 +106,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn into_u32_array(self) -> [u32; 4] {
         let bitmask = self.bitmask();
         [
diff --git a/src/bool/scalar/bvec3a.rs b/src/bool/scalar/bvec3a.rs
index f35908c..f2dc95f 100644
--- a/src/bool/scalar/bvec3a.rs
+++ b/src/bool/scalar/bvec3a.rs
@@ -24,6 +24,7 @@
 
     /// Creates a new vector mask.
     #[inline(always)]
+    #[must_use]
     pub const fn new(x: bool, y: bool, z: bool) -> Self {
         Self {
             x: MASK[x as usize],
@@ -34,6 +35,7 @@
 
     /// Creates a vector with all elements set to `v`.
     #[inline]
+    #[must_use]
     pub const fn splat(v: bool) -> Self {
         Self::new(v, v, v)
     }
@@ -43,23 +45,54 @@
     /// A true element results in a `1` bit and a false element in a `0` bit.  Element `x` goes
     /// into the first lowest bit, element `y` into the second, etc.
     #[inline]
+    #[must_use]
     pub fn bitmask(self) -> u32 {
         (self.x & 0x1) | (self.y & 0x1) << 1 | (self.z & 0x1) << 2
     }
 
     /// Returns true if any of the elements are true, false otherwise.
     #[inline]
+    #[must_use]
     pub fn any(self) -> bool {
         ((self.x | self.y | self.z) & 0x1) != 0
     }
 
     /// Returns true if all the elements are true, false otherwise.
     #[inline]
+    #[must_use]
     pub fn all(self) -> bool {
         ((self.x & self.y & self.z) & 0x1) != 0
     }
 
+    /// Tests the value at `index`.
+    ///
+    /// Panics if `index` is greater than 2.
     #[inline]
+    #[must_use]
+    pub fn test(&self, index: usize) -> bool {
+        match index {
+            0 => (self.x & 0x1) != 0,
+            1 => (self.y & 0x1) != 0,
+            2 => (self.z & 0x1) != 0,
+            _ => panic!("index out of bounds"),
+        }
+    }
+
+    /// Sets the element at `index`.
+    ///
+    /// Panics if `index` is greater than 2.
+    #[inline]
+    pub fn set(&mut self, index: usize, value: bool) {
+        match index {
+            0 => self.x = MASK[value as usize],
+            1 => self.y = MASK[value as usize],
+            2 => self.z = MASK[value as usize],
+            _ => panic!("index out of bounds"),
+        }
+    }
+
+    #[inline]
+    #[must_use]
     fn into_bool_array(self) -> [bool; 3] {
         [
             (self.x & 0x1) != 0,
@@ -69,6 +102,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn into_u32_array(self) -> [u32; 3] {
         [self.x, self.y, self.z]
     }
diff --git a/src/bool/scalar/bvec4a.rs b/src/bool/scalar/bvec4a.rs
index 28b0066..bdf8884 100644
--- a/src/bool/scalar/bvec4a.rs
+++ b/src/bool/scalar/bvec4a.rs
@@ -25,6 +25,7 @@
 
     /// Creates a new vector mask.
     #[inline(always)]
+    #[must_use]
     pub const fn new(x: bool, y: bool, z: bool, w: bool) -> Self {
         Self {
             x: MASK[x as usize],
@@ -36,6 +37,7 @@
 
     /// Creates a vector with all elements set to `v`.
     #[inline]
+    #[must_use]
     pub const fn splat(v: bool) -> Self {
         Self::new(v, v, v, v)
     }
@@ -45,23 +47,56 @@
     /// A true element results in a `1` bit and a false element in a `0` bit.  Element `x` goes
     /// into the first lowest bit, element `y` into the second, etc.
     #[inline]
+    #[must_use]
     pub fn bitmask(self) -> u32 {
         (self.x & 0x1) | (self.y & 0x1) << 1 | (self.z & 0x1) << 2 | (self.w & 0x1) << 3
     }
 
     /// Returns true if any of the elements are true, false otherwise.
     #[inline]
+    #[must_use]
     pub fn any(self) -> bool {
         ((self.x | self.y | self.z | self.w) & 0x1) != 0
     }
 
     /// Returns true if all the elements are true, false otherwise.
     #[inline]
+    #[must_use]
     pub fn all(self) -> bool {
         ((self.x & self.y & self.z & self.w) & 0x1) != 0
     }
 
+    /// Tests the value at `index`.
+    ///
+    /// Panics if `index` is greater than 3.
     #[inline]
+    #[must_use]
+    pub fn test(&self, index: usize) -> bool {
+        match index {
+            0 => (self.x & 0x1) != 0,
+            1 => (self.y & 0x1) != 0,
+            2 => (self.z & 0x1) != 0,
+            3 => (self.w & 0x1) != 0,
+            _ => panic!("index out of bounds"),
+        }
+    }
+
+    /// Sets the element at `index`.
+    ///
+    /// Panics if `index` is greater than 3.
+    #[inline]
+    pub fn set(&mut self, index: usize, value: bool) {
+        match index {
+            0 => self.x = MASK[value as usize],
+            1 => self.y = MASK[value as usize],
+            2 => self.z = MASK[value as usize],
+            3 => self.w = MASK[value as usize],
+            _ => panic!("index out of bounds"),
+        }
+    }
+
+    #[inline]
+    #[must_use]
     fn into_bool_array(self) -> [bool; 4] {
         [
             (self.x & 0x1) != 0,
@@ -72,6 +107,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn into_u32_array(self) -> [u32; 4] {
         [self.x, self.y, self.z, self.w]
     }
diff --git a/src/bool/sse2/bvec3a.rs b/src/bool/sse2/bvec3a.rs
index 0fdbdf6..0ac65a5 100644
--- a/src/bool/sse2/bvec3a.rs
+++ b/src/bool/sse2/bvec3a.rs
@@ -9,6 +9,7 @@
 #[cfg(target_arch = "x86_64")]
 use core::arch::x86_64::*;
 
+#[repr(C)]
 union UnionCast {
     a: [u32; 4],
     v: BVec3A,
@@ -16,8 +17,7 @@
 
 /// A 3-dimensional SIMD vector mask.
 ///
-/// This type is 16 byte aligned and is backed by a SIMD vector. If SIMD is not available
-/// `BVec3A` will be a type alias for `BVec3`.
+/// This type is 16 byte aligned.
 #[derive(Clone, Copy)]
 #[repr(transparent)]
 pub struct BVec3A(pub(crate) __m128);
@@ -33,6 +33,7 @@
 
     /// Creates a new vector mask.
     #[inline(always)]
+    #[must_use]
     pub const fn new(x: bool, y: bool, z: bool) -> Self {
         unsafe {
             UnionCast {
@@ -44,6 +45,7 @@
 
     /// Creates a vector with all elements set to `v`.
     #[inline]
+    #[must_use]
     pub const fn splat(v: bool) -> Self {
         Self::new(v, v, v)
     }
@@ -53,29 +55,59 @@
     /// A true element results in a `1` bit and a false element in a `0` bit.  Element `x` goes
     /// into the first lowest bit, element `y` into the second, etc.
     #[inline]
+    #[must_use]
     pub fn bitmask(self) -> u32 {
         unsafe { (_mm_movemask_ps(self.0) as u32) & 0x7 }
     }
 
     /// Returns true if any of the elements are true, false otherwise.
     #[inline]
+    #[must_use]
     pub fn any(self) -> bool {
         self.bitmask() != 0
     }
 
     /// Returns true if all the elements are true, false otherwise.
     #[inline]
+    #[must_use]
     pub fn all(self) -> bool {
         self.bitmask() == 0x7
     }
 
+    /// Tests the value at `index`.
+    ///
+    /// Panics if `index` is greater than 2.
     #[inline]
+    #[must_use]
+    pub fn test(&self, index: usize) -> bool {
+        match index {
+            0 => (self.bitmask() & (1 << 0)) != 0,
+            1 => (self.bitmask() & (1 << 1)) != 0,
+            2 => (self.bitmask() & (1 << 2)) != 0,
+            _ => panic!("index out of bounds"),
+        }
+    }
+
+    /// Sets the element at `index`.
+    ///
+    /// Panics if `index` is greater than 2.
+    #[inline]
+    pub fn set(&mut self, index: usize, value: bool) {
+        use crate::Vec3A;
+        let mut v = Vec3A(self.0);
+        v[index] = f32::from_bits(MASK[value as usize]);
+        *self = Self(v.0);
+    }
+
+    #[inline]
+    #[must_use]
     fn into_bool_array(self) -> [bool; 3] {
         let bitmask = self.bitmask();
         [(bitmask & 1) != 0, (bitmask & 2) != 0, (bitmask & 4) != 0]
     }
 
     #[inline]
+    #[must_use]
     fn into_u32_array(self) -> [u32; 3] {
         let bitmask = self.bitmask();
         [
diff --git a/src/bool/sse2/bvec4a.rs b/src/bool/sse2/bvec4a.rs
index fc9d08c..18f8a03 100644
--- a/src/bool/sse2/bvec4a.rs
+++ b/src/bool/sse2/bvec4a.rs
@@ -9,6 +9,7 @@
 #[cfg(target_arch = "x86_64")]
 use core::arch::x86_64::*;
 
+#[repr(C)]
 union UnionCast {
     a: [u32; 4],
     v: BVec4A,
@@ -16,8 +17,7 @@
 
 /// A 4-dimensional SIMD vector mask.
 ///
-/// This type is 16 byte aligned and is backed by a SIMD vector. If SIMD is not available
-/// `BVec4A` will be a type alias for `BVec4`.
+/// This type is 16 byte aligned.
 #[derive(Clone, Copy)]
 #[repr(transparent)]
 pub struct BVec4A(pub(crate) __m128);
@@ -33,6 +33,7 @@
 
     /// Creates a new vector mask.
     #[inline(always)]
+    #[must_use]
     pub const fn new(x: bool, y: bool, z: bool, w: bool) -> Self {
         unsafe {
             UnionCast {
@@ -49,6 +50,7 @@
 
     /// Creates a vector with all elements set to `v`.
     #[inline]
+    #[must_use]
     pub const fn splat(v: bool) -> Self {
         Self::new(v, v, v, v)
     }
@@ -58,23 +60,53 @@
     /// A true element results in a `1` bit and a false element in a `0` bit.  Element `x` goes
     /// into the first lowest bit, element `y` into the second, etc.
     #[inline]
+    #[must_use]
     pub fn bitmask(self) -> u32 {
         unsafe { _mm_movemask_ps(self.0) as u32 }
     }
 
     /// Returns true if any of the elements are true, false otherwise.
     #[inline]
+    #[must_use]
     pub fn any(self) -> bool {
         self.bitmask() != 0
     }
 
     /// Returns true if all the elements are true, false otherwise.
     #[inline]
+    #[must_use]
     pub fn all(self) -> bool {
         self.bitmask() == 0xf
     }
 
+    /// Tests the value at `index`.
+    ///
+    /// Panics if `index` is greater than 3.
     #[inline]
+    #[must_use]
+    pub fn test(&self, index: usize) -> bool {
+        match index {
+            0 => (self.bitmask() & (1 << 0)) != 0,
+            1 => (self.bitmask() & (1 << 1)) != 0,
+            2 => (self.bitmask() & (1 << 2)) != 0,
+            3 => (self.bitmask() & (1 << 3)) != 0,
+            _ => panic!("index out of bounds"),
+        }
+    }
+
+    /// Sets the element at `index`.
+    ///
+    /// Panics if `index` is greater than 3.
+    #[inline]
+    pub fn set(&mut self, index: usize, value: bool) {
+        use crate::Vec4;
+        let mut v = Vec4(self.0);
+        v[index] = f32::from_bits(MASK[value as usize]);
+        *self = Self(v.0);
+    }
+
+    #[inline]
+    #[must_use]
     fn into_bool_array(self) -> [bool; 4] {
         let bitmask = self.bitmask();
         [
@@ -86,6 +118,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn into_u32_array(self) -> [u32; 4] {
         let bitmask = self.bitmask();
         [
diff --git a/src/bool/wasm32/bvec3a.rs b/src/bool/wasm32/bvec3a.rs
index 755246a..a634670 100644
--- a/src/bool/wasm32/bvec3a.rs
+++ b/src/bool/wasm32/bvec3a.rs
@@ -8,8 +8,7 @@
 
 /// A 3-dimensional SIMD vector mask.
 ///
-/// This type is 16 byte aligned and is backed by a SIMD vector. If SIMD is not available
-/// `BVec3A` will be a type alias for `BVec3`.
+/// This type is 16 byte aligned.
 #[derive(Clone, Copy)]
 #[repr(transparent)]
 pub struct BVec3A(pub(crate) v128);
@@ -25,6 +24,7 @@
 
     /// Creates a new vector mask.
     #[inline(always)]
+    #[must_use]
     pub const fn new(x: bool, y: bool, z: bool) -> Self {
         Self(u32x4(
             MASK[x as usize],
@@ -36,6 +36,7 @@
 
     /// Creates a vector with all elements set to `v`.
     #[inline]
+    #[must_use]
     pub const fn splat(v: bool) -> Self {
         Self::new(v, v, v)
     }
@@ -45,29 +46,59 @@
     /// A true element results in a `1` bit and a false element in a `0` bit.  Element `x` goes
     /// into the first lowest bit, element `y` into the second, etc.
     #[inline]
+    #[must_use]
     pub fn bitmask(self) -> u32 {
         (u32x4_bitmask(self.0) & 0x7) as u32
     }
 
     /// Returns true if any of the elements are true, false otherwise.
     #[inline]
+    #[must_use]
     pub fn any(self) -> bool {
         self.bitmask() != 0
     }
 
     /// Returns true if all the elements are true, false otherwise.
     #[inline]
+    #[must_use]
     pub fn all(self) -> bool {
         self.bitmask() == 0x7
     }
 
+    /// Tests the value at `index`.
+    ///
+    /// Panics if `index` is greater than 2.
     #[inline]
+    #[must_use]
+    pub fn test(&self, index: usize) -> bool {
+        match index {
+            0 => (self.bitmask() & (1 << 0)) != 0,
+            1 => (self.bitmask() & (1 << 1)) != 0,
+            2 => (self.bitmask() & (1 << 2)) != 0,
+            _ => panic!("index out of bounds"),
+        }
+    }
+
+    /// Sets the element at `index`.
+    ///
+    /// Panics if `index` is greater than 2.
+    #[inline]
+    pub fn set(&mut self, index: usize, value: bool) {
+        use crate::Vec3A;
+        let mut v = Vec3A(self.0);
+        v[index] = f32::from_bits(MASK[value as usize]);
+        *self = Self(v.0);
+    }
+
+    #[inline]
+    #[must_use]
     fn into_bool_array(self) -> [bool; 3] {
         let bitmask = self.bitmask();
         [(bitmask & 1) != 0, (bitmask & 2) != 0, (bitmask & 4) != 0]
     }
 
     #[inline]
+    #[must_use]
     fn into_u32_array(self) -> [u32; 3] {
         let bitmask = self.bitmask();
         [
diff --git a/src/bool/wasm32/bvec4a.rs b/src/bool/wasm32/bvec4a.rs
index cdec83f..3813354 100644
--- a/src/bool/wasm32/bvec4a.rs
+++ b/src/bool/wasm32/bvec4a.rs
@@ -8,8 +8,7 @@
 
 /// A 4-dimensional SIMD vector mask.
 ///
-/// This type is 16 byte aligned and is backed by a SIMD vector. If SIMD is not available
-/// `BVec4A` will be a type alias for `BVec4`.
+/// This type is 16 byte aligned.
 #[derive(Clone, Copy)]
 #[repr(transparent)]
 pub struct BVec4A(pub(crate) v128);
@@ -25,6 +24,7 @@
 
     /// Creates a new vector mask.
     #[inline(always)]
+    #[must_use]
     pub const fn new(x: bool, y: bool, z: bool, w: bool) -> Self {
         Self(u32x4(
             MASK[x as usize],
@@ -36,6 +36,7 @@
 
     /// Creates a vector with all elements set to `v`.
     #[inline]
+    #[must_use]
     pub const fn splat(v: bool) -> Self {
         Self::new(v, v, v, v)
     }
@@ -45,23 +46,53 @@
     /// A true element results in a `1` bit and a false element in a `0` bit.  Element `x` goes
     /// into the first lowest bit, element `y` into the second, etc.
     #[inline]
+    #[must_use]
     pub fn bitmask(self) -> u32 {
         u32x4_bitmask(self.0) as u32
     }
 
     /// Returns true if any of the elements are true, false otherwise.
     #[inline]
+    #[must_use]
     pub fn any(self) -> bool {
         self.bitmask() != 0
     }
 
     /// Returns true if all the elements are true, false otherwise.
     #[inline]
+    #[must_use]
     pub fn all(self) -> bool {
         self.bitmask() == 0xf
     }
 
+    /// Tests the value at `index`.
+    ///
+    /// Panics if `index` is greater than 3.
     #[inline]
+    #[must_use]
+    pub fn test(&self, index: usize) -> bool {
+        match index {
+            0 => (self.bitmask() & (1 << 0)) != 0,
+            1 => (self.bitmask() & (1 << 1)) != 0,
+            2 => (self.bitmask() & (1 << 2)) != 0,
+            3 => (self.bitmask() & (1 << 3)) != 0,
+            _ => panic!("index out of bounds"),
+        }
+    }
+
+    /// Sets the element at `index`.
+    ///
+    /// Panics if `index` is greater than 3.
+    #[inline]
+    pub fn set(&mut self, index: usize, value: bool) {
+        use crate::Vec4;
+        let mut v = Vec4(self.0);
+        v[index] = f32::from_bits(MASK[value as usize]);
+        *self = Self(v.0);
+    }
+
+    #[inline]
+    #[must_use]
     fn into_bool_array(self) -> [bool; 4] {
         let bitmask = self.bitmask();
         [
@@ -73,6 +104,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn into_u32_array(self) -> [u32; 4] {
         let bitmask = self.bitmask();
         [
diff --git a/src/coresimd.rs b/src/coresimd.rs
index c6a87d5..a6401ef 100644
--- a/src/coresimd.rs
+++ b/src/coresimd.rs
@@ -1,4 +1,4 @@
-use core::simd::*;
+use core::simd::{num::SimdFloat, *};
 
 /// Calculates the vector 3 dot product and returns answer in x lane of f32x4.
 #[inline(always)]
diff --git a/src/euler.rs b/src/euler.rs
index c97a962..85f8099 100644
--- a/src/euler.rs
+++ b/src/euler.rs
@@ -4,11 +4,7 @@
 From: http://bediyap.com/programming/convert-quaternion-to-euler-rotations/
 */
 
-use super::{DQuat, Quat};
-
-#[cfg(feature = "libm")]
-#[allow(unused_imports)]
-use num_traits::Float;
+use crate::{DQuat, Quat};
 
 /// Euler rotation sequences.
 ///
@@ -17,7 +13,6 @@
 ///
 /// YXZ can be used for yaw (y-axis), pitch (x-axis), roll (z-axis).
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
 pub enum EulerRot {
     /// Intrinsic three-axis rotation ZYX
     ZYX,
@@ -51,9 +46,10 @@
     fn third(self, q: Q) -> Self::Output;
 
     /// Compute all angles of a rotation in the notation order
-    fn convert_quat(self, q: Q) -> (Self::Output, Self::Output, Self::Output) {
-        (self.first(q), self.second(q), self.third(q))
-    }
+    fn convert_quat(self, q: Q) -> (Self::Output, Self::Output, Self::Output);
+
+    #[doc(hidden)]
+    fn sine_theta(self, q: Q) -> Self::Output;
 }
 
 /// Conversion from euler angles to quaternion.
@@ -63,81 +59,186 @@
     fn new_quat(self, u: T, v: T, w: T) -> Self::Output;
 }
 
-/// Adds a atan2 that handles the negative zero case.
-/// Basically forces positive zero in the x-argument for atan2.
-pub(crate) trait Atan2Fixed<T = Self> {
-    fn atan2_fixed(self, other: T) -> T;
-}
-
-impl Atan2Fixed for f32 {
-    fn atan2_fixed(self, other: f32) -> f32 {
-        self.atan2(if other == 0.0f32 { 0.0f32 } else { other })
-    }
-}
-impl Atan2Fixed for f64 {
-    fn atan2_fixed(self, other: f64) -> f64 {
-        self.atan2(if other == 0.0f64 { 0.0f64 } else { other })
-    }
-}
-
 macro_rules! impl_from_quat {
-    ($t:ty, $quat:ident) => {
+    ($t:ident, $quat:ident) => {
         impl EulerFromQuaternion<$quat> for EulerRot {
             type Output = $t;
-            fn first(self, q: $quat) -> $t {
+
+            fn sine_theta(self, q: $quat) -> $t {
                 use EulerRot::*;
                 match self {
-                    ZYX => (2.0 * (q.x * q.y + q.w * q.z))
-                        .atan2(q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z),
-                    ZXY => (-2.0 * (q.x * q.y - q.w * q.z))
-                        .atan2(q.w * q.w - q.x * q.x + q.y * q.y - q.z * q.z),
-                    YXZ => (2.0 * (q.x * q.z + q.w * q.y))
-                        .atan2(q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z),
-                    YZX => (-2.0 * (q.x * q.z - q.w * q.y))
-                        .atan2(q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z),
-                    XYZ => (-2.0 * (q.y * q.z - q.w * q.x))
-                        .atan2(q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z),
-                    XZY => (2.0 * (q.y * q.z + q.w * q.x))
-                        .atan2(q.w * q.w - q.x * q.x + q.y * q.y - q.z * q.z),
+                    ZYX => -2.0 * (q.x * q.z - q.w * q.y),
+                    ZXY => 2.0 * (q.y * q.z + q.w * q.x),
+                    YXZ => -2.0 * (q.y * q.z - q.w * q.x),
+                    YZX => 2.0 * (q.x * q.y + q.w * q.z),
+                    XYZ => 2.0 * (q.x * q.z + q.w * q.y),
+                    XZY => -2.0 * (q.x * q.y - q.w * q.z),
+                }
+                .clamp(-1.0, 1.0)
+            }
+
+            fn first(self, q: $quat) -> $t {
+                use crate::$t::math;
+                use EulerRot::*;
+
+                let sine_theta = self.sine_theta(q);
+                if math::abs(sine_theta) > 0.99999 {
+                    let scale = 2.0 * math::signum(sine_theta);
+
+                    match self {
+                        ZYX => scale * math::atan2(-q.x, q.w),
+                        ZXY => scale * math::atan2(q.y, q.w),
+                        YXZ => scale * math::atan2(-q.z, q.w),
+                        YZX => scale * math::atan2(q.x, q.w),
+                        XYZ => scale * math::atan2(q.z, q.w),
+                        XZY => scale * math::atan2(-q.y, q.w),
+                    }
+                } else {
+                    match self {
+                        ZYX => math::atan2(
+                            2.0 * (q.x * q.y + q.w * q.z),
+                            q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z,
+                        ),
+                        ZXY => math::atan2(
+                            -2.0 * (q.x * q.y - q.w * q.z),
+                            q.w * q.w - q.x * q.x + q.y * q.y - q.z * q.z,
+                        ),
+                        YXZ => math::atan2(
+                            2.0 * (q.x * q.z + q.w * q.y),
+                            q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z,
+                        ),
+                        YZX => math::atan2(
+                            -2.0 * (q.x * q.z - q.w * q.y),
+                            q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z,
+                        ),
+                        XYZ => math::atan2(
+                            -2.0 * (q.y * q.z - q.w * q.x),
+                            q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z,
+                        ),
+                        XZY => math::atan2(
+                            2.0 * (q.y * q.z + q.w * q.x),
+                            q.w * q.w - q.x * q.x + q.y * q.y - q.z * q.z,
+                        ),
+                    }
                 }
             }
 
             fn second(self, q: $quat) -> $t {
-                use EulerRot::*;
-
-                /// Clamp number to range [-1,1](-1,1) for asin() and acos(), else NaN is possible.
-                #[inline(always)]
-                fn arc_clamp(val: $t) -> $t {
-                    <$t>::min(<$t>::max(val, -1.0), 1.0)
-                }
-
-                match self {
-                    ZYX => arc_clamp(-2.0 * (q.x * q.z - q.w * q.y)).asin(),
-                    ZXY => arc_clamp(2.0 * (q.y * q.z + q.w * q.x)).asin(),
-                    YXZ => arc_clamp(-2.0 * (q.y * q.z - q.w * q.x)).asin(),
-                    YZX => arc_clamp(2.0 * (q.x * q.y + q.w * q.z)).asin(),
-                    XYZ => arc_clamp(2.0 * (q.x * q.z + q.w * q.y)).asin(),
-                    XZY => arc_clamp(-2.0 * (q.x * q.y - q.w * q.z)).asin(),
-                }
+                use crate::$t::math;
+                math::asin(self.sine_theta(q))
             }
 
             fn third(self, q: $quat) -> $t {
+                use crate::$t::math;
                 use EulerRot::*;
-                match self {
-                    ZYX => (2.0 * (q.y * q.z + q.w * q.x))
-                        .atan2(q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z),
-                    ZXY => (-2.0 * (q.x * q.z - q.w * q.y))
-                        .atan2(q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z),
-                    YXZ => (2.0 * (q.x * q.y + q.w * q.z))
-                        .atan2(q.w * q.w - q.x * q.x + q.y * q.y - q.z * q.z),
-                    YZX => (-2.0 * (q.y * q.z - q.w * q.x))
-                        .atan2(q.w * q.w - q.x * q.x + q.y * q.y - q.z * q.z),
-                    XYZ => (-2.0 * (q.x * q.y - q.w * q.z))
-                        .atan2(q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z),
-                    XZY => (2.0 * (q.x * q.z + q.w * q.y))
-                        .atan2(q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z),
+                if math::abs(self.sine_theta(q)) > 0.99999 {
+                    0.0
+                } else {
+                    match self {
+                        ZYX => math::atan2(
+                            2.0 * (q.y * q.z + q.w * q.x),
+                            q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z,
+                        ),
+                        ZXY => math::atan2(
+                            -2.0 * (q.x * q.z - q.w * q.y),
+                            q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z,
+                        ),
+                        YXZ => math::atan2(
+                            2.0 * (q.x * q.y + q.w * q.z),
+                            q.w * q.w - q.x * q.x + q.y * q.y - q.z * q.z,
+                        ),
+                        YZX => math::atan2(
+                            -2.0 * (q.y * q.z - q.w * q.x),
+                            q.w * q.w - q.x * q.x + q.y * q.y - q.z * q.z,
+                        ),
+                        XYZ => math::atan2(
+                            -2.0 * (q.x * q.y - q.w * q.z),
+                            q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z,
+                        ),
+                        XZY => math::atan2(
+                            2.0 * (q.x * q.z + q.w * q.y),
+                            q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z,
+                        ),
+                    }
                 }
             }
+
+            fn convert_quat(self, q: $quat) -> ($t, $t, $t) {
+                use crate::$t::math;
+                use EulerRot::*;
+
+                let sine_theta = self.sine_theta(q);
+                let second = math::asin(sine_theta);
+
+                if math::abs(sine_theta) > 0.99999 {
+                    let scale = 2.0 * math::signum(sine_theta);
+
+                    return match self {
+                        ZYX => (scale * math::atan2(-q.x, q.w), second, 0.0),
+                        ZXY => (scale * math::atan2(q.y, q.w), second, 0.0),
+                        YXZ => (scale * math::atan2(-q.z, q.w), second, 0.0),
+                        YZX => (scale * math::atan2(q.x, q.w), second, 0.0),
+                        XYZ => (scale * math::atan2(q.z, q.w), second, 0.0),
+                        XZY => (scale * math::atan2(-q.y, q.w), second, 0.0),
+                    };
+                }
+
+                let first = match self {
+                    ZYX => math::atan2(
+                        2.0 * (q.x * q.y + q.w * q.z),
+                        q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z,
+                    ),
+                    ZXY => math::atan2(
+                        -2.0 * (q.x * q.y - q.w * q.z),
+                        q.w * q.w - q.x * q.x + q.y * q.y - q.z * q.z,
+                    ),
+                    YXZ => math::atan2(
+                        2.0 * (q.x * q.z + q.w * q.y),
+                        q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z,
+                    ),
+                    YZX => math::atan2(
+                        -2.0 * (q.x * q.z - q.w * q.y),
+                        q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z,
+                    ),
+                    XYZ => math::atan2(
+                        -2.0 * (q.y * q.z - q.w * q.x),
+                        q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z,
+                    ),
+                    XZY => math::atan2(
+                        2.0 * (q.y * q.z + q.w * q.x),
+                        q.w * q.w - q.x * q.x + q.y * q.y - q.z * q.z,
+                    ),
+                };
+
+                let third = match self {
+                    ZYX => math::atan2(
+                        2.0 * (q.y * q.z + q.w * q.x),
+                        q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z,
+                    ),
+                    ZXY => math::atan2(
+                        -2.0 * (q.x * q.z - q.w * q.y),
+                        q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z,
+                    ),
+                    YXZ => math::atan2(
+                        2.0 * (q.x * q.y + q.w * q.z),
+                        q.w * q.w - q.x * q.x + q.y * q.y - q.z * q.z,
+                    ),
+                    YZX => math::atan2(
+                        -2.0 * (q.y * q.z - q.w * q.x),
+                        q.w * q.w - q.x * q.x + q.y * q.y - q.z * q.z,
+                    ),
+                    XYZ => math::atan2(
+                        -2.0 * (q.x * q.y - q.w * q.z),
+                        q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z,
+                    ),
+                    XZY => math::atan2(
+                        2.0 * (q.x * q.z + q.w * q.y),
+                        q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z,
+                    ),
+                };
+
+                (first, second, third)
+            }
         }
         // End - impl EulerFromQuaternion
     };
diff --git a/src/f32.rs b/src/f32.rs
index 2076bd4..3a53381 100644
--- a/src/f32.rs
+++ b/src/f32.rs
@@ -1,6 +1,8 @@
 mod affine2;
 mod affine3a;
+mod float;
 mod mat3;
+pub(crate) mod math;
 mod vec2;
 mod vec3;
 
diff --git a/src/f32/affine2.rs b/src/f32/affine2.rs
index c2a438e..c089586 100644
--- a/src/f32/affine2.rs
+++ b/src/f32/affine2.rs
@@ -1,7 +1,7 @@
 // Generated from affine.rs.tera template. Edit the template, not the generated file.
 
 use crate::{Mat2, Mat3, Mat3A, Vec2, Vec3A};
-use core::ops::{Deref, DerefMut, Mul};
+use core::ops::{Deref, DerefMut, Mul, MulAssign};
 
 /// A 2D affine transform, which can represent translation, rotation, scaling and shear.
 #[derive(Copy, Clone)]
@@ -37,6 +37,7 @@
 
     /// Creates an affine transform from three column vectors.
     #[inline(always)]
+    #[must_use]
     pub const fn from_cols(x_axis: Vec2, y_axis: Vec2, z_axis: Vec2) -> Self {
         Self {
             matrix2: Mat2::from_cols(x_axis, y_axis),
@@ -46,6 +47,7 @@
 
     /// Creates an affine transform from a `[f32; 6]` array stored in column major order.
     #[inline]
+    #[must_use]
     pub fn from_cols_array(m: &[f32; 6]) -> Self {
         Self {
             matrix2: Mat2::from_cols_slice(&m[0..4]),
@@ -55,6 +57,7 @@
 
     /// Creates a `[f32; 6]` array storing data in column major order.
     #[inline]
+    #[must_use]
     pub fn to_cols_array(&self) -> [f32; 6] {
         let x = &self.matrix2.x_axis;
         let y = &self.matrix2.y_axis;
@@ -67,6 +70,7 @@
     /// If your data is in row major order you will need to `transpose` the returned
     /// matrix.
     #[inline]
+    #[must_use]
     pub fn from_cols_array_2d(m: &[[f32; 2]; 3]) -> Self {
         Self {
             matrix2: Mat2::from_cols(m[0].into(), m[1].into()),
@@ -78,6 +82,7 @@
     /// column major order.
     /// If you require data in row major order `transpose` the matrix first.
     #[inline]
+    #[must_use]
     pub fn to_cols_array_2d(&self) -> [[f32; 2]; 3] {
         [
             self.matrix2.x_axis.into(),
@@ -92,6 +97,7 @@
     ///
     /// Panics if `slice` is less than 6 elements long.
     #[inline]
+    #[must_use]
     pub fn from_cols_slice(slice: &[f32]) -> Self {
         Self {
             matrix2: Mat2::from_cols_slice(&slice[0..4]),
@@ -113,6 +119,7 @@
     /// Creates an affine transform that changes scale.
     /// Note that if any scale is zero the transform will be non-invertible.
     #[inline]
+    #[must_use]
     pub fn from_scale(scale: Vec2) -> Self {
         Self {
             matrix2: Mat2::from_diagonal(scale),
@@ -122,6 +129,7 @@
 
     /// Creates an affine transform from the given rotation `angle`.
     #[inline]
+    #[must_use]
     pub fn from_angle(angle: f32) -> Self {
         Self {
             matrix2: Mat2::from_angle(angle),
@@ -131,6 +139,7 @@
 
     /// Creates an affine transformation from the given 2D `translation`.
     #[inline]
+    #[must_use]
     pub fn from_translation(translation: Vec2) -> Self {
         Self {
             matrix2: Mat2::IDENTITY,
@@ -140,6 +149,7 @@
 
     /// Creates an affine transform from a 2x2 matrix (expressing scale, shear and rotation)
     #[inline]
+    #[must_use]
     pub fn from_mat2(matrix2: Mat2) -> Self {
         Self {
             matrix2,
@@ -153,6 +163,7 @@
     /// Equivalent to
     /// `Affine2::from_translation(translation) * Affine2::from_mat2(mat2)`
     #[inline]
+    #[must_use]
     pub fn from_mat2_translation(matrix2: Mat2, translation: Vec2) -> Self {
         Self {
             matrix2,
@@ -166,6 +177,7 @@
     /// Equivalent to `Affine2::from_translation(translation) *
     /// Affine2::from_angle(angle) * Affine2::from_scale(scale)`
     #[inline]
+    #[must_use]
     pub fn from_scale_angle_translation(scale: Vec2, angle: f32, translation: Vec2) -> Self {
         let rotation = Mat2::from_angle(angle);
         Self {
@@ -179,6 +191,7 @@
     ///
     /// Equivalent to `Affine2::from_translation(translation) * Affine2::from_angle(angle)`
     #[inline]
+    #[must_use]
     pub fn from_angle_translation(angle: f32, translation: Vec2) -> Self {
         Self {
             matrix2: Mat2::from_angle(angle),
@@ -188,6 +201,7 @@
 
     /// The given `Mat3` must be an affine transform,
     #[inline]
+    #[must_use]
     pub fn from_mat3(m: Mat3) -> Self {
         use crate::swizzles::Vec3Swizzles;
         Self {
@@ -196,8 +210,9 @@
         }
     }
 
-    /// The given `Mat3A` must be an affine transform,
+    /// The given [`Mat3A`] must be an affine transform,
     #[inline]
+    #[must_use]
     pub fn from_mat3a(m: Mat3A) -> Self {
         use crate::swizzles::Vec3Swizzles;
         Self {
@@ -206,8 +221,37 @@
         }
     }
 
+    /// Extracts `scale`, `angle` and `translation` from `self`.
+    ///
+    /// The transform is expected to be non-degenerate and without shearing, or the output
+    /// will be invalid.
+    ///
+    /// # Panics
+    ///
+    /// Will panic if the determinant `self.matrix2` is zero or if the resulting scale
+    /// vector contains any zero elements when `glam_assert` is enabled.
+    #[inline]
+    #[must_use]
+    pub fn to_scale_angle_translation(self) -> (Vec2, f32, Vec2) {
+        use crate::f32::math;
+        let det = self.matrix2.determinant();
+        glam_assert!(det != 0.0);
+
+        let scale = Vec2::new(
+            self.matrix2.x_axis.length() * math::signum(det),
+            self.matrix2.y_axis.length(),
+        );
+
+        glam_assert!(scale.cmpne(Vec2::ZERO).all());
+
+        let angle = math::atan2(-self.matrix2.y_axis.x, self.matrix2.y_axis.y);
+
+        (scale, angle, self.translation)
+    }
+
     /// Transforms the given 2D point, applying shear, scale, rotation and translation.
     #[inline]
+    #[must_use]
     pub fn transform_point2(&self, rhs: Vec2) -> Vec2 {
         self.matrix2 * rhs + self.translation
     }
@@ -215,7 +259,7 @@
     /// Transforms the given 2D vector, applying shear, scale and rotation (but NOT
     /// translation).
     ///
-    /// To also apply translation, use [`Self::transform_point2`] instead.
+    /// To also apply translation, use [`Self::transform_point2()`] instead.
     #[inline]
     pub fn transform_vector2(&self, rhs: Vec2) -> Vec2 {
         self.matrix2 * rhs
@@ -226,12 +270,14 @@
     /// If any element is either `NaN`, positive or negative infinity, this will return
     /// `false`.
     #[inline]
+    #[must_use]
     pub fn is_finite(&self) -> bool {
         self.matrix2.is_finite() && self.translation.is_finite()
     }
 
     /// Returns `true` if any elements are `NaN`.
     #[inline]
+    #[must_use]
     pub fn is_nan(&self) -> bool {
         self.matrix2.is_nan() || self.translation.is_nan()
     }
@@ -246,6 +292,7 @@
     /// For more see
     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
     #[inline]
+    #[must_use]
     pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
         self.matrix2.abs_diff_eq(rhs.matrix2, max_abs_diff)
             && self.translation.abs_diff_eq(rhs.translation, max_abs_diff)
@@ -254,8 +301,8 @@
     /// Return the inverse of this transform.
     ///
     /// Note that if the transform is not invertible the result will be invalid.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn inverse(&self) -> Self {
         let matrix2 = self.matrix2.inverse();
         // transform negative translation by the matrix inverse:
@@ -339,6 +386,13 @@
     }
 }
 
+impl MulAssign for Affine2 {
+    #[inline]
+    fn mul_assign(&mut self, rhs: Affine2) {
+        *self = self.mul(rhs);
+    }
+}
+
 impl From<Affine2> for Mat3 {
     #[inline]
     fn from(m: Affine2) -> Mat3 {
diff --git a/src/f32/affine3a.rs b/src/f32/affine3a.rs
index 40cc66e..1fdddd5 100644
--- a/src/f32/affine3a.rs
+++ b/src/f32/affine3a.rs
@@ -1,9 +1,11 @@
 // Generated from affine.rs.tera template. Edit the template, not the generated file.
 
 use crate::{Mat3, Mat3A, Mat4, Quat, Vec3, Vec3A};
-use core::ops::{Deref, DerefMut, Mul};
+use core::ops::{Deref, DerefMut, Mul, MulAssign};
 
 /// A 3D affine transform, which can represent translation, rotation, scaling and shear.
+///
+/// This type is 16 byte aligned.
 #[derive(Copy, Clone)]
 #[repr(C)]
 pub struct Affine3A {
@@ -37,6 +39,7 @@
 
     /// Creates an affine transform from three column vectors.
     #[inline(always)]
+    #[must_use]
     pub const fn from_cols(x_axis: Vec3A, y_axis: Vec3A, z_axis: Vec3A, w_axis: Vec3A) -> Self {
         Self {
             matrix3: Mat3A::from_cols(x_axis, y_axis, z_axis),
@@ -46,6 +49,7 @@
 
     /// Creates an affine transform from a `[f32; 12]` array stored in column major order.
     #[inline]
+    #[must_use]
     pub fn from_cols_array(m: &[f32; 12]) -> Self {
         Self {
             matrix3: Mat3A::from_cols_slice(&m[0..9]),
@@ -55,6 +59,7 @@
 
     /// Creates a `[f32; 12]` array storing data in column major order.
     #[inline]
+    #[must_use]
     pub fn to_cols_array(&self) -> [f32; 12] {
         let x = &self.matrix3.x_axis;
         let y = &self.matrix3.y_axis;
@@ -68,6 +73,7 @@
     /// If your data is in row major order you will need to `transpose` the returned
     /// matrix.
     #[inline]
+    #[must_use]
     pub fn from_cols_array_2d(m: &[[f32; 3]; 4]) -> Self {
         Self {
             matrix3: Mat3A::from_cols(m[0].into(), m[1].into(), m[2].into()),
@@ -79,6 +85,7 @@
     /// column major order.
     /// If you require data in row major order `transpose` the matrix first.
     #[inline]
+    #[must_use]
     pub fn to_cols_array_2d(&self) -> [[f32; 3]; 4] {
         [
             self.matrix3.x_axis.into(),
@@ -94,6 +101,7 @@
     ///
     /// Panics if `slice` is less than 12 elements long.
     #[inline]
+    #[must_use]
     pub fn from_cols_slice(slice: &[f32]) -> Self {
         Self {
             matrix3: Mat3A::from_cols_slice(&slice[0..9]),
@@ -115,6 +123,7 @@
     /// Creates an affine transform that changes scale.
     /// Note that if any scale is zero the transform will be non-invertible.
     #[inline]
+    #[must_use]
     pub fn from_scale(scale: Vec3) -> Self {
         Self {
             matrix3: Mat3A::from_diagonal(scale),
@@ -123,6 +132,7 @@
     }
     /// Creates an affine transform from the given `rotation` quaternion.
     #[inline]
+    #[must_use]
     pub fn from_quat(rotation: Quat) -> Self {
         Self {
             matrix3: Mat3A::from_quat(rotation),
@@ -133,6 +143,7 @@
     /// Creates an affine transform containing a 3D rotation around a normalized
     /// rotation `axis` of `angle` (in radians).
     #[inline]
+    #[must_use]
     pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
         Self {
             matrix3: Mat3A::from_axis_angle(axis, angle),
@@ -143,6 +154,7 @@
     /// Creates an affine transform containing a 3D rotation around the x axis of
     /// `angle` (in radians).
     #[inline]
+    #[must_use]
     pub fn from_rotation_x(angle: f32) -> Self {
         Self {
             matrix3: Mat3A::from_rotation_x(angle),
@@ -153,6 +165,7 @@
     /// Creates an affine transform containing a 3D rotation around the y axis of
     /// `angle` (in radians).
     #[inline]
+    #[must_use]
     pub fn from_rotation_y(angle: f32) -> Self {
         Self {
             matrix3: Mat3A::from_rotation_y(angle),
@@ -163,6 +176,7 @@
     /// Creates an affine transform containing a 3D rotation around the z axis of
     /// `angle` (in radians).
     #[inline]
+    #[must_use]
     pub fn from_rotation_z(angle: f32) -> Self {
         Self {
             matrix3: Mat3A::from_rotation_z(angle),
@@ -172,6 +186,7 @@
 
     /// Creates an affine transformation from the given 3D `translation`.
     #[inline]
+    #[must_use]
     pub fn from_translation(translation: Vec3) -> Self {
         #[allow(clippy::useless_conversion)]
         Self {
@@ -183,6 +198,7 @@
     /// Creates an affine transform from a 3x3 matrix (expressing scale, shear and
     /// rotation)
     #[inline]
+    #[must_use]
     pub fn from_mat3(mat3: Mat3) -> Self {
         #[allow(clippy::useless_conversion)]
         Self {
@@ -196,6 +212,7 @@
     ///
     /// Equivalent to `Affine3A::from_translation(translation) * Affine3A::from_mat3(mat3)`
     #[inline]
+    #[must_use]
     pub fn from_mat3_translation(mat3: Mat3, translation: Vec3) -> Self {
         #[allow(clippy::useless_conversion)]
         Self {
@@ -210,6 +227,7 @@
     /// Equivalent to `Affine3A::from_translation(translation) *
     /// Affine3A::from_quat(rotation) * Affine3A::from_scale(scale)`
     #[inline]
+    #[must_use]
     pub fn from_scale_rotation_translation(scale: Vec3, rotation: Quat, translation: Vec3) -> Self {
         let rotation = Mat3A::from_quat(rotation);
         #[allow(clippy::useless_conversion)]
@@ -227,6 +245,7 @@
     ///
     /// Equivalent to `Affine3A::from_translation(translation) * Affine3A::from_quat(rotation)`
     #[inline]
+    #[must_use]
     pub fn from_rotation_translation(rotation: Quat, translation: Vec3) -> Self {
         #[allow(clippy::useless_conversion)]
         Self {
@@ -238,6 +257,7 @@
     /// The given `Mat4` must be an affine transform,
     /// i.e. contain no perspective transform.
     #[inline]
+    #[must_use]
     pub fn from_mat4(m: Mat4) -> Self {
         Self {
             matrix3: Mat3A::from_cols(
@@ -259,16 +279,14 @@
     /// Will panic if the determinant `self.matrix3` is zero or if the resulting scale
     /// vector contains any zero elements when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn to_scale_rotation_translation(&self) -> (Vec3, Quat, Vec3) {
-        #[cfg(feature = "libm")]
-        #[allow(unused_imports)]
-        use num_traits::Float;
-
+        use crate::f32::math;
         let det = self.matrix3.determinant();
         glam_assert!(det != 0.0);
 
         let scale = Vec3::new(
-            self.matrix3.x_axis.length() * det.signum(),
+            self.matrix3.x_axis.length() * math::signum(det),
             self.matrix3.y_axis.length(),
             self.matrix3.z_axis.length(),
         );
@@ -293,6 +311,7 @@
     ///
     /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
     #[inline]
+    #[must_use]
     pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
         Self::look_to_rh(eye, -dir, up)
     }
@@ -302,6 +321,7 @@
     ///
     /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
     #[inline]
+    #[must_use]
     pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
         let f = dir.normalize();
         let s = f.cross(up).normalize();
@@ -325,6 +345,7 @@
     ///
     /// Will panic if `up` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
         glam_assert!(up.is_normalized());
         Self::look_to_lh(eye, center - eye, up)
@@ -338,6 +359,7 @@
     ///
     /// Will panic if `up` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
         glam_assert!(up.is_normalized());
         Self::look_to_rh(eye, center - eye, up)
@@ -357,8 +379,9 @@
     /// Transforms the given 3D vector, applying shear, scale and rotation (but NOT
     /// translation).
     ///
-    /// To also apply translation, use [`Self::transform_point3`] instead.
+    /// To also apply translation, use [`Self::transform_point3()`] instead.
     #[inline]
+    #[must_use]
     pub fn transform_vector3(&self, rhs: Vec3) -> Vec3 {
         #[allow(clippy::useless_conversion)]
         ((self.matrix3.x_axis * rhs.x)
@@ -367,17 +390,19 @@
             .into()
     }
 
-    /// Transforms the given `Vec3A`, applying shear, scale, rotation and translation.
+    /// Transforms the given [`Vec3A`], applying shear, scale, rotation and translation.
     #[inline]
+    #[must_use]
     pub fn transform_point3a(&self, rhs: Vec3A) -> Vec3A {
         self.matrix3 * rhs + self.translation
     }
 
-    /// Transforms the given `Vec3A`, applying shear, scale and rotation (but NOT
+    /// Transforms the given [`Vec3A`], applying shear, scale and rotation (but NOT
     /// translation).
     ///
-    /// To also apply translation, use [`Self::transform_point3a`] instead.
+    /// To also apply translation, use [`Self::transform_point3a()`] instead.
     #[inline]
+    #[must_use]
     pub fn transform_vector3a(&self, rhs: Vec3A) -> Vec3A {
         self.matrix3 * rhs
     }
@@ -387,12 +412,14 @@
     /// If any element is either `NaN`, positive or negative infinity, this will return
     /// `false`.
     #[inline]
+    #[must_use]
     pub fn is_finite(&self) -> bool {
         self.matrix3.is_finite() && self.translation.is_finite()
     }
 
     /// Returns `true` if any elements are `NaN`.
     #[inline]
+    #[must_use]
     pub fn is_nan(&self) -> bool {
         self.matrix3.is_nan() || self.translation.is_nan()
     }
@@ -407,6 +434,7 @@
     /// For more see
     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
     #[inline]
+    #[must_use]
     pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
         self.matrix3.abs_diff_eq(rhs.matrix3, max_abs_diff)
             && self.translation.abs_diff_eq(rhs.translation, max_abs_diff)
@@ -415,8 +443,8 @@
     /// Return the inverse of this transform.
     ///
     /// Note that if the transform is not invertible the result will be invalid.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn inverse(&self) -> Self {
         let matrix3 = self.matrix3.inverse();
         // transform negative translation by the matrix inverse:
@@ -500,6 +528,13 @@
     }
 }
 
+impl MulAssign for Affine3A {
+    #[inline]
+    fn mul_assign(&mut self, rhs: Affine3A) {
+        *self = self.mul(rhs);
+    }
+}
+
 impl From<Affine3A> for Mat4 {
     #[inline]
     fn from(m: Affine3A) -> Mat4 {
diff --git a/src/f32/coresimd/mat2.rs b/src/f32/coresimd/mat2.rs
index 200aa52..f8c0f91 100644
--- a/src/f32/coresimd/mat2.rs
+++ b/src/f32/coresimd/mat2.rs
@@ -1,24 +1,25 @@
 // Generated from mat.rs.tera template. Edit the template, not the generated file.
 
-use crate::{swizzles::*, DMat2, Mat3, Mat3A, Vec2};
+use crate::{f32::math, swizzles::*, DMat2, Mat3, Mat3A, Vec2};
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
 use core::iter::{Product, Sum};
 use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
 
-use core::simd::{Which::*, *};
+use core::simd::*;
 
-#[cfg(feature = "libm")]
-#[allow(unused_imports)]
-use num_traits::Float;
-
-/// Creates a 2x2 matrix from column vectors.
+/// Creates a 2x2 matrix from two column vectors.
 #[inline(always)]
+#[must_use]
 pub const fn mat2(x_axis: Vec2, y_axis: Vec2) -> Mat2 {
     Mat2::from_cols(x_axis, y_axis)
 }
 
 /// A 2x2 column major matrix.
+///
+/// SIMD vector types are used for storage on supported platforms.
+///
+/// This type is 16 byte aligned.
 #[derive(Clone, Copy)]
 #[repr(transparent)]
 pub struct Mat2(pub(crate) f32x4);
@@ -35,12 +36,14 @@
 
     #[allow(clippy::too_many_arguments)]
     #[inline(always)]
+    #[must_use]
     const fn new(m00: f32, m01: f32, m10: f32, m11: f32) -> Self {
         Self(f32x4::from_array([m00, m01, m10, m11]))
     }
 
     /// Creates a 2x2 matrix from two column vectors.
     #[inline(always)]
+    #[must_use]
     pub const fn from_cols(x_axis: Vec2, y_axis: Vec2) -> Self {
         Self(f32x4::from_array([x_axis.x, x_axis.y, y_axis.x, y_axis.y]))
     }
@@ -49,6 +52,7 @@
     /// If your data is stored in row major you will need to `transpose` the returned
     /// matrix.
     #[inline]
+    #[must_use]
     pub const fn from_cols_array(m: &[f32; 4]) -> Self {
         Self(f32x4::from_array(*m))
     }
@@ -56,6 +60,7 @@
     /// Creates a `[f32; 4]` array storing data in column major order.
     /// If you require data in row major order `transpose` the matrix first.
     #[inline]
+    #[must_use]
     pub const fn to_cols_array(&self) -> [f32; 4] {
         unsafe { *(self as *const Self as *const [f32; 4]) }
     }
@@ -64,6 +69,7 @@
     /// If your data is in row major order you will need to `transpose` the returned
     /// matrix.
     #[inline]
+    #[must_use]
     pub const fn from_cols_array_2d(m: &[[f32; 2]; 2]) -> Self {
         Self::from_cols(Vec2::from_array(m[0]), Vec2::from_array(m[1]))
     }
@@ -71,6 +77,7 @@
     /// Creates a `[[f32; 2]; 2]` 2D array storing data in column major order.
     /// If you require data in row major order `transpose` the matrix first.
     #[inline]
+    #[must_use]
     pub const fn to_cols_array_2d(&self) -> [[f32; 2]; 2] {
         unsafe { *(self as *const Self as *const [[f32; 2]; 2]) }
     }
@@ -78,6 +85,7 @@
     /// Creates a 2x2 matrix with its diagonal set to `diagonal` and all other entries set to 0.
     #[doc(alias = "scale")]
     #[inline]
+    #[must_use]
     pub const fn from_diagonal(diagonal: Vec2) -> Self {
         Self::new(diagonal.x, 0.0, 0.0, diagonal.y)
     }
@@ -85,26 +93,30 @@
     /// Creates a 2x2 matrix containing the combining non-uniform `scale` and rotation of
     /// `angle` (in radians).
     #[inline]
+    #[must_use]
     pub fn from_scale_angle(scale: Vec2, angle: f32) -> Self {
-        let (sin, cos) = angle.sin_cos();
+        let (sin, cos) = math::sin_cos(angle);
         Self::new(cos * scale.x, sin * scale.x, -sin * scale.y, cos * scale.y)
     }
 
     /// Creates a 2x2 matrix containing a rotation of `angle` (in radians).
     #[inline]
+    #[must_use]
     pub fn from_angle(angle: f32) -> Self {
-        let (sin, cos) = angle.sin_cos();
+        let (sin, cos) = math::sin_cos(angle);
         Self::new(cos, sin, -sin, cos)
     }
 
     /// Creates a 2x2 matrix from a 3x3 matrix, discarding the 2nd row and column.
     #[inline]
+    #[must_use]
     pub fn from_mat3(m: Mat3) -> Self {
         Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
     }
 
     /// 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())
     }
@@ -115,6 +127,7 @@
     ///
     /// Panics if `slice` is less than 4 elements long.
     #[inline]
+    #[must_use]
     pub const fn from_cols_slice(slice: &[f32]) -> Self {
         Self::new(slice[0], slice[1], slice[2], slice[3])
     }
@@ -138,6 +151,7 @@
     ///
     /// Panics if `index` is greater than 1.
     #[inline]
+    #[must_use]
     pub fn col(&self, index: usize) -> Vec2 {
         match index {
             0 => self.x_axis,
@@ -166,6 +180,7 @@
     ///
     /// Panics if `index` is greater than 1.
     #[inline]
+    #[must_use]
     pub fn row(&self, index: usize) -> Vec2 {
         match index {
             0 => Vec2::new(self.x_axis.x, self.y_axis.x),
@@ -177,25 +192,28 @@
     /// Returns `true` if, and only if, all elements are finite.
     /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
     #[inline]
+    #[must_use]
     pub fn is_finite(&self) -> bool {
         self.x_axis.is_finite() && self.y_axis.is_finite()
     }
 
     /// Returns `true` if any elements are `NaN`.
     #[inline]
+    #[must_use]
     pub fn is_nan(&self) -> bool {
         self.x_axis.is_nan() || self.y_axis.is_nan()
     }
 
     /// Returns the transpose of `self`.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn transpose(&self) -> Self {
         Self(simd_swizzle!(self.0, [0, 2, 1, 3]))
     }
 
     /// Returns the determinant of `self`.
     #[inline]
+    #[must_use]
     pub fn determinant(&self) -> f32 {
         let abcd = self.0;
         let dcba = simd_swizzle!(abcd, [3, 2, 1, 0]);
@@ -211,8 +229,8 @@
     /// # Panics
     ///
     /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn inverse(&self) -> Self {
         const SIGN: f32x4 = f32x4::from_array([1.0, -1.0, -1.0, 1.0]);
         let abcd = self.0;
@@ -228,6 +246,7 @@
 
     /// Transforms a 2D vector.
     #[inline]
+    #[must_use]
     pub fn mul_vec2(&self, rhs: Vec2) -> Vec2 {
         let abcd = self.0;
         let xxyy = f32x4::from_array([rhs.x, rhs.x, rhs.y, rhs.y]);
@@ -239,6 +258,7 @@
 
     /// Multiplies two 2x2 matrices.
     #[inline]
+    #[must_use]
     pub fn mul_mat2(&self, rhs: &Self) -> Self {
         let abcd = self.0;
         let xxyy0 = simd_swizzle!(rhs.0, [0, 0, 1, 1]);
@@ -249,27 +269,26 @@
         let cydyaxbx1 = simd_swizzle!(axbxcydy1, [2, 3, 0, 1]);
         let result0 = axbxcydy0 + cydyaxbx0;
         let result1 = axbxcydy1 + cydyaxbx1;
-        Self(simd_swizzle!(
-            result0,
-            result1,
-            [First(0), First(1), Second(0), Second(1)]
-        ))
+        Self(simd_swizzle!(result0, result1, [0, 1, 4, 5]))
     }
 
     /// Adds two 2x2 matrices.
     #[inline]
+    #[must_use]
     pub fn add_mat2(&self, rhs: &Self) -> Self {
         Self(self.0 + rhs.0)
     }
 
     /// Subtracts two 2x2 matrices.
     #[inline]
+    #[must_use]
     pub fn sub_mat2(&self, rhs: &Self) -> Self {
         Self(self.0 - rhs.0)
     }
 
     /// Multiplies a 2x2 matrix by a scalar.
     #[inline]
+    #[must_use]
     pub fn mul_scalar(&self, rhs: f32) -> Self {
         Self(self.0 * f32x4::splat(rhs))
     }
@@ -284,6 +303,7 @@
     /// For more see
     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
     #[inline]
+    #[must_use]
     pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
         self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
             && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
diff --git a/src/f32/coresimd/mat3a.rs b/src/f32/coresimd/mat3a.rs
index bda6d27..3c0645d 100644
--- a/src/f32/coresimd/mat3a.rs
+++ b/src/f32/coresimd/mat3a.rs
@@ -1,19 +1,16 @@
 // Generated from mat.rs.tera template. Edit the template, not the generated file.
 
-use crate::{swizzles::*, DMat3, EulerRot, Mat2, Mat3, Mat4, Quat, Vec2, Vec3, Vec3A};
+use crate::{f32::math, swizzles::*, DMat3, EulerRot, Mat2, Mat3, Mat4, Quat, Vec2, Vec3, Vec3A};
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
 use core::iter::{Product, Sum};
 use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
 
-use core::simd::{Which::*, *};
+use core::simd::*;
 
-#[cfg(feature = "libm")]
-#[allow(unused_imports)]
-use num_traits::Float;
-
-/// Creates a 3x3 matrix from column vectors.
+/// Creates a 3x3 matrix from three column vectors.
 #[inline(always)]
+#[must_use]
 pub const fn mat3a(x_axis: Vec3A, y_axis: Vec3A, z_axis: Vec3A) -> Mat3A {
     Mat3A::from_cols(x_axis, y_axis, z_axis)
 }
@@ -62,6 +59,7 @@
 
     #[allow(clippy::too_many_arguments)]
     #[inline(always)]
+    #[must_use]
     const fn new(
         m00: f32,
         m01: f32,
@@ -80,8 +78,9 @@
         }
     }
 
-    /// Creates a 3x3 matrix from two column vectors.
+    /// Creates a 3x3 matrix from three column vectors.
     #[inline(always)]
+    #[must_use]
     pub const fn from_cols(x_axis: Vec3A, y_axis: Vec3A, z_axis: Vec3A) -> Self {
         Self {
             x_axis,
@@ -94,6 +93,7 @@
     /// If your data is stored in row major you will need to `transpose` the returned
     /// matrix.
     #[inline]
+    #[must_use]
     pub const fn from_cols_array(m: &[f32; 9]) -> Self {
         Self::new(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8])
     }
@@ -101,6 +101,7 @@
     /// Creates a `[f32; 9]` array storing data in column major order.
     /// If you require data in row major order `transpose` the matrix first.
     #[inline]
+    #[must_use]
     pub const fn to_cols_array(&self) -> [f32; 9] {
         let [x_axis_x, x_axis_y, x_axis_z] = self.x_axis.to_array();
         let [y_axis_x, y_axis_y, y_axis_z] = self.y_axis.to_array();
@@ -116,6 +117,7 @@
     /// If your data is in row major order you will need to `transpose` the returned
     /// matrix.
     #[inline]
+    #[must_use]
     pub const fn from_cols_array_2d(m: &[[f32; 3]; 3]) -> Self {
         Self::from_cols(
             Vec3A::from_array(m[0]),
@@ -127,6 +129,7 @@
     /// Creates a `[[f32; 3]; 3]` 3D array storing data in column major order.
     /// If you require data in row major order `transpose` the matrix first.
     #[inline]
+    #[must_use]
     pub const fn to_cols_array_2d(&self) -> [[f32; 3]; 3] {
         [
             self.x_axis.to_array(),
@@ -138,6 +141,7 @@
     /// Creates a 3x3 matrix with its diagonal set to `diagonal` and all other entries set to 0.
     #[doc(alias = "scale")]
     #[inline]
+    #[must_use]
     pub const fn from_diagonal(diagonal: Vec3) -> Self {
         Self::new(
             diagonal.x, 0.0, 0.0, 0.0, diagonal.y, 0.0, 0.0, 0.0, diagonal.z,
@@ -145,6 +149,8 @@
     }
 
     /// Creates a 3x3 matrix from a 4x4 matrix, discarding the 4th row and column.
+    #[inline]
+    #[must_use]
     pub fn from_mat4(m: Mat4) -> Self {
         Self::from_cols(m.x_axis.into(), m.y_axis.into(), m.z_axis.into())
     }
@@ -155,6 +161,7 @@
     ///
     /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_quat(rotation: Quat) -> Self {
         glam_assert!(rotation.is_normalized());
 
@@ -185,10 +192,11 @@
     ///
     /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
         glam_assert!(axis.is_normalized());
 
-        let (sin, cos) = angle.sin_cos();
+        let (sin, cos) = math::sin_cos(angle);
         let (xsin, ysin, zsin) = axis.mul(sin).into();
         let (x, y, z) = axis.into();
         let (x2, y2, z2) = axis.mul(axis).into();
@@ -203,9 +211,10 @@
         )
     }
 
-    #[inline]
     /// Creates a 3D rotation matrix from the given euler rotation sequence and the angles (in
     /// radians).
+    #[inline]
+    #[must_use]
     pub fn from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self {
         let quat = Quat::from_euler(order, a, b, c);
         Self::from_quat(quat)
@@ -213,8 +222,9 @@
 
     /// Creates a 3D rotation matrix from `angle` (in radians) around the x axis.
     #[inline]
+    #[must_use]
     pub fn from_rotation_x(angle: f32) -> Self {
-        let (sina, cosa) = angle.sin_cos();
+        let (sina, cosa) = math::sin_cos(angle);
         Self::from_cols(
             Vec3A::X,
             Vec3A::new(0.0, cosa, sina),
@@ -224,8 +234,9 @@
 
     /// Creates a 3D rotation matrix from `angle` (in radians) around the y axis.
     #[inline]
+    #[must_use]
     pub fn from_rotation_y(angle: f32) -> Self {
-        let (sina, cosa) = angle.sin_cos();
+        let (sina, cosa) = math::sin_cos(angle);
         Self::from_cols(
             Vec3A::new(cosa, 0.0, -sina),
             Vec3A::Y,
@@ -235,8 +246,9 @@
 
     /// Creates a 3D rotation matrix from `angle` (in radians) around the z axis.
     #[inline]
+    #[must_use]
     pub fn from_rotation_z(angle: f32) -> Self {
-        let (sina, cosa) = angle.sin_cos();
+        let (sina, cosa) = math::sin_cos(angle);
         Self::from_cols(
             Vec3A::new(cosa, sina, 0.0),
             Vec3A::new(-sina, cosa, 0.0),
@@ -249,6 +261,7 @@
     /// The resulting matrix can be used to transform 2D points and vectors. See
     /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
     #[inline]
+    #[must_use]
     pub fn from_translation(translation: Vec2) -> Self {
         Self::from_cols(
             Vec3A::X,
@@ -263,8 +276,9 @@
     /// The resulting matrix can be used to transform 2D points and vectors. See
     /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
     #[inline]
+    #[must_use]
     pub fn from_angle(angle: f32) -> Self {
-        let (sin, cos) = angle.sin_cos();
+        let (sin, cos) = math::sin_cos(angle);
         Self::from_cols(
             Vec3A::new(cos, sin, 0.0),
             Vec3A::new(-sin, cos, 0.0),
@@ -278,8 +292,9 @@
     /// The resulting matrix can be used to transform 2D points and vectors. See
     /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
     #[inline]
+    #[must_use]
     pub fn from_scale_angle_translation(scale: Vec2, angle: f32, translation: Vec2) -> Self {
-        let (sin, cos) = angle.sin_cos();
+        let (sin, cos) = math::sin_cos(angle);
         Self::from_cols(
             Vec3A::new(cos * scale.x, sin * scale.x, 0.0),
             Vec3A::new(-sin * scale.y, cos * scale.y, 0.0),
@@ -296,6 +311,7 @@
     ///
     /// Will panic if all elements of `scale` are zero when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_scale(scale: Vec2) -> Self {
         // Do not panic as long as any component is non-zero
         glam_assert!(scale.cmpne(Vec2::ZERO).any());
@@ -322,6 +338,7 @@
     ///
     /// Panics if `slice` is less than 9 elements long.
     #[inline]
+    #[must_use]
     pub const fn from_cols_slice(slice: &[f32]) -> Self {
         Self::new(
             slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
@@ -353,6 +370,7 @@
     ///
     /// Panics if `index` is greater than 2.
     #[inline]
+    #[must_use]
     pub fn col(&self, index: usize) -> Vec3A {
         match index {
             0 => self.x_axis,
@@ -383,6 +401,7 @@
     ///
     /// Panics if `index` is greater than 2.
     #[inline]
+    #[must_use]
     pub fn row(&self, index: usize) -> Vec3A {
         match index {
             0 => Vec3A::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
@@ -395,52 +414,35 @@
     /// Returns `true` if, and only if, all elements are finite.
     /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
     #[inline]
+    #[must_use]
     pub fn is_finite(&self) -> bool {
         self.x_axis.is_finite() && self.y_axis.is_finite() && self.z_axis.is_finite()
     }
 
     /// Returns `true` if any elements are `NaN`.
     #[inline]
+    #[must_use]
     pub fn is_nan(&self) -> bool {
         self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan()
     }
 
     /// Returns the transpose of `self`.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn transpose(&self) -> Self {
-        let tmp0 = simd_swizzle!(
-            self.x_axis.0,
-            self.y_axis.0,
-            [First(0), First(1), Second(0), Second(1)]
-        );
-        let tmp1 = simd_swizzle!(
-            self.x_axis.0,
-            self.y_axis.0,
-            [First(2), First(3), Second(2), Second(3)]
-        );
+        let tmp0 = simd_swizzle!(self.x_axis.0, self.y_axis.0, [0, 1, 4, 5]);
+        let tmp1 = simd_swizzle!(self.x_axis.0, self.y_axis.0, [2, 3, 6, 7]);
 
         Self {
-            x_axis: Vec3A(simd_swizzle!(
-                tmp0,
-                self.z_axis.0,
-                [First(0), First(2), Second(0), Second(0)]
-            )),
-            y_axis: Vec3A(simd_swizzle!(
-                tmp0,
-                self.z_axis.0,
-                [First(1), First(3), Second(1), Second(1)]
-            )),
-            z_axis: Vec3A(simd_swizzle!(
-                tmp1,
-                self.z_axis.0,
-                [First(0), First(2), Second(2), Second(2)]
-            )),
+            x_axis: Vec3A(simd_swizzle!(tmp0, self.z_axis.0, [0, 2, 4, 4])),
+            y_axis: Vec3A(simd_swizzle!(tmp0, self.z_axis.0, [1, 3, 5, 5])),
+            z_axis: Vec3A(simd_swizzle!(tmp1, self.z_axis.0, [0, 2, 6, 6])),
         }
     }
 
     /// Returns the determinant of `self`.
     #[inline]
+    #[must_use]
     pub fn determinant(&self) -> f32 {
         self.z_axis.dot(self.x_axis.cross(self.y_axis))
     }
@@ -452,8 +454,8 @@
     /// # Panics
     ///
     /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn inverse(&self) -> Self {
         let tmp0 = self.y_axis.cross(self.z_axis);
         let tmp1 = self.z_axis.cross(self.x_axis);
@@ -474,6 +476,7 @@
     ///
     /// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn transform_point2(&self, rhs: Vec2) -> Vec2 {
         glam_assert!(self.row(2).abs_diff_eq(Vec3A::Z, 1e-6));
         Mat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs + self.z_axis.xy()
@@ -489,6 +492,7 @@
     ///
     /// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn transform_vector2(&self, rhs: Vec2) -> Vec2 {
         glam_assert!(self.row(2).abs_diff_eq(Vec3A::Z, 1e-6));
         Mat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs
@@ -496,12 +500,14 @@
 
     /// Transforms a 3D vector.
     #[inline]
+    #[must_use]
     pub fn mul_vec3(&self, rhs: Vec3) -> Vec3 {
         self.mul_vec3a(rhs.into()).into()
     }
 
-    /// Transforms a `Vec3A`.
+    /// Transforms a [`Vec3A`].
     #[inline]
+    #[must_use]
     pub fn mul_vec3a(&self, rhs: Vec3A) -> Vec3A {
         let mut res = self.x_axis.mul(rhs.xxx());
         res = res.add(self.y_axis.mul(rhs.yyy()));
@@ -511,6 +517,7 @@
 
     /// Multiplies two 3x3 matrices.
     #[inline]
+    #[must_use]
     pub fn mul_mat3(&self, rhs: &Self) -> Self {
         Self::from_cols(
             self.mul(rhs.x_axis),
@@ -521,6 +528,7 @@
 
     /// Adds two 3x3 matrices.
     #[inline]
+    #[must_use]
     pub fn add_mat3(&self, rhs: &Self) -> Self {
         Self::from_cols(
             self.x_axis.add(rhs.x_axis),
@@ -531,6 +539,7 @@
 
     /// Subtracts two 3x3 matrices.
     #[inline]
+    #[must_use]
     pub fn sub_mat3(&self, rhs: &Self) -> Self {
         Self::from_cols(
             self.x_axis.sub(rhs.x_axis),
@@ -541,6 +550,7 @@
 
     /// Multiplies a 3x3 matrix by a scalar.
     #[inline]
+    #[must_use]
     pub fn mul_scalar(&self, rhs: f32) -> Self {
         Self::from_cols(
             self.x_axis.mul(rhs),
@@ -559,6 +569,7 @@
     /// For more see
     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
     #[inline]
+    #[must_use]
     pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
         self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
             && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
diff --git a/src/f32/coresimd/mat4.rs b/src/f32/coresimd/mat4.rs
index 26239ba..b430fcd 100644
--- a/src/f32/coresimd/mat4.rs
+++ b/src/f32/coresimd/mat4.rs
@@ -1,19 +1,18 @@
 // Generated from mat.rs.tera template. Edit the template, not the generated file.
 
-use crate::{coresimd::*, swizzles::*, DMat4, EulerRot, Mat3, Mat3A, Quat, Vec3, Vec3A, Vec4};
+use crate::{
+    coresimd::*, f32::math, swizzles::*, DMat4, EulerRot, Mat3, Mat3A, Quat, Vec3, Vec3A, Vec4,
+};
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
 use core::iter::{Product, Sum};
 use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
 
-use core::simd::{Which::*, *};
+use core::simd::*;
 
-#[cfg(feature = "libm")]
-#[allow(unused_imports)]
-use num_traits::Float;
-
-/// Creates a 4x4 matrix from column vectors.
+/// Creates a 4x4 matrix from four column vectors.
 #[inline(always)]
+#[must_use]
 pub const fn mat4(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Mat4 {
     Mat4::from_cols(x_axis, y_axis, z_axis, w_axis)
 }
@@ -29,7 +28,7 @@
 /// using methods such as [`Self::from_translation()`], [`Self::from_quat()`],
 /// [`Self::from_scale()`] and [`Self::from_scale_rotation_translation()`].
 ///
-/// Othographic projections can be created using the methods [`Self::orthographic_lh()`] for
+/// Orthographic projections can be created using the methods [`Self::orthographic_lh()`] for
 /// left-handed coordinate systems and [`Self::orthographic_rh()`] for right-handed
 /// systems. The resulting matrix is also an affine transformation.
 ///
@@ -68,6 +67,7 @@
 
     #[allow(clippy::too_many_arguments)]
     #[inline(always)]
+    #[must_use]
     const fn new(
         m00: f32,
         m01: f32,
@@ -94,8 +94,9 @@
         }
     }
 
-    /// Creates a 4x4 matrix from two column vectors.
+    /// Creates a 4x4 matrix from four column vectors.
     #[inline(always)]
+    #[must_use]
     pub const fn from_cols(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Self {
         Self {
             x_axis,
@@ -109,6 +110,7 @@
     /// If your data is stored in row major you will need to `transpose` the returned
     /// matrix.
     #[inline]
+    #[must_use]
     pub const fn from_cols_array(m: &[f32; 16]) -> Self {
         Self::new(
             m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9], m[10], m[11], m[12], m[13],
@@ -119,6 +121,7 @@
     /// Creates a `[f32; 16]` array storing data in column major order.
     /// If you require data in row major order `transpose` the matrix first.
     #[inline]
+    #[must_use]
     pub const fn to_cols_array(&self) -> [f32; 16] {
         let [x_axis_x, x_axis_y, x_axis_z, x_axis_w] = self.x_axis.to_array();
         let [y_axis_x, y_axis_y, y_axis_z, y_axis_w] = self.y_axis.to_array();
@@ -135,6 +138,7 @@
     /// If your data is in row major order you will need to `transpose` the returned
     /// matrix.
     #[inline]
+    #[must_use]
     pub const fn from_cols_array_2d(m: &[[f32; 4]; 4]) -> Self {
         Self::from_cols(
             Vec4::from_array(m[0]),
@@ -147,6 +151,7 @@
     /// Creates a `[[f32; 4]; 4]` 4D array storing data in column major order.
     /// If you require data in row major order `transpose` the matrix first.
     #[inline]
+    #[must_use]
     pub const fn to_cols_array_2d(&self) -> [[f32; 4]; 4] {
         [
             self.x_axis.to_array(),
@@ -159,6 +164,7 @@
     /// Creates a 4x4 matrix with its diagonal set to `diagonal` and all other entries set to 0.
     #[doc(alias = "scale")]
     #[inline]
+    #[must_use]
     pub const fn from_diagonal(diagonal: Vec4) -> Self {
         // diagonal.x, diagonal.y etc can't be done in a const-context
         let [x, y, z, w] = diagonal.to_array();
@@ -168,6 +174,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn quat_to_axes(rotation: Quat) -> (Vec4, Vec4, Vec4) {
         glam_assert!(rotation.is_normalized());
 
@@ -201,6 +208,7 @@
     ///
     /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_scale_rotation_translation(scale: Vec3, rotation: Quat, translation: Vec3) -> Self {
         let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
         Self::from_cols(
@@ -220,6 +228,7 @@
     ///
     /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_rotation_translation(rotation: Quat, translation: Vec3) -> Self {
         let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
         Self::from_cols(x_axis, y_axis, z_axis, Vec4::from((translation, 1.0)))
@@ -233,12 +242,13 @@
     /// Will panic if the determinant of `self` is zero or if the resulting scale vector
     /// contains any zero elements when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn to_scale_rotation_translation(&self) -> (Vec3, Quat, Vec3) {
         let det = self.determinant();
         glam_assert!(det != 0.0);
 
         let scale = Vec3::new(
-            self.x_axis.length() * det.signum(),
+            self.x_axis.length() * math::signum(det),
             self.y_axis.length(),
             self.z_axis.length(),
         );
@@ -267,6 +277,7 @@
     ///
     /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_quat(rotation: Quat) -> Self {
         let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
         Self::from_cols(x_axis, y_axis, z_axis, Vec4::W)
@@ -278,6 +289,7 @@
     /// The resulting matrix can be used to transform 3D points and vectors. See
     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
     #[inline]
+    #[must_use]
     pub fn from_mat3(m: Mat3) -> Self {
         Self::from_cols(
             Vec4::from((m.x_axis, 0.0)),
@@ -293,6 +305,7 @@
     /// The resulting matrix can be used to transform 3D points and vectors. See
     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
     #[inline]
+    #[must_use]
     pub fn from_mat3a(m: Mat3A) -> Self {
         Self::from_cols(
             Vec4::from((m.x_axis, 0.0)),
@@ -307,6 +320,7 @@
     /// The resulting matrix can be used to transform 3D points and vectors. See
     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
     #[inline]
+    #[must_use]
     pub fn from_translation(translation: Vec3) -> Self {
         Self::from_cols(
             Vec4::X,
@@ -326,10 +340,11 @@
     ///
     /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
         glam_assert!(axis.is_normalized());
 
-        let (sin, cos) = angle.sin_cos();
+        let (sin, cos) = math::sin_cos(angle);
         let axis_sin = axis.mul(sin);
         let axis_sq = axis.mul(axis);
         let omc = 1.0 - cos;
@@ -359,12 +374,13 @@
         )
     }
 
-    #[inline]
     /// Creates a affine transformation matrix containing a rotation from the given euler
     /// rotation sequence and angles (in radians).
     ///
     /// The resulting matrix can be used to transform 3D points and vectors. See
     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
+    #[inline]
+    #[must_use]
     pub fn from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self {
         let quat = Quat::from_euler(order, a, b, c);
         Self::from_quat(quat)
@@ -376,8 +392,9 @@
     /// The resulting matrix can be used to transform 3D points and vectors. See
     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
     #[inline]
+    #[must_use]
     pub fn from_rotation_x(angle: f32) -> Self {
-        let (sina, cosa) = angle.sin_cos();
+        let (sina, cosa) = math::sin_cos(angle);
         Self::from_cols(
             Vec4::X,
             Vec4::new(0.0, cosa, sina, 0.0),
@@ -392,8 +409,9 @@
     /// The resulting matrix can be used to transform 3D points and vectors. See
     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
     #[inline]
+    #[must_use]
     pub fn from_rotation_y(angle: f32) -> Self {
-        let (sina, cosa) = angle.sin_cos();
+        let (sina, cosa) = math::sin_cos(angle);
         Self::from_cols(
             Vec4::new(cosa, 0.0, -sina, 0.0),
             Vec4::Y,
@@ -408,8 +426,9 @@
     /// The resulting matrix can be used to transform 3D points and vectors. See
     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
     #[inline]
+    #[must_use]
     pub fn from_rotation_z(angle: f32) -> Self {
-        let (sina, cosa) = angle.sin_cos();
+        let (sina, cosa) = math::sin_cos(angle);
         Self::from_cols(
             Vec4::new(cosa, sina, 0.0, 0.0),
             Vec4::new(-sina, cosa, 0.0, 0.0),
@@ -427,6 +446,7 @@
     ///
     /// Will panic if all elements of `scale` are zero when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_scale(scale: Vec3) -> Self {
         // Do not panic as long as any component is non-zero
         glam_assert!(scale.cmpne(Vec3::ZERO).any());
@@ -445,6 +465,7 @@
     ///
     /// Panics if `slice` is less than 16 elements long.
     #[inline]
+    #[must_use]
     pub const fn from_cols_slice(slice: &[f32]) -> Self {
         Self::new(
             slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
@@ -483,6 +504,7 @@
     ///
     /// Panics if `index` is greater than 3.
     #[inline]
+    #[must_use]
     pub fn col(&self, index: usize) -> Vec4 {
         match index {
             0 => self.x_axis,
@@ -515,6 +537,7 @@
     ///
     /// Panics if `index` is greater than 3.
     #[inline]
+    #[must_use]
     pub fn row(&self, index: usize) -> Vec4 {
         match index {
             0 => Vec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
@@ -528,6 +551,7 @@
     /// Returns `true` if, and only if, all elements are finite.
     /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
     #[inline]
+    #[must_use]
     pub fn is_finite(&self) -> bool {
         self.x_axis.is_finite()
             && self.y_axis.is_finite()
@@ -537,61 +561,31 @@
 
     /// Returns `true` if any elements are `NaN`.
     #[inline]
+    #[must_use]
     pub fn is_nan(&self) -> bool {
         self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan() || self.w_axis.is_nan()
     }
 
     /// Returns the transpose of `self`.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn transpose(&self) -> Self {
         // Based on https://github.com/microsoft/DirectXMath `XMMatrixTranspose`
-        let tmp0 = simd_swizzle!(
-            self.x_axis.0,
-            self.y_axis.0,
-            [First(0), First(1), Second(0), Second(1)]
-        );
-        let tmp1 = simd_swizzle!(
-            self.x_axis.0,
-            self.y_axis.0,
-            [First(2), First(3), Second(2), Second(3)]
-        );
-        let tmp2 = simd_swizzle!(
-            self.z_axis.0,
-            self.w_axis.0,
-            [First(0), First(1), Second(0), Second(1)]
-        );
-        let tmp3 = simd_swizzle!(
-            self.z_axis.0,
-            self.w_axis.0,
-            [First(2), First(3), Second(2), Second(3)]
-        );
+        let tmp0 = simd_swizzle!(self.x_axis.0, self.y_axis.0, [0, 1, 4, 5]);
+        let tmp1 = simd_swizzle!(self.x_axis.0, self.y_axis.0, [2, 3, 6, 7]);
+        let tmp2 = simd_swizzle!(self.z_axis.0, self.w_axis.0, [0, 1, 4, 5]);
+        let tmp3 = simd_swizzle!(self.z_axis.0, self.w_axis.0, [2, 3, 6, 7]);
 
         Self {
-            x_axis: Vec4(simd_swizzle!(
-                tmp0,
-                tmp2,
-                [First(0), First(2), Second(0), Second(2)]
-            )),
-            y_axis: Vec4(simd_swizzle!(
-                tmp0,
-                tmp2,
-                [First(1), First(3), Second(1), Second(3)]
-            )),
-            z_axis: Vec4(simd_swizzle!(
-                tmp1,
-                tmp3,
-                [First(0), First(2), Second(0), Second(2)]
-            )),
-            w_axis: Vec4(simd_swizzle!(
-                tmp1,
-                tmp3,
-                [First(1), First(3), Second(1), Second(3)]
-            )),
+            x_axis: Vec4(simd_swizzle!(tmp0, tmp2, [0, 2, 4, 6])),
+            y_axis: Vec4(simd_swizzle!(tmp0, tmp2, [1, 3, 5, 7])),
+            z_axis: Vec4(simd_swizzle!(tmp1, tmp3, [0, 2, 4, 6])),
+            w_axis: Vec4(simd_swizzle!(tmp1, tmp3, [1, 3, 5, 7])),
         }
     }
 
     /// Returns the determinant of `self`.
+    #[must_use]
     pub fn determinant(&self) -> f32 {
         // Based on https://github.com/g-truc/glm `glm_mat4_determinant`
         let swp2a = simd_swizzle!(self.z_axis.0, [2, 1, 1, 0]);
@@ -611,13 +605,13 @@
         let swpfaca = simd_swizzle!(self.y_axis.0, [1, 0, 0, 0]);
         let mulfaca = swpfaca * subfaca;
 
-        let subtmpb = simd_swizzle!(sube, subf, [First(1), First(3), Second(0), Second(0)]);
+        let subtmpb = simd_swizzle!(sube, subf, [1, 3, 4, 4]);
         let subfacb = simd_swizzle!(subtmpb, [0, 1, 1, 3]);
         let swpfacb = simd_swizzle!(self.y_axis.0, [2, 2, 1, 1]);
         let mulfacb = swpfacb * subfacb;
 
         let subres = mulfaca - mulfacb;
-        let subtmpc = simd_swizzle!(sube, subf, [First(2), First(2), Second(0), Second(1)]);
+        let subtmpc = simd_swizzle!(sube, subf, [2, 2, 4, 5]);
         let subfacc = simd_swizzle!(subtmpc, [0, 2, 3, 3]);
         let swpfacc = simd_swizzle!(self.y_axis.0, [3, 3, 3, 2]);
         let mulfacc = swpfacc * subfacc;
@@ -639,174 +633,78 @@
     pub fn inverse(&self) -> Self {
         // Based on https://github.com/g-truc/glm `glm_mat4_inverse`
         let fac0 = {
-            let swp0a = simd_swizzle!(
-                self.w_axis.0,
-                self.z_axis.0,
-                [First(3), First(3), Second(3), Second(3)]
-            );
-            let swp0b = simd_swizzle!(
-                self.w_axis.0,
-                self.z_axis.0,
-                [First(2), First(2), Second(2), Second(2)]
-            );
+            let swp0a = simd_swizzle!(self.w_axis.0, self.z_axis.0, [3, 3, 7, 7]);
+            let swp0b = simd_swizzle!(self.w_axis.0, self.z_axis.0, [2, 2, 6, 6]);
 
-            let swp00 = simd_swizzle!(
-                self.z_axis.0,
-                self.y_axis.0,
-                [First(2), First(2), Second(2), Second(2)]
-            );
+            let swp00 = simd_swizzle!(self.z_axis.0, self.y_axis.0, [2, 2, 6, 6]);
             let swp01 = simd_swizzle!(swp0a, [0, 0, 0, 2]);
             let swp02 = simd_swizzle!(swp0b, [0, 0, 0, 2]);
-            let swp03 = simd_swizzle!(
-                self.z_axis.0,
-                self.y_axis.0,
-                [First(3), First(3), Second(3), Second(3)]
-            );
+            let swp03 = simd_swizzle!(self.z_axis.0, self.y_axis.0, [3, 3, 7, 7]);
 
             let mul00 = swp00 * swp01;
             let mul01 = swp02 * swp03;
             mul00 - mul01
         };
         let fac1 = {
-            let swp0a = simd_swizzle!(
-                self.w_axis.0,
-                self.z_axis.0,
-                [First(3), First(3), Second(3), Second(3)]
-            );
-            let swp0b = simd_swizzle!(
-                self.w_axis.0,
-                self.z_axis.0,
-                [First(1), First(1), Second(1), Second(1)]
-            );
+            let swp0a = simd_swizzle!(self.w_axis.0, self.z_axis.0, [3, 3, 7, 7]);
+            let swp0b = simd_swizzle!(self.w_axis.0, self.z_axis.0, [1, 1, 5, 5]);
 
-            let swp00 = simd_swizzle!(
-                self.z_axis.0,
-                self.y_axis.0,
-                [First(1), First(1), Second(1), Second(1)]
-            );
+            let swp00 = simd_swizzle!(self.z_axis.0, self.y_axis.0, [1, 1, 5, 5]);
             let swp01 = simd_swizzle!(swp0a, [0, 0, 0, 2]);
             let swp02 = simd_swizzle!(swp0b, [0, 0, 0, 2]);
-            let swp03 = simd_swizzle!(
-                self.z_axis.0,
-                self.y_axis.0,
-                [First(3), First(3), Second(3), Second(3)]
-            );
+            let swp03 = simd_swizzle!(self.z_axis.0, self.y_axis.0, [3, 3, 7, 7]);
 
             let mul00 = swp00 * swp01;
             let mul01 = swp02 * swp03;
             mul00 - mul01
         };
         let fac2 = {
-            let swp0a = simd_swizzle!(
-                self.w_axis.0,
-                self.z_axis.0,
-                [First(2), First(2), Second(2), Second(2)]
-            );
-            let swp0b = simd_swizzle!(
-                self.w_axis.0,
-                self.z_axis.0,
-                [First(1), First(1), Second(1), Second(1)]
-            );
+            let swp0a = simd_swizzle!(self.w_axis.0, self.z_axis.0, [2, 2, 6, 6]);
+            let swp0b = simd_swizzle!(self.w_axis.0, self.z_axis.0, [1, 1, 5, 5]);
 
-            let swp00 = simd_swizzle!(
-                self.z_axis.0,
-                self.y_axis.0,
-                [First(1), First(1), Second(1), Second(1)]
-            );
+            let swp00 = simd_swizzle!(self.z_axis.0, self.y_axis.0, [1, 1, 5, 5]);
             let swp01 = simd_swizzle!(swp0a, [0, 0, 0, 2]);
             let swp02 = simd_swizzle!(swp0b, [0, 0, 0, 2]);
-            let swp03 = simd_swizzle!(
-                self.z_axis.0,
-                self.y_axis.0,
-                [First(2), First(2), Second(2), Second(2)]
-            );
+            let swp03 = simd_swizzle!(self.z_axis.0, self.y_axis.0, [2, 2, 6, 6]);
 
             let mul00 = swp00 * swp01;
             let mul01 = swp02 * swp03;
             mul00 - mul01
         };
         let fac3 = {
-            let swp0a = simd_swizzle!(
-                self.w_axis.0,
-                self.z_axis.0,
-                [First(3), First(3), Second(3), Second(3)]
-            );
-            let swp0b = simd_swizzle!(
-                self.w_axis.0,
-                self.z_axis.0,
-                [First(0), First(0), Second(0), Second(0)]
-            );
+            let swp0a = simd_swizzle!(self.w_axis.0, self.z_axis.0, [3, 3, 7, 7]);
+            let swp0b = simd_swizzle!(self.w_axis.0, self.z_axis.0, [0, 0, 4, 4]);
 
-            let swp00 = simd_swizzle!(
-                self.z_axis.0,
-                self.y_axis.0,
-                [First(0), First(0), Second(0), Second(0)]
-            );
+            let swp00 = simd_swizzle!(self.z_axis.0, self.y_axis.0, [0, 0, 4, 4]);
             let swp01 = simd_swizzle!(swp0a, [0, 0, 0, 2]);
             let swp02 = simd_swizzle!(swp0b, [0, 0, 0, 2]);
-            let swp03 = simd_swizzle!(
-                self.z_axis.0,
-                self.y_axis.0,
-                [First(3), First(3), Second(3), Second(3)]
-            );
+            let swp03 = simd_swizzle!(self.z_axis.0, self.y_axis.0, [3, 3, 7, 7]);
 
             let mul00 = swp00 * swp01;
             let mul01 = swp02 * swp03;
             mul00 - mul01
         };
         let fac4 = {
-            let swp0a = simd_swizzle!(
-                self.w_axis.0,
-                self.z_axis.0,
-                [First(2), First(2), Second(2), Second(2)]
-            );
-            let swp0b = simd_swizzle!(
-                self.w_axis.0,
-                self.z_axis.0,
-                [First(0), First(0), Second(0), Second(0)]
-            );
+            let swp0a = simd_swizzle!(self.w_axis.0, self.z_axis.0, [2, 2, 6, 6]);
+            let swp0b = simd_swizzle!(self.w_axis.0, self.z_axis.0, [0, 0, 4, 4]);
 
-            let swp00 = simd_swizzle!(
-                self.z_axis.0,
-                self.y_axis.0,
-                [First(0), First(0), Second(0), Second(0)]
-            );
+            let swp00 = simd_swizzle!(self.z_axis.0, self.y_axis.0, [0, 0, 4, 4]);
             let swp01 = simd_swizzle!(swp0a, [0, 0, 0, 2]);
             let swp02 = simd_swizzle!(swp0b, [0, 0, 0, 2]);
-            let swp03 = simd_swizzle!(
-                self.z_axis.0,
-                self.y_axis.0,
-                [First(2), First(2), Second(2), Second(2)]
-            );
+            let swp03 = simd_swizzle!(self.z_axis.0, self.y_axis.0, [2, 2, 6, 6]);
 
             let mul00 = swp00 * swp01;
             let mul01 = swp02 * swp03;
             mul00 - mul01
         };
         let fac5 = {
-            let swp0a = simd_swizzle!(
-                self.w_axis.0,
-                self.z_axis.0,
-                [First(1), First(1), Second(1), Second(1)]
-            );
-            let swp0b = simd_swizzle!(
-                self.w_axis.0,
-                self.z_axis.0,
-                [First(0), First(0), Second(0), Second(0)]
-            );
+            let swp0a = simd_swizzle!(self.w_axis.0, self.z_axis.0, [1, 1, 5, 5]);
+            let swp0b = simd_swizzle!(self.w_axis.0, self.z_axis.0, [0, 0, 4, 4]);
 
-            let swp00 = simd_swizzle!(
-                self.z_axis.0,
-                self.y_axis.0,
-                [First(0), First(0), Second(0), Second(0)]
-            );
+            let swp00 = simd_swizzle!(self.z_axis.0, self.y_axis.0, [0, 0, 4, 4]);
             let swp01 = simd_swizzle!(swp0a, [0, 0, 0, 2]);
             let swp02 = simd_swizzle!(swp0b, [0, 0, 0, 2]);
-            let swp03 = simd_swizzle!(
-                self.z_axis.0,
-                self.y_axis.0,
-                [First(1), First(1), Second(1), Second(1)]
-            );
+            let swp03 = simd_swizzle!(self.z_axis.0, self.y_axis.0, [1, 1, 5, 5]);
 
             let mul00 = swp00 * swp01;
             let mul01 = swp02 * swp03;
@@ -815,32 +713,16 @@
         let sign_a = f32x4::from_array([-1.0, 1.0, -1.0, 1.0]);
         let sign_b = f32x4::from_array([1.0, -1.0, 1.0, -1.0]);
 
-        let temp0 = simd_swizzle!(
-            self.y_axis.0,
-            self.x_axis.0,
-            [First(0), First(0), Second(0), Second(0)]
-        );
+        let temp0 = simd_swizzle!(self.y_axis.0, self.x_axis.0, [0, 0, 4, 4]);
         let vec0 = simd_swizzle!(temp0, [0, 2, 2, 2]);
 
-        let temp1 = simd_swizzle!(
-            self.y_axis.0,
-            self.x_axis.0,
-            [First(1), First(1), Second(1), Second(1)]
-        );
+        let temp1 = simd_swizzle!(self.y_axis.0, self.x_axis.0, [1, 1, 5, 5]);
         let vec1 = simd_swizzle!(temp1, [0, 2, 2, 2]);
 
-        let temp2 = simd_swizzle!(
-            self.y_axis.0,
-            self.x_axis.0,
-            [First(2), First(2), Second(2), Second(2)]
-        );
+        let temp2 = simd_swizzle!(self.y_axis.0, self.x_axis.0, [2, 2, 6, 6]);
         let vec2 = simd_swizzle!(temp2, [0, 2, 2, 2]);
 
-        let temp3 = simd_swizzle!(
-            self.y_axis.0,
-            self.x_axis.0,
-            [First(3), First(3), Second(3), Second(3)]
-        );
+        let temp3 = simd_swizzle!(self.y_axis.0, self.x_axis.0, [3, 3, 7, 7]);
         let vec3 = simd_swizzle!(temp3, [0, 2, 2, 2]);
 
         let mul00 = vec1 * fac0;
@@ -871,9 +753,9 @@
         let add03 = sub03 + mul11;
         let inv3 = sign_a * add03;
 
-        let row0 = simd_swizzle!(inv0, inv1, [First(0), First(0), Second(0), Second(0)]);
-        let row1 = simd_swizzle!(inv2, inv3, [First(0), First(0), Second(0), Second(0)]);
-        let row2 = simd_swizzle!(row0, row1, [First(0), First(2), Second(0), Second(2)]);
+        let row0 = simd_swizzle!(inv0, inv1, [0, 0, 4, 4]);
+        let row1 = simd_swizzle!(inv2, inv3, [0, 0, 4, 4]);
+        let row2 = simd_swizzle!(row0, row1, [0, 2, 4, 6]);
 
         let dot0 = dot4(self.x_axis.0, row2);
         glam_assert!(dot0 != 0.0);
@@ -893,6 +775,7 @@
     ///
     /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
     #[inline]
+    #[must_use]
     pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
         Self::look_to_rh(eye, -dir, up)
     }
@@ -902,6 +785,7 @@
     ///
     /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
     #[inline]
+    #[must_use]
     pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
         let f = dir.normalize();
         let s = f.cross(up).normalize();
@@ -923,6 +807,7 @@
     ///
     /// Will panic if `up` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
         glam_assert!(up.is_normalized());
         Self::look_to_lh(eye, center.sub(eye), up)
@@ -945,6 +830,7 @@
     /// This is the same as the OpenGL `gluPerspective` function.
     /// See <https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml>
     #[inline]
+    #[must_use]
     pub fn perspective_rh_gl(
         fov_y_radians: f32,
         aspect_ratio: f32,
@@ -952,7 +838,7 @@
         z_far: f32,
     ) -> Self {
         let inv_length = 1.0 / (z_near - z_far);
-        let f = 1.0 / (0.5 * fov_y_radians).tan();
+        let f = 1.0 / math::tan(0.5 * fov_y_radians);
         let a = f / aspect_ratio;
         let b = (z_near + z_far) * inv_length;
         let c = (2.0 * z_near * z_far) * inv_length;
@@ -971,9 +857,10 @@
     /// Will panic if `z_near` or `z_far` are less than or equal to zero when `glam_assert` is
     /// enabled.
     #[inline]
+    #[must_use]
     pub fn perspective_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
         glam_assert!(z_near > 0.0 && z_far > 0.0);
-        let (sin_fov, cos_fov) = (0.5 * fov_y_radians).sin_cos();
+        let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
         let h = cos_fov / sin_fov;
         let w = h / aspect_ratio;
         let r = z_far / (z_far - z_near);
@@ -992,9 +879,10 @@
     /// Will panic if `z_near` or `z_far` are less than or equal to zero when `glam_assert` is
     /// enabled.
     #[inline]
+    #[must_use]
     pub fn perspective_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
         glam_assert!(z_near > 0.0 && z_far > 0.0);
-        let (sin_fov, cos_fov) = (0.5 * fov_y_radians).sin_cos();
+        let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
         let h = cos_fov / sin_fov;
         let w = h / aspect_ratio;
         let r = z_far / (z_near - z_far);
@@ -1012,9 +900,10 @@
     ///
     /// Will panic if `z_near` is less than or equal to zero when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn perspective_infinite_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
         glam_assert!(z_near > 0.0);
-        let (sin_fov, cos_fov) = (0.5 * fov_y_radians).sin_cos();
+        let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
         let h = cos_fov / sin_fov;
         let w = h / aspect_ratio;
         Self::from_cols(
@@ -1031,13 +920,14 @@
     ///
     /// Will panic if `z_near` is less than or equal to zero when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn perspective_infinite_reverse_lh(
         fov_y_radians: f32,
         aspect_ratio: f32,
         z_near: f32,
     ) -> Self {
         glam_assert!(z_near > 0.0);
-        let (sin_fov, cos_fov) = (0.5 * fov_y_radians).sin_cos();
+        let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
         let h = cos_fov / sin_fov;
         let w = h / aspect_ratio;
         Self::from_cols(
@@ -1051,9 +941,10 @@
     /// Creates an infinite right-handed perspective projection matrix with
     /// `[0,1]` depth range.
     #[inline]
+    #[must_use]
     pub fn perspective_infinite_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
         glam_assert!(z_near > 0.0);
-        let f = 1.0 / (0.5 * fov_y_radians).tan();
+        let f = 1.0 / math::tan(0.5 * fov_y_radians);
         Self::from_cols(
             Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
             Vec4::new(0.0, f, 0.0, 0.0),
@@ -1065,13 +956,14 @@
     /// Creates an infinite reverse right-handed perspective projection matrix
     /// with `[0,1]` depth range.
     #[inline]
+    #[must_use]
     pub fn perspective_infinite_reverse_rh(
         fov_y_radians: f32,
         aspect_ratio: f32,
         z_near: f32,
     ) -> Self {
         glam_assert!(z_near > 0.0);
-        let f = 1.0 / (0.5 * fov_y_radians).tan();
+        let f = 1.0 / math::tan(0.5 * fov_y_radians);
         Self::from_cols(
             Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
             Vec4::new(0.0, f, 0.0, 0.0),
@@ -1085,6 +977,7 @@
     /// See
     /// <https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glOrtho.xml>
     #[inline]
+    #[must_use]
     pub fn orthographic_rh_gl(
         left: f32,
         right: f32,
@@ -1110,6 +1003,7 @@
 
     /// Creates a left-handed orthographic projection matrix with `[0,1]` depth range.
     #[inline]
+    #[must_use]
     pub fn orthographic_lh(
         left: f32,
         right: f32,
@@ -1136,6 +1030,7 @@
 
     /// Creates a right-handed orthographic projection matrix with `[0,1]` depth range.
     #[inline]
+    #[must_use]
     pub fn orthographic_rh(
         left: f32,
         right: f32,
@@ -1167,6 +1062,7 @@
     ///
     /// This method assumes that `self` contains a projective transform.
     #[inline]
+    #[must_use]
     pub fn project_point3(&self, rhs: Vec3) -> Vec3 {
         let mut res = self.x_axis.mul(rhs.x);
         res = self.y_axis.mul(rhs.y).add(res);
@@ -1189,6 +1085,7 @@
     ///
     /// Will panic if the 3rd row of `self` is not `(0, 0, 0, 1)` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn transform_point3(&self, rhs: Vec3) -> Vec3 {
         glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
         let mut res = self.x_axis.mul(rhs.x);
@@ -1209,6 +1106,7 @@
     ///
     /// Will panic if the 3rd row of `self` is not `(0, 0, 0, 1)` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn transform_vector3(&self, rhs: Vec3) -> Vec3 {
         glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
         let mut res = self.x_axis.mul(rhs.x);
@@ -1217,10 +1115,11 @@
         res.xyz()
     }
 
-    /// Transforms the given `Vec3A` as 3D point.
+    /// Transforms the given [`Vec3A`] as 3D point.
     ///
-    /// This is the equivalent of multiplying the `Vec3A` as a 4D vector where `w` is `1.0`.
+    /// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `1.0`.
     #[inline]
+    #[must_use]
     pub fn transform_point3a(&self, rhs: Vec3A) -> Vec3A {
         glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
         let mut res = self.x_axis.mul(rhs.xxxx());
@@ -1230,10 +1129,11 @@
         res.into()
     }
 
-    /// Transforms the give `Vec3A` as 3D vector.
+    /// Transforms the give [`Vec3A`] as 3D vector.
     ///
-    /// This is the equivalent of multiplying the `Vec3A` as a 4D vector where `w` is `0.0`.
+    /// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `0.0`.
     #[inline]
+    #[must_use]
     pub fn transform_vector3a(&self, rhs: Vec3A) -> Vec3A {
         glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
         let mut res = self.x_axis.mul(rhs.xxxx());
@@ -1244,6 +1144,7 @@
 
     /// Transforms a 4D vector.
     #[inline]
+    #[must_use]
     pub fn mul_vec4(&self, rhs: Vec4) -> Vec4 {
         let mut res = self.x_axis.mul(rhs.xxxx());
         res = res.add(self.y_axis.mul(rhs.yyyy()));
@@ -1254,6 +1155,7 @@
 
     /// Multiplies two 4x4 matrices.
     #[inline]
+    #[must_use]
     pub fn mul_mat4(&self, rhs: &Self) -> Self {
         Self::from_cols(
             self.mul(rhs.x_axis),
@@ -1265,6 +1167,7 @@
 
     /// Adds two 4x4 matrices.
     #[inline]
+    #[must_use]
     pub fn add_mat4(&self, rhs: &Self) -> Self {
         Self::from_cols(
             self.x_axis.add(rhs.x_axis),
@@ -1276,6 +1179,7 @@
 
     /// Subtracts two 4x4 matrices.
     #[inline]
+    #[must_use]
     pub fn sub_mat4(&self, rhs: &Self) -> Self {
         Self::from_cols(
             self.x_axis.sub(rhs.x_axis),
@@ -1287,6 +1191,7 @@
 
     /// Multiplies a 4x4 matrix by a scalar.
     #[inline]
+    #[must_use]
     pub fn mul_scalar(&self, rhs: f32) -> Self {
         Self::from_cols(
             self.x_axis.mul(rhs),
@@ -1306,6 +1211,7 @@
     /// For more see
     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
     #[inline]
+    #[must_use]
     pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
         self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
             && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
diff --git a/src/f32/coresimd/quat.rs b/src/f32/coresimd/quat.rs
index 21aa519..0d6d1af 100644
--- a/src/f32/coresimd/quat.rs
+++ b/src/f32/coresimd/quat.rs
@@ -3,13 +3,10 @@
 use crate::{
     coresimd::*,
     euler::{EulerFromQuaternion, EulerRot, EulerToQuaternion},
-    DQuat, FloatEx, Mat3, Mat3A, Mat4, Vec2, Vec3, Vec3A, Vec4,
+    f32::math,
+    DQuat, Mat3, Mat3A, Mat4, Vec2, Vec3, Vec3A, Vec4,
 };
 
-#[cfg(feature = "libm")]
-#[allow(unused_imports)]
-use num_traits::Float;
-
 use core::simd::*;
 
 #[cfg(not(target_arch = "spirv"))]
@@ -22,6 +19,7 @@
 /// This should generally not be called manually unless you know what you are doing. Use
 /// one of the other constructors instead such as `identity` or `from_axis_angle`.
 #[inline]
+#[must_use]
 pub const fn quat(x: f32, y: f32, z: f32, w: f32) -> Quat {
     Quat::from_xyzw(x, y, z, w)
 }
@@ -32,6 +30,8 @@
 /// floating point "error creep" which can occur when successive quaternion
 /// operations are applied.
 ///
+/// SIMD vector types are used for storage on supported platforms.
+///
 /// This type is 16 byte aligned.
 #[derive(Clone, Copy)]
 #[repr(transparent)]
@@ -59,6 +59,7 @@
     /// This function does not check if the input is normalized, it is up to the user to
     /// provide normalized input or to normalized the resulting quaternion.
     #[inline(always)]
+    #[must_use]
     pub const fn from_xyzw(x: f32, y: f32, z: f32, w: f32) -> Self {
         Self(f32x4::from_array([x, y, z, w]))
     }
@@ -70,6 +71,7 @@
     /// This function does not check if the input is normalized, it is up to the user to
     /// provide normalized input or to normalized the resulting quaternion.
     #[inline]
+    #[must_use]
     pub const fn from_array(a: [f32; 4]) -> Self {
         Self(f32x4::from_array(a))
     }
@@ -81,7 +83,8 @@
     /// This function does not check if the input is normalized, it is up to the user to
     /// provide normalized input or to normalized the resulting quaternion.
     #[inline]
-    pub fn from_vec4(v: Vec4) -> Self {
+    #[must_use]
+    pub const fn from_vec4(v: Vec4) -> Self {
         Self(v.0)
     }
 
@@ -96,6 +99,7 @@
     ///
     /// Panics if `slice` length is less than 4.
     #[inline]
+    #[must_use]
     pub fn from_slice(slice: &[f32]) -> Self {
         Self::from_xyzw(slice[0], slice[1], slice[2], slice[3])
     }
@@ -114,15 +118,17 @@
     }
 
     /// Create a quaternion for a normalized rotation `axis` and `angle` (in radians).
-    /// The axis must be normalized (unit-length).
+    ///
+    /// The axis must be a unit vector.
     ///
     /// # Panics
     ///
     /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
         glam_assert!(axis.is_normalized());
-        let (s, c) = (angle * 0.5).sin_cos();
+        let (s, c) = math::sin_cos(angle * 0.5);
         let v = axis * s;
         Self::from_xyzw(v.x, v.y, v.z, c)
     }
@@ -131,6 +137,7 @@
     ///
     /// `from_scaled_axis(Vec3::ZERO)` results in the identity quaternion.
     #[inline]
+    #[must_use]
     pub fn from_scaled_axis(v: Vec3) -> Self {
         let length = v.length();
         if length == 0.0 {
@@ -142,33 +149,38 @@
 
     /// Creates a quaternion from the `angle` (in radians) around the x axis.
     #[inline]
+    #[must_use]
     pub fn from_rotation_x(angle: f32) -> Self {
-        let (s, c) = (angle * 0.5).sin_cos();
+        let (s, c) = math::sin_cos(angle * 0.5);
         Self::from_xyzw(s, 0.0, 0.0, c)
     }
 
     /// Creates a quaternion from the `angle` (in radians) around the y axis.
     #[inline]
+    #[must_use]
     pub fn from_rotation_y(angle: f32) -> Self {
-        let (s, c) = (angle * 0.5).sin_cos();
+        let (s, c) = math::sin_cos(angle * 0.5);
         Self::from_xyzw(0.0, s, 0.0, c)
     }
 
     /// Creates a quaternion from the `angle` (in radians) around the z axis.
     #[inline]
+    #[must_use]
     pub fn from_rotation_z(angle: f32) -> Self {
-        let (s, c) = (angle * 0.5).sin_cos();
+        let (s, c) = math::sin_cos(angle * 0.5);
         Self::from_xyzw(0.0, 0.0, s, c)
     }
 
-    #[inline]
     /// Creates a quaternion from the given Euler rotation sequence and the angles (in radians).
+    #[inline]
+    #[must_use]
     pub fn from_euler(euler: EulerRot, a: f32, b: f32, c: f32) -> Self {
         euler.new_quat(a, b, c)
     }
 
     /// From the columns of a 3x3 rotation matrix.
     #[inline]
+    #[must_use]
     pub(crate) fn from_rotation_axes(x_axis: Vec3, y_axis: Vec3, z_axis: Vec3) -> Self {
         // Based on https://github.com/microsoft/DirectXMath `XM$quaternionRotationMatrix`
         let (m00, m01, m02) = x_axis.into();
@@ -181,7 +193,7 @@
             if dif10 <= 0.0 {
                 // x^2 >= y^2
                 let four_xsq = omm22 - dif10;
-                let inv4x = 0.5 / four_xsq.sqrt();
+                let inv4x = 0.5 / math::sqrt(four_xsq);
                 Self::from_xyzw(
                     four_xsq * inv4x,
                     (m01 + m10) * inv4x,
@@ -191,7 +203,7 @@
             } else {
                 // y^2 >= x^2
                 let four_ysq = omm22 + dif10;
-                let inv4y = 0.5 / four_ysq.sqrt();
+                let inv4y = 0.5 / math::sqrt(four_ysq);
                 Self::from_xyzw(
                     (m01 + m10) * inv4y,
                     four_ysq * inv4y,
@@ -206,7 +218,7 @@
             if sum10 <= 0.0 {
                 // z^2 >= w^2
                 let four_zsq = opm22 - sum10;
-                let inv4z = 0.5 / four_zsq.sqrt();
+                let inv4z = 0.5 / math::sqrt(four_zsq);
                 Self::from_xyzw(
                     (m02 + m20) * inv4z,
                     (m12 + m21) * inv4z,
@@ -216,7 +228,7 @@
             } else {
                 // w^2 >= z^2
                 let four_wsq = opm22 + sum10;
-                let inv4w = 0.5 / four_wsq.sqrt();
+                let inv4w = 0.5 / math::sqrt(four_wsq);
                 Self::from_xyzw(
                     (m12 - m21) * inv4w,
                     (m20 - m02) * inv4w,
@@ -229,18 +241,21 @@
 
     /// Creates a quaternion from a 3x3 rotation matrix.
     #[inline]
+    #[must_use]
     pub fn from_mat3(mat: &Mat3) -> Self {
         Self::from_rotation_axes(mat.x_axis, mat.y_axis, mat.z_axis)
     }
 
     /// Creates a quaternion from a 3x3 SIMD aligned rotation matrix.
     #[inline]
+    #[must_use]
     pub fn from_mat3a(mat: &Mat3A) -> Self {
         Self::from_rotation_axes(mat.x_axis.into(), mat.y_axis.into(), mat.z_axis.into())
     }
 
     /// Creates a quaternion from a 3x3 rotation matrix inside a homogeneous 4x4 matrix.
     #[inline]
+    #[must_use]
     pub fn from_mat4(mat: &Mat4) -> Self {
         Self::from_rotation_axes(
             mat.x_axis.truncate(),
@@ -252,7 +267,7 @@
     /// Gets the minimal rotation for transforming `from` to `to`.  The rotation is in the
     /// plane spanned by the two vectors.  Will rotate at most 180 degrees.
     ///
-    /// The input vectors must be normalized (unit-length).
+    /// The inputs must be unit vectors.
     ///
     /// `from_rotation_arc(from, to) * from ≈ to`.
     ///
@@ -262,6 +277,7 @@
     /// # Panics
     ///
     /// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
+    #[must_use]
     pub fn from_rotation_arc(from: Vec3, to: Vec3) -> Self {
         glam_assert!(from.is_normalized());
         glam_assert!(to.is_normalized());
@@ -287,7 +303,7 @@
     /// The rotation is in the plane spanned by the two vectors.  Will rotate at most 90
     /// degrees.
     ///
-    /// The input vectors must be normalized (unit-length).
+    /// The inputs must be unit vectors.
     ///
     /// `to.dot(from_rotation_arc_colinear(from, to) * from).abs() ≈ 1`.
     ///
@@ -295,6 +311,7 @@
     ///
     /// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_rotation_arc_colinear(from: Vec3, to: Vec3) -> Self {
         if from.dot(to) < 0.0 {
             Self::from_rotation_arc(from, -to)
@@ -306,7 +323,7 @@
     /// Gets the minimal rotation for transforming `from` to `to`.  The resulting rotation is
     /// around the z axis. Will rotate at most 180 degrees.
     ///
-    /// The input vectors must be normalized (unit-length).
+    /// The inputs must be unit vectors.
     ///
     /// `from_rotation_arc_2d(from, to) * from ≈ to`.
     ///
@@ -316,6 +333,7 @@
     /// # Panics
     ///
     /// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
+    #[must_use]
     pub fn from_rotation_arc_2d(from: Vec2, to: Vec2) -> Self {
         glam_assert!(from.is_normalized());
         glam_assert!(to.is_normalized());
@@ -336,31 +354,30 @@
             let z = from.x * to.y - to.x * from.y;
             let w = 1.0 + dot;
             // calculate length with x=0 and y=0 to normalize
-            let len_rcp = 1.0 / (z * z + w * w).sqrt();
+            let len_rcp = 1.0 / math::sqrt(z * z + w * w);
             Self::from_xyzw(0.0, 0.0, z * len_rcp, w * len_rcp)
         }
     }
 
-    /// Returns the rotation axis and angle (in radians) of `self`.
+    /// Returns the rotation axis (normalized) and angle (in radians) of `self`.
     #[inline]
+    #[must_use]
     pub fn to_axis_angle(self) -> (Vec3, f32) {
         const EPSILON: f32 = 1.0e-8;
-        const EPSILON_SQUARED: f32 = EPSILON * EPSILON;
-        let w = self.w;
-        let angle = w.acos_approx() * 2.0;
-        let scale_sq = f32::max(1.0 - w * w, 0.0);
-        if scale_sq >= EPSILON_SQUARED {
-            (
-                Vec3::new(self.x, self.y, self.z) * scale_sq.sqrt().recip(),
-                angle,
-            )
+        let v = Vec3::new(self.x, self.y, self.z);
+        let length = v.length();
+        if length >= EPSILON {
+            let angle = 2.0 * math::atan2(length, self.w);
+            let axis = v / length;
+            (axis, angle)
         } else {
-            (Vec3::X, angle)
+            (Vec3::X, 0.0)
         }
     }
 
     /// Returns the rotation axis scaled by the rotation in radians.
     #[inline]
+    #[must_use]
     pub fn to_scaled_axis(self) -> Vec3 {
         let (axis, angle) = self.to_axis_angle();
         axis * angle
@@ -368,26 +385,29 @@
 
     /// Returns the rotation angles for the given euler rotation sequence.
     #[inline]
+    #[must_use]
     pub fn to_euler(self, euler: EulerRot) -> (f32, f32, f32) {
         euler.convert_quat(self)
     }
 
     /// `[x, y, z, w]`
     #[inline]
+    #[must_use]
     pub fn to_array(&self) -> [f32; 4] {
         [self.x, self.y, self.z, self.w]
     }
 
     /// Returns the vector part of the quaternion.
     #[inline]
+    #[must_use]
     pub fn xyz(self) -> Vec3 {
         Vec3::new(self.x, self.y, self.z)
     }
 
     /// Returns the quaternion conjugate of `self`. For a unit quaternion the
     /// conjugate is also the inverse.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn conjugate(self) -> Self {
         const SIGN: f32x4 = f32x4::from_array([-1.0, -1.0, -1.0, 1.0]);
         Self(self.0.mul(SIGN))
@@ -402,8 +422,8 @@
     /// # Panics
     ///
     /// Will panic if `self` is not normalized when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn inverse(self) -> Self {
         glam_assert!(self.is_normalized());
         self.conjugate()
@@ -412,6 +432,7 @@
     /// Computes the dot product of `self` and `rhs`. The dot product is
     /// equal to the cosine of the angle between two quaternion rotations.
     #[inline]
+    #[must_use]
     pub fn dot(self, rhs: Self) -> f32 {
         Vec4::from(self).dot(Vec4::from(rhs))
     }
@@ -419,6 +440,7 @@
     /// Computes the length of `self`.
     #[doc(alias = "magnitude")]
     #[inline]
+    #[must_use]
     pub fn length(self) -> f32 {
         Vec4::from(self).length()
     }
@@ -429,6 +451,7 @@
     /// root operation.
     #[doc(alias = "magnitude2")]
     #[inline]
+    #[must_use]
     pub fn length_squared(self) -> f32 {
         Vec4::from(self).length_squared()
     }
@@ -437,6 +460,7 @@
     ///
     /// For valid results, `self` must _not_ be of length zero.
     #[inline]
+    #[must_use]
     pub fn length_recip(self) -> f32 {
         Vec4::from(self).length_recip()
     }
@@ -448,8 +472,8 @@
     /// Panics
     ///
     /// Will panic if `self` is zero length when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn normalize(self) -> Self {
         Self::from_vec4(Vec4::from(self).normalize())
     }
@@ -457,11 +481,13 @@
     /// Returns `true` if, and only if, all elements are finite.
     /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
     #[inline]
+    #[must_use]
     pub fn is_finite(self) -> bool {
         Vec4::from(self).is_finite()
     }
 
     #[inline]
+    #[must_use]
     pub fn is_nan(self) -> bool {
         Vec4::from(self).is_nan()
     }
@@ -470,11 +496,13 @@
     ///
     /// Uses a precision threshold of `1e-6`.
     #[inline]
+    #[must_use]
     pub fn is_normalized(self) -> bool {
         Vec4::from(self).is_normalized()
     }
 
     #[inline]
+    #[must_use]
     pub fn is_near_identity(self) -> bool {
         // Based on https://github.com/nfrechette/rtm `rtm::quat_near_identity`
         let threshold_angle = 0.002_847_144_6;
@@ -491,7 +519,7 @@
         // If the quat.w is close to -1.0, the angle will be near 2*PI which is close to
         // a negative 0 rotation. By forcing quat.w to be positive, we'll end up with
         // the shortest path.
-        let positive_w_angle = self.w.abs().acos_approx() * 2.0;
+        let positive_w_angle = math::acos_approx(math::abs(self.w)) * 2.0;
         positive_w_angle < threshold_angle
     }
 
@@ -504,9 +532,10 @@
     ///
     /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn angle_between(self, rhs: Self) -> f32 {
         glam_assert!(self.is_normalized() && rhs.is_normalized());
-        self.dot(rhs).abs().acos_approx() * 2.0
+        math::acos_approx(math::abs(self.dot(rhs))) * 2.0
     }
 
     /// Returns true if the absolute difference of all elements between `self` and `rhs`
@@ -519,6 +548,7 @@
     /// For more see
     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
     #[inline]
+    #[must_use]
     pub fn abs_diff_eq(self, rhs: Self, max_abs_diff: f32) -> bool {
         Vec4::from(self).abs_diff_eq(Vec4::from(rhs), max_abs_diff)
     }
@@ -532,8 +562,9 @@
     /// # Panics
     ///
     /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
-    #[inline]
     #[doc(alias = "mix")]
+    #[inline]
+    #[must_use]
     pub fn lerp(self, end: Self, s: f32) -> Self {
         glam_assert!(self.is_normalized());
         glam_assert!(end.is_normalized());
@@ -559,6 +590,7 @@
     ///
     /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn slerp(self, mut end: Self, s: f32) -> Self {
         // http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/
         glam_assert!(self.is_normalized());
@@ -582,11 +614,11 @@
             // assumes lerp returns a normalized quaternion
             self.lerp(end, s)
         } else {
-            let theta = dot.acos_approx();
+            let theta = math::acos_approx(dot);
 
-            let x = (theta * (1.0 - s)).sin();
-            let y = (theta * s).sin();
-            let z = theta.sin();
+            let x = math::sin(theta * (1.0 - s));
+            let y = math::sin(theta * s);
+            let z = math::sin(theta);
             let w = 0.0;
             let tmp = f32x4::from_array([x, y, z, w]);
 
@@ -604,6 +636,7 @@
     ///
     /// Will panic if `self` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn mul_vec3(self, rhs: Vec3) -> Vec3 {
         glam_assert!(self.is_normalized());
 
@@ -619,6 +652,7 @@
     ///
     /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn mul_quat(self, rhs: Self) -> Self {
         glam_assert!(self.is_normalized());
         glam_assert!(rhs.is_normalized());
@@ -658,6 +692,7 @@
 
     /// Creates a quaternion from a 3x3 rotation matrix inside a 3D affine transform.
     #[inline]
+    #[must_use]
     pub fn from_affine3(a: &crate::Affine3A) -> Self {
         #[allow(clippy::useless_conversion)]
         Self::from_rotation_axes(
@@ -669,6 +704,7 @@
 
     /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
     #[inline]
+    #[must_use]
     pub fn mul_vec3a(self, rhs: Vec3A) -> Vec3A {
         const TWO: f32x4 = f32x4::from_array([2.0; 4]);
         let w = simd_swizzle!(self.0, [3, 3, 3, 3]);
@@ -683,9 +719,17 @@
     }
 
     #[inline]
-    pub fn as_f64(self) -> DQuat {
+    #[must_use]
+    pub fn as_dquat(self) -> DQuat {
         DQuat::from_xyzw(self.x as f64, self.y as f64, self.z as f64, self.w as f64)
     }
+
+    #[inline]
+    #[must_use]
+    #[deprecated(since = "0.24.2", note = "Use as_dquat() instead")]
+    pub fn as_f64(self) -> DQuat {
+        self.as_dquat()
+    }
 }
 
 #[cfg(not(target_arch = "spirv"))]
diff --git a/src/f32/coresimd/vec3a.rs b/src/f32/coresimd/vec3a.rs
index 86e16d9..559143e 100644
--- a/src/f32/coresimd/vec3a.rs
+++ b/src/f32/coresimd/vec3a.rs
@@ -1,31 +1,31 @@
 // Generated from vec.rs.tera template. Edit the template, not the generated file.
 
-use crate::{coresimd::*, BVec3A, Vec2, Vec3, Vec4};
+use crate::{coresimd::*, f32::math, BVec3A, Vec2, Vec3, Vec4};
 
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
 use core::iter::{Product, Sum};
 use core::{f32, ops::*};
 
-use core::simd::*;
+use core::simd::{cmp::SimdPartialEq, cmp::SimdPartialOrd, num::SimdFloat, *};
 use std::simd::StdFloat;
 
-#[cfg(feature = "libm")]
-#[allow(unused_imports)]
-use num_traits::Float;
-
 /// Creates a 3-dimensional vector.
 #[inline(always)]
+#[must_use]
 pub const fn vec3a(x: f32, y: f32, z: f32) -> Vec3A {
     Vec3A::new(x, y, z)
 }
 
-/// A 3-dimensional vector with SIMD support.
+/// A 3-dimensional vector.
 ///
-/// This type is 16 byte aligned. A SIMD vector type is used for storage on supported platforms for
-/// better performance than the `Vec3` type.
+/// SIMD vector types are used for storage on supported platforms for better
+/// performance than the [`Vec3`] type.
 ///
-/// It is possible to convert between `Vec3` and `Vec3A` types using `From` trait implementations.
+/// It is possible to convert between [`Vec3`] and [`Vec3A`] types using [`From`]
+/// or [`Into`] trait implementations.
+///
+/// This type is 16 byte aligned.
 #[derive(Clone, Copy)]
 #[repr(transparent)]
 pub struct Vec3A(pub(crate) f32x4);
@@ -40,25 +40,37 @@
     /// All negative ones.
     pub const NEG_ONE: Self = Self::splat(-1.0);
 
-    /// All NAN.
+    /// All `f32::MIN`.
+    pub const MIN: Self = Self::splat(f32::MIN);
+
+    /// All `f32::MAX`.
+    pub const MAX: Self = Self::splat(f32::MAX);
+
+    /// All `f32::NAN`.
     pub const NAN: Self = Self::splat(f32::NAN);
 
-    /// A unit-length vector pointing along the positive X axis.
+    /// All `f32::INFINITY`.
+    pub const INFINITY: Self = Self::splat(f32::INFINITY);
+
+    /// All `f32::NEG_INFINITY`.
+    pub const NEG_INFINITY: Self = Self::splat(f32::NEG_INFINITY);
+
+    /// A unit vector pointing along the positive X axis.
     pub const X: Self = Self::new(1.0, 0.0, 0.0);
 
-    /// A unit-length vector pointing along the positive Y axis.
+    /// A unit vector pointing along the positive Y axis.
     pub const Y: Self = Self::new(0.0, 1.0, 0.0);
 
-    /// A unit-length vector pointing along the positive Z axis.
+    /// A unit vector pointing along the positive Z axis.
     pub const Z: Self = Self::new(0.0, 0.0, 1.0);
 
-    /// A unit-length vector pointing along the negative X axis.
+    /// A unit vector pointing along the negative X axis.
     pub const NEG_X: Self = Self::new(-1.0, 0.0, 0.0);
 
-    /// A unit-length vector pointing along the negative Y axis.
+    /// A unit vector pointing along the negative Y axis.
     pub const NEG_Y: Self = Self::new(0.0, -1.0, 0.0);
 
-    /// A unit-length vector pointing along the negative Z axis.
+    /// A unit vector pointing along the negative Z axis.
     pub const NEG_Z: Self = Self::new(0.0, 0.0, -1.0);
 
     /// The unit axes.
@@ -66,12 +78,14 @@
 
     /// Creates a new vector.
     #[inline(always)]
+    #[must_use]
     pub const fn new(x: f32, y: f32, z: f32) -> Self {
         Self(f32x4::from_array([x, y, z, z]))
     }
 
     /// Creates a vector with all elements set to `v`.
     #[inline]
+    #[must_use]
     pub const fn splat(v: f32) -> Self {
         Self(Simd::from_array([v; 4]))
     }
@@ -82,18 +96,21 @@
     /// A true element in the mask uses the corresponding element from `if_true`, and false
     /// uses the element from `if_false`.
     #[inline]
+    #[must_use]
     pub fn select(mask: BVec3A, if_true: Self, if_false: Self) -> Self {
         Self(mask.0.select(if_true.0, if_false.0))
     }
 
     /// Creates a new vector from an array.
     #[inline]
+    #[must_use]
     pub const fn from_array(a: [f32; 3]) -> Self {
         Self::new(a[0], a[1], a[2])
     }
 
     /// `[x, y, z]`
     #[inline]
+    #[must_use]
     pub const fn to_array(&self) -> [f32; 3] {
         unsafe { *(self as *const Vec3A as *const [f32; 3]) }
     }
@@ -104,6 +121,7 @@
     ///
     /// Panics if `slice` is less than 3 elements long.
     #[inline]
+    #[must_use]
     pub const fn from_slice(slice: &[f32]) -> Self {
         Self::new(slice[0], slice[1], slice[2])
     }
@@ -123,20 +141,23 @@
     /// Internal method for creating a 3D vector from a 4D vector, discarding `w`.
     #[allow(dead_code)]
     #[inline]
+    #[must_use]
     pub(crate) fn from_vec4(v: Vec4) -> Self {
         Self(v.0)
     }
 
     /// Creates a 4D vector from `self` and the given `w` value.
     #[inline]
+    #[must_use]
     pub fn extend(self, w: f32) -> Vec4 {
         Vec4::new(self.x, self.y, self.z, w)
     }
 
     /// Creates a 2D vector from the `x` and `y` elements of `self`, discarding `z`.
     ///
-    /// Truncation may also be performed by using `self.xy()` or `Vec2::from()`.
+    /// Truncation may also be performed by using [`self.xy()`][crate::swizzles::Vec3Swizzles::xy()].
     #[inline]
+    #[must_use]
     pub fn truncate(self) -> Vec2 {
         use crate::swizzles::Vec3Swizzles;
         self.xy()
@@ -144,18 +165,21 @@
 
     /// Computes the dot product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn dot(self, rhs: Self) -> f32 {
         dot3(self.0, rhs.0)
     }
 
     /// Returns a vector where every component is the dot product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn dot_into_vec(self, rhs: Self) -> Self {
-        Self(unsafe { dot3_into_f32x4(self.0, rhs.0) })
+        Self(dot3_into_f32x4(self.0, rhs.0))
     }
 
     /// Computes the cross product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn cross(self, rhs: Self) -> Self {
         let lhszxy = simd_swizzle!(self.0, [2, 0, 1, 1]);
         let rhszxy = simd_swizzle!(rhs.0, [2, 0, 1, 1]);
@@ -169,6 +193,7 @@
     ///
     /// In other words this computes `[self.x.min(rhs.x), self.y.min(rhs.y), ..]`.
     #[inline]
+    #[must_use]
     pub fn min(self, rhs: Self) -> Self {
         Self(self.0.simd_min(rhs.0))
     }
@@ -177,6 +202,7 @@
     ///
     /// In other words this computes `[self.x.max(rhs.x), self.y.max(rhs.y), ..]`.
     #[inline]
+    #[must_use]
     pub fn max(self, rhs: Self) -> Self {
         Self(self.0.simd_max(rhs.0))
     }
@@ -189,6 +215,7 @@
     ///
     /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn clamp(self, min: Self, max: Self) -> Self {
         glam_assert!(min.cmple(max).all(), "clamp: expected min <= max");
         self.max(min).min(max)
@@ -198,6 +225,7 @@
     ///
     /// In other words this computes `min(x, y, ..)`.
     #[inline]
+    #[must_use]
     pub fn min_element(self) -> f32 {
         let v = self.0;
         let v = v.simd_min(simd_swizzle!(v, [2, 2, 1, 1]));
@@ -209,6 +237,7 @@
     ///
     /// In other words this computes `max(x, y, ..)`.
     #[inline]
+    #[must_use]
     pub fn max_element(self) -> f32 {
         let v = self.0;
         let v = v.simd_max(simd_swizzle!(v, [2, 2, 0, 0]));
@@ -222,6 +251,7 @@
     /// In other words, this computes `[self.x == rhs.x, self.y == rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpeq(self, rhs: Self) -> BVec3A {
         BVec3A(f32x4::simd_eq(self.0, rhs.0))
     }
@@ -232,6 +262,7 @@
     /// In other words this computes `[self.x != rhs.x, self.y != rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpne(self, rhs: Self) -> BVec3A {
         BVec3A(f32x4::simd_ne(self.0, rhs.0))
     }
@@ -242,6 +273,7 @@
     /// In other words this computes `[self.x >= rhs.x, self.y >= rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpge(self, rhs: Self) -> BVec3A {
         BVec3A(f32x4::simd_ge(self.0, rhs.0))
     }
@@ -252,6 +284,7 @@
     /// In other words this computes `[self.x > rhs.x, self.y > rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpgt(self, rhs: Self) -> BVec3A {
         BVec3A(f32x4::simd_gt(self.0, rhs.0))
     }
@@ -262,6 +295,7 @@
     /// In other words this computes `[self.x <= rhs.x, self.y <= rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmple(self, rhs: Self) -> BVec3A {
         BVec3A(f32x4::simd_le(self.0, rhs.0))
     }
@@ -272,12 +306,14 @@
     /// In other words this computes `[self.x < rhs.x, self.y < rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmplt(self, rhs: Self) -> BVec3A {
         BVec3A(f32x4::simd_lt(self.0, rhs.0))
     }
 
     /// Returns a vector containing the absolute value of each element of `self`.
     #[inline]
+    #[must_use]
     pub fn abs(self) -> Self {
         Self(self.0.abs())
     }
@@ -288,12 +324,14 @@
     /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
     /// - `NAN` if the number is `NAN`
     #[inline]
+    #[must_use]
     pub fn signum(self) -> Self {
         Self(self.0.signum())
     }
 
     /// Returns a vector with signs of `rhs` and the magnitudes of `self`.
     #[inline]
+    #[must_use]
     pub fn copysign(self, rhs: Self) -> Self {
         Self(self.0.copysign(rhs.0))
     }
@@ -303,6 +341,7 @@
     /// A negative element results in a `1` bit and a positive element in a `0` bit.  Element `x` goes
     /// into the first lowest bit, element `y` into the second, etc.
     #[inline]
+    #[must_use]
     pub fn is_negative_bitmask(self) -> u32 {
         (self.0.is_sign_negative().to_bitmask() & 0x7) as u32
     }
@@ -310,6 +349,7 @@
     /// Returns `true` if, and only if, all elements are finite.  If any element is either
     /// `NaN`, positive or negative infinity, this will return `false`.
     #[inline]
+    #[must_use]
     pub fn is_finite(self) -> bool {
         f32x4::is_finite(self.0)
             .bitor(mask32x4::from_array([false, false, false, true]))
@@ -318,6 +358,7 @@
 
     /// Returns `true` if any elements are `NaN`.
     #[inline]
+    #[must_use]
     pub fn is_nan(self) -> bool {
         self.is_nan_mask().any()
     }
@@ -326,6 +367,7 @@
     ///
     /// In other words, this computes `[x.is_nan(), y.is_nan(), z.is_nan(), w.is_nan()]`.
     #[inline]
+    #[must_use]
     pub fn is_nan_mask(self) -> BVec3A {
         BVec3A(f32x4::is_nan(self.0))
     }
@@ -333,6 +375,7 @@
     /// Computes the length of `self`.
     #[doc(alias = "magnitude")]
     #[inline]
+    #[must_use]
     pub fn length(self) -> f32 {
         let dot = dot3_in_x(self.0, self.0);
         dot.sqrt()[0]
@@ -343,6 +386,7 @@
     /// This is faster than `length()` as it avoids a square root operation.
     #[doc(alias = "magnitude2")]
     #[inline]
+    #[must_use]
     pub fn length_squared(self) -> f32 {
         self.dot(self)
     }
@@ -351,6 +395,7 @@
     ///
     /// For valid results, `self` must _not_ be of length zero.
     #[inline]
+    #[must_use]
     pub fn length_recip(self) -> f32 {
         let dot = dot3_in_x(self.0, self.0);
         dot.sqrt().recip()[0]
@@ -358,27 +403,53 @@
 
     /// Computes the Euclidean distance between two points in space.
     #[inline]
+    #[must_use]
     pub fn distance(self, rhs: Self) -> f32 {
         (self - rhs).length()
     }
 
     /// Compute the squared euclidean distance between two points in space.
     #[inline]
+    #[must_use]
     pub fn distance_squared(self, rhs: Self) -> f32 {
         (self - rhs).length_squared()
     }
 
+    /// Returns the element-wise quotient of [Euclidean division] of `self` by `rhs`.
+    #[inline]
+    #[must_use]
+    pub fn div_euclid(self, rhs: Self) -> Self {
+        Self::new(
+            math::div_euclid(self.x, rhs.x),
+            math::div_euclid(self.y, rhs.y),
+            math::div_euclid(self.z, rhs.z),
+        )
+    }
+
+    /// Returns the element-wise remainder of [Euclidean division] of `self` by `rhs`.
+    ///
+    /// [Euclidean division]: f32::rem_euclid
+    #[inline]
+    #[must_use]
+    pub fn rem_euclid(self, rhs: Self) -> Self {
+        Self::new(
+            math::rem_euclid(self.x, rhs.x),
+            math::rem_euclid(self.y, rhs.y),
+            math::rem_euclid(self.z, rhs.z),
+        )
+    }
+
     /// Returns `self` normalized to length 1.0.
     ///
     /// For valid results, `self` must _not_ be of length zero, nor very close to zero.
     ///
-    /// See also [`Self::try_normalize`] and [`Self::normalize_or_zero`].
+    /// See also [`Self::try_normalize()`] and [`Self::normalize_or_zero()`].
     ///
     /// Panics
     ///
     /// Will panic if `self` is zero length when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn normalize(self) -> Self {
         let length = dot3_into_f32x4(self.0, self.0).sqrt();
         #[allow(clippy::let_and_return)]
@@ -392,9 +463,9 @@
     /// In particular, if the input is zero (or very close to zero), or non-finite,
     /// the result of this operation will be `None`.
     ///
-    /// See also [`Self::normalize_or_zero`].
-    #[must_use]
+    /// See also [`Self::normalize_or_zero()`].
     #[inline]
+    #[must_use]
     pub fn try_normalize(self) -> Option<Self> {
         let rcp = self.length_recip();
         if rcp.is_finite() && rcp > 0.0 {
@@ -409,9 +480,9 @@
     /// In particular, if the input is zero (or very close to zero), or non-finite,
     /// the result of this operation will be zero.
     ///
-    /// See also [`Self::try_normalize`].
-    #[must_use]
+    /// See also [`Self::try_normalize()`].
     #[inline]
+    #[must_use]
     pub fn normalize_or_zero(self) -> Self {
         let rcp = self.length_recip();
         if rcp.is_finite() && rcp > 0.0 {
@@ -425,9 +496,10 @@
     ///
     /// Uses a precision threshold of `1e-6`.
     #[inline]
+    #[must_use]
     pub fn is_normalized(self) -> bool {
         // TODO: do something with epsilon
-        (self.length_squared() - 1.0).abs() <= 1e-4
+        math::abs(self.length_squared() - 1.0) <= 1e-4
     }
 
     /// Returns the vector projection of `self` onto `rhs`.
@@ -437,8 +509,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` is zero length when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn project_onto(self, rhs: Self) -> Self {
         let other_len_sq_rcp = rhs.dot(rhs).recip();
         glam_assert!(other_len_sq_rcp.is_finite());
@@ -455,8 +527,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` has a length of zero when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn reject_from(self, rhs: Self) -> Self {
         self - self.project_onto(rhs)
     }
@@ -468,8 +540,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` is not normalized when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn project_onto_normalized(self, rhs: Self) -> Self {
         glam_assert!(rhs.is_normalized());
         rhs * self.dot(rhs)
@@ -485,8 +557,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` is not normalized when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn reject_from_normalized(self, rhs: Self) -> Self {
         self - self.project_onto_normalized(rhs)
     }
@@ -494,6 +566,7 @@
     /// Returns a vector containing the nearest integer to a number for each element of `self`.
     /// Round half-way cases away from 0.0.
     #[inline]
+    #[must_use]
     pub fn round(self) -> Self {
         Self(self.0.round())
     }
@@ -501,6 +574,7 @@
     /// Returns a vector containing the largest integer less than or equal to a number for each
     /// element of `self`.
     #[inline]
+    #[must_use]
     pub fn floor(self) -> Self {
         Self(self.0.floor())
     }
@@ -508,15 +582,25 @@
     /// Returns a vector containing the smallest integer greater than or equal to a number for
     /// each element of `self`.
     #[inline]
+    #[must_use]
     pub fn ceil(self) -> Self {
         Self(self.0.ceil())
     }
 
+    /// Returns a vector containing the integer part each element of `self`. This means numbers are
+    /// always truncated towards zero.
+    #[inline]
+    #[must_use]
+    pub fn trunc(self) -> Self {
+        Self(self.0.trunc())
+    }
+
     /// Returns a vector containing the fractional part of the vector, e.g. `self -
     /// self.floor()`.
     ///
     /// Note that this is fast but not precise for large numbers.
     #[inline]
+    #[must_use]
     pub fn fract(self) -> Self {
         self - self.floor()
     }
@@ -524,18 +608,25 @@
     /// Returns a vector containing `e^self` (the exponential function) for each element of
     /// `self`.
     #[inline]
+    #[must_use]
     pub fn exp(self) -> Self {
-        Self::new(self.x.exp(), self.y.exp(), self.z.exp())
+        Self::new(math::exp(self.x), math::exp(self.y), math::exp(self.z))
     }
 
     /// Returns a vector containing each element of `self` raised to the power of `n`.
     #[inline]
+    #[must_use]
     pub fn powf(self, n: f32) -> Self {
-        Self::new(self.x.powf(n), self.y.powf(n), self.z.powf(n))
+        Self::new(
+            math::powf(self.x, n),
+            math::powf(self.y, n),
+            math::powf(self.z, n),
+        )
     }
 
     /// Returns a vector containing the reciprocal `1.0/n` of each element of `self`.
     #[inline]
+    #[must_use]
     pub fn recip(self) -> Self {
         Self(self.0.recip())
     }
@@ -547,6 +638,7 @@
     /// extrapolated.
     #[doc(alias = "mix")]
     #[inline]
+    #[must_use]
     pub fn lerp(self, rhs: Self, s: f32) -> Self {
         self + ((rhs - self) * s)
     }
@@ -561,6 +653,7 @@
     /// For more see
     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
     #[inline]
+    #[must_use]
     pub fn abs_diff_eq(self, rhs: Self, max_abs_diff: f32) -> bool {
         self.sub(rhs).abs().cmple(Self::splat(max_abs_diff)).all()
     }
@@ -571,33 +664,38 @@
     ///
     /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn clamp_length(self, min: f32, max: f32) -> Self {
         glam_assert!(min <= max);
         let length_sq = self.length_squared();
         if length_sq < min * min {
-            self * (length_sq.sqrt().recip() * min)
+            min * (self / math::sqrt(length_sq))
         } else if length_sq > max * max {
-            self * (length_sq.sqrt().recip() * max)
+            max * (self / math::sqrt(length_sq))
         } else {
             self
         }
     }
 
     /// Returns a vector with a length no more than `max`
+    #[inline]
+    #[must_use]
     pub fn clamp_length_max(self, max: f32) -> Self {
         let length_sq = self.length_squared();
         if length_sq > max * max {
-            self * (length_sq.sqrt().recip() * max)
+            max * (self / math::sqrt(length_sq))
         } else {
             self
         }
     }
 
     /// Returns a vector with a length no less than `min`
+    #[inline]
+    #[must_use]
     pub fn clamp_length_min(self, min: f32) -> Self {
         let length_sq = self.length_squared();
         if length_sq < min * min {
-            self * (length_sq.sqrt().recip() * min)
+            min * (self / math::sqrt(length_sq))
         } else {
             self
         }
@@ -611,70 +709,70 @@
     /// and will be heavily dependant on designing algorithms with specific target hardware in
     /// mind.
     #[inline]
+    #[must_use]
     pub fn mul_add(self, a: Self, b: Self) -> Self {
         Self(self.0.mul_add(a.0, b.0))
     }
 
     /// Returns the angle (in radians) between two vectors.
     ///
-    /// The input vectors do not need to be unit length however they must be non-zero.
+    /// The inputs do not need to be unit vectors however they must be non-zero.
     #[inline]
+    #[must_use]
     pub fn angle_between(self, rhs: Self) -> f32 {
-        use crate::FloatEx;
-        self.dot(rhs)
-            .div(self.length_squared().mul(rhs.length_squared()).sqrt())
-            .acos_approx()
+        math::acos_approx(
+            self.dot(rhs)
+                .div(math::sqrt(self.length_squared().mul(rhs.length_squared()))),
+        )
     }
 
     /// Returns some vector that is orthogonal to the given one.
     ///
     /// The input vector must be finite and non-zero.
     ///
-    /// The output vector is not necessarily unit-length.
-    /// For that use [`Self::any_orthonormal_vector`] instead.
+    /// The output vector is not necessarily unit length. For that use
+    /// [`Self::any_orthonormal_vector()`] instead.
     #[inline]
+    #[must_use]
     pub fn any_orthogonal_vector(&self) -> Self {
         // This can probably be optimized
-        if self.x.abs() > self.y.abs() {
+        if math::abs(self.x) > math::abs(self.y) {
             Self::new(-self.z, 0.0, self.x) // self.cross(Self::Y)
         } else {
             Self::new(0.0, self.z, -self.y) // self.cross(Self::X)
         }
     }
 
-    /// Returns any unit-length vector that is orthogonal to the given one.
-    /// The input vector must be finite and non-zero.
+    /// Returns any unit vector that is orthogonal to the given one.
+    ///
+    /// The input vector must be unit length.
     ///
     /// # Panics
     ///
     /// Will panic if `self` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn any_orthonormal_vector(&self) -> Self {
         glam_assert!(self.is_normalized());
         // From https://graphics.pixar.com/library/OrthonormalB/paper.pdf
-        #[cfg(feature = "std")]
-        let sign = (1.0_f32).copysign(self.z);
-        #[cfg(not(feature = "std"))]
-        let sign = self.z.signum();
+        let sign = math::signum(self.z);
         let a = -1.0 / (sign + self.z);
         let b = self.x * self.y * a;
         Self::new(b, sign + self.y * self.y * a, -self.y)
     }
 
-    /// Given a unit-length vector return two other vectors that together form an orthonormal
-    /// basis.  That is, all three vectors are orthogonal to each other and are normalized.
+    /// Given a unit vector return two other vectors that together form an orthonormal
+    /// basis. That is, all three vectors are orthogonal to each other and are normalized.
     ///
     /// # Panics
     ///
     /// Will panic if `self` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn any_orthonormal_pair(&self) -> (Self, Self) {
         glam_assert!(self.is_normalized());
         // From https://graphics.pixar.com/library/OrthonormalB/paper.pdf
-        #[cfg(feature = "std")]
-        let sign = (1.0_f32).copysign(self.z);
-        #[cfg(not(feature = "std"))]
-        let sign = self.z.signum();
+        let sign = math::signum(self.z);
         let a = -1.0 / (sign + self.z);
         let b = self.x * self.y * a;
         (
@@ -685,21 +783,52 @@
 
     /// Casts all elements of `self` to `f64`.
     #[inline]
+    #[must_use]
     pub fn as_dvec3(&self) -> crate::DVec3 {
         crate::DVec3::new(self.x as f64, self.y as f64, self.z as f64)
     }
 
+    /// Casts all elements of `self` to `i16`.
+    #[inline]
+    #[must_use]
+    pub fn as_i16vec3(&self) -> crate::I16Vec3 {
+        crate::I16Vec3::new(self.x as i16, self.y as i16, self.z as i16)
+    }
+
+    /// Casts all elements of `self` to `u16`.
+    #[inline]
+    #[must_use]
+    pub fn as_u16vec3(&self) -> crate::U16Vec3 {
+        crate::U16Vec3::new(self.x as u16, self.y as u16, self.z as u16)
+    }
+
     /// Casts all elements of `self` to `i32`.
     #[inline]
+    #[must_use]
     pub fn as_ivec3(&self) -> crate::IVec3 {
         crate::IVec3::new(self.x as i32, self.y as i32, self.z as i32)
     }
 
     /// Casts all elements of `self` to `u32`.
     #[inline]
+    #[must_use]
     pub fn as_uvec3(&self) -> crate::UVec3 {
         crate::UVec3::new(self.x as u32, self.y as u32, self.z as u32)
     }
+
+    /// Casts all elements of `self` to `i64`.
+    #[inline]
+    #[must_use]
+    pub fn as_i64vec3(&self) -> crate::I64Vec3 {
+        crate::I64Vec3::new(self.x as i64, self.y as i64, self.z as i64)
+    }
+
+    /// Casts all elements of `self` to `u64`.
+    #[inline]
+    #[must_use]
+    pub fn as_u64vec3(&self) -> crate::U64Vec3 {
+        crate::U64Vec3::new(self.x as u64, self.y as u64, self.z as u64)
+    }
 }
 
 impl Default for Vec3A {
@@ -1053,7 +1182,7 @@
 }
 
 impl From<Vec4> for Vec3A {
-    /// Creates a `Vec3A` from the `x`, `y` and `z` elements of `self` discarding `w`.
+    /// Creates a [`Vec3A`] from the `x`, `y` and `z` elements of `self` discarding `w`.
     ///
     /// On architectures where SIMD is supported such as SSE2 on `x86_64` this conversion is a noop.
     #[inline]
diff --git a/src/f32/coresimd/vec4.rs b/src/f32/coresimd/vec4.rs
index bc26d66..81b4e7e 100644
--- a/src/f32/coresimd/vec4.rs
+++ b/src/f32/coresimd/vec4.rs
@@ -1,28 +1,27 @@
 // Generated from vec.rs.tera template. Edit the template, not the generated file.
 
-use crate::{coresimd::*, BVec4A, Vec2, Vec3, Vec3A};
+use crate::{coresimd::*, f32::math, BVec4A, Vec2, Vec3, Vec3A};
 
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
 use core::iter::{Product, Sum};
 use core::{f32, ops::*};
 
-use core::simd::*;
+use core::simd::{cmp::SimdPartialEq, cmp::SimdPartialOrd, num::SimdFloat, *};
 use std::simd::StdFloat;
 
-#[cfg(feature = "libm")]
-#[allow(unused_imports)]
-use num_traits::Float;
-
 /// Creates a 4-dimensional vector.
 #[inline(always)]
+#[must_use]
 pub const fn vec4(x: f32, y: f32, z: f32, w: f32) -> Vec4 {
     Vec4::new(x, y, z, w)
 }
 
-/// A 4-dimensional vector with SIMD support.
+/// A 4-dimensional vector.
 ///
-/// This type uses 16 byte aligned SIMD vector type for storage.
+/// SIMD vector types are used for storage on supported platforms.
+///
+/// This type is 16 byte aligned.
 #[derive(Clone, Copy)]
 #[repr(transparent)]
 pub struct Vec4(pub(crate) f32x4);
@@ -37,31 +36,43 @@
     /// All negative ones.
     pub const NEG_ONE: Self = Self::splat(-1.0);
 
-    /// All NAN.
+    /// All `f32::MIN`.
+    pub const MIN: Self = Self::splat(f32::MIN);
+
+    /// All `f32::MAX`.
+    pub const MAX: Self = Self::splat(f32::MAX);
+
+    /// All `f32::NAN`.
     pub const NAN: Self = Self::splat(f32::NAN);
 
-    /// A unit-length vector pointing along the positive X axis.
+    /// All `f32::INFINITY`.
+    pub const INFINITY: Self = Self::splat(f32::INFINITY);
+
+    /// All `f32::NEG_INFINITY`.
+    pub const NEG_INFINITY: Self = Self::splat(f32::NEG_INFINITY);
+
+    /// A unit vector pointing along the positive X axis.
     pub const X: Self = Self::new(1.0, 0.0, 0.0, 0.0);
 
-    /// A unit-length vector pointing along the positive Y axis.
+    /// A unit vector pointing along the positive Y axis.
     pub const Y: Self = Self::new(0.0, 1.0, 0.0, 0.0);
 
-    /// A unit-length vector pointing along the positive Z axis.
+    /// A unit vector pointing along the positive Z axis.
     pub const Z: Self = Self::new(0.0, 0.0, 1.0, 0.0);
 
-    /// A unit-length vector pointing along the positive W axis.
+    /// A unit vector pointing along the positive W axis.
     pub const W: Self = Self::new(0.0, 0.0, 0.0, 1.0);
 
-    /// A unit-length vector pointing along the negative X axis.
+    /// A unit vector pointing along the negative X axis.
     pub const NEG_X: Self = Self::new(-1.0, 0.0, 0.0, 0.0);
 
-    /// A unit-length vector pointing along the negative Y axis.
+    /// A unit vector pointing along the negative Y axis.
     pub const NEG_Y: Self = Self::new(0.0, -1.0, 0.0, 0.0);
 
-    /// A unit-length vector pointing along the negative Z axis.
+    /// A unit vector pointing along the negative Z axis.
     pub const NEG_Z: Self = Self::new(0.0, 0.0, -1.0, 0.0);
 
-    /// A unit-length vector pointing along the negative W axis.
+    /// A unit vector pointing along the negative W axis.
     pub const NEG_W: Self = Self::new(0.0, 0.0, 0.0, -1.0);
 
     /// The unit axes.
@@ -69,12 +80,14 @@
 
     /// Creates a new vector.
     #[inline(always)]
+    #[must_use]
     pub const fn new(x: f32, y: f32, z: f32, w: f32) -> Self {
         Self(f32x4::from_array([x, y, z, w]))
     }
 
     /// Creates a vector with all elements set to `v`.
     #[inline]
+    #[must_use]
     pub const fn splat(v: f32) -> Self {
         Self(Simd::from_array([v; 4]))
     }
@@ -85,18 +98,21 @@
     /// A true element in the mask uses the corresponding element from `if_true`, and false
     /// uses the element from `if_false`.
     #[inline]
+    #[must_use]
     pub fn select(mask: BVec4A, if_true: Self, if_false: Self) -> Self {
         Self(mask.0.select(if_true.0, if_false.0))
     }
 
     /// Creates a new vector from an array.
     #[inline]
+    #[must_use]
     pub const fn from_array(a: [f32; 4]) -> Self {
         Self::new(a[0], a[1], a[2], a[3])
     }
 
     /// `[x, y, z, w]`
     #[inline]
+    #[must_use]
     pub const fn to_array(&self) -> [f32; 4] {
         unsafe { *(self as *const Vec4 as *const [f32; 4]) }
     }
@@ -107,6 +123,7 @@
     ///
     /// Panics if `slice` is less than 4 elements long.
     #[inline]
+    #[must_use]
     pub const fn from_slice(slice: &[f32]) -> Self {
         Self::new(slice[0], slice[1], slice[2], slice[3])
     }
@@ -124,12 +141,13 @@
         slice[3] = self.w;
     }
 
-    /// Creates a 2D vector from the `x`, `y` and `z` elements of `self`, discarding `w`.
+    /// Creates a 3D vector from the `x`, `y` and `z` elements of `self`, discarding `w`.
     ///
-    /// Truncation to `Vec3` may also be performed by using `self.xyz()` or `Vec3::from()`.
+    /// Truncation to [`Vec3`] may also be performed by using [`self.xyz()`][crate::swizzles::Vec4Swizzles::xyz()].
     ///
-    /// To truncate to `Vec3A` use `Vec3A::from()`.
+    /// To truncate to [`Vec3A`] use [`Vec3A::from()`].
     #[inline]
+    #[must_use]
     pub fn truncate(self) -> Vec3 {
         use crate::swizzles::Vec4Swizzles;
         self.xyz()
@@ -137,20 +155,23 @@
 
     /// Computes the dot product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn dot(self, rhs: Self) -> f32 {
         dot4(self.0, rhs.0)
     }
 
     /// Returns a vector where every component is the dot product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn dot_into_vec(self, rhs: Self) -> Self {
-        Self(unsafe { dot4_into_f32x4(self.0, rhs.0) })
+        Self(dot4_into_f32x4(self.0, rhs.0))
     }
 
     /// Returns a vector containing the minimum values for each element of `self` and `rhs`.
     ///
     /// In other words this computes `[self.x.min(rhs.x), self.y.min(rhs.y), ..]`.
     #[inline]
+    #[must_use]
     pub fn min(self, rhs: Self) -> Self {
         Self(self.0.simd_min(rhs.0))
     }
@@ -159,6 +180,7 @@
     ///
     /// In other words this computes `[self.x.max(rhs.x), self.y.max(rhs.y), ..]`.
     #[inline]
+    #[must_use]
     pub fn max(self, rhs: Self) -> Self {
         Self(self.0.simd_max(rhs.0))
     }
@@ -171,6 +193,7 @@
     ///
     /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn clamp(self, min: Self, max: Self) -> Self {
         glam_assert!(min.cmple(max).all(), "clamp: expected min <= max");
         self.max(min).min(max)
@@ -180,6 +203,7 @@
     ///
     /// In other words this computes `min(x, y, ..)`.
     #[inline]
+    #[must_use]
     pub fn min_element(self) -> f32 {
         self.0.reduce_min()
     }
@@ -188,6 +212,7 @@
     ///
     /// In other words this computes `max(x, y, ..)`.
     #[inline]
+    #[must_use]
     pub fn max_element(self) -> f32 {
         self.0.reduce_max()
     }
@@ -198,6 +223,7 @@
     /// In other words, this computes `[self.x == rhs.x, self.y == rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpeq(self, rhs: Self) -> BVec4A {
         BVec4A(f32x4::simd_eq(self.0, rhs.0))
     }
@@ -208,6 +234,7 @@
     /// In other words this computes `[self.x != rhs.x, self.y != rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpne(self, rhs: Self) -> BVec4A {
         BVec4A(f32x4::simd_ne(self.0, rhs.0))
     }
@@ -218,6 +245,7 @@
     /// In other words this computes `[self.x >= rhs.x, self.y >= rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpge(self, rhs: Self) -> BVec4A {
         BVec4A(f32x4::simd_ge(self.0, rhs.0))
     }
@@ -228,6 +256,7 @@
     /// In other words this computes `[self.x > rhs.x, self.y > rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpgt(self, rhs: Self) -> BVec4A {
         BVec4A(f32x4::simd_gt(self.0, rhs.0))
     }
@@ -238,6 +267,7 @@
     /// In other words this computes `[self.x <= rhs.x, self.y <= rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmple(self, rhs: Self) -> BVec4A {
         BVec4A(f32x4::simd_le(self.0, rhs.0))
     }
@@ -248,12 +278,14 @@
     /// In other words this computes `[self.x < rhs.x, self.y < rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmplt(self, rhs: Self) -> BVec4A {
         BVec4A(f32x4::simd_lt(self.0, rhs.0))
     }
 
     /// Returns a vector containing the absolute value of each element of `self`.
     #[inline]
+    #[must_use]
     pub fn abs(self) -> Self {
         Self(self.0.abs())
     }
@@ -264,12 +296,14 @@
     /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
     /// - `NAN` if the number is `NAN`
     #[inline]
+    #[must_use]
     pub fn signum(self) -> Self {
         Self(self.0.signum())
     }
 
     /// Returns a vector with signs of `rhs` and the magnitudes of `self`.
     #[inline]
+    #[must_use]
     pub fn copysign(self, rhs: Self) -> Self {
         Self(self.0.copysign(rhs.0))
     }
@@ -279,6 +313,7 @@
     /// A negative element results in a `1` bit and a positive element in a `0` bit.  Element `x` goes
     /// into the first lowest bit, element `y` into the second, etc.
     #[inline]
+    #[must_use]
     pub fn is_negative_bitmask(self) -> u32 {
         self.0.is_sign_negative().to_bitmask() as u32
     }
@@ -286,12 +321,14 @@
     /// Returns `true` if, and only if, all elements are finite.  If any element is either
     /// `NaN`, positive or negative infinity, this will return `false`.
     #[inline]
+    #[must_use]
     pub fn is_finite(self) -> bool {
         f32x4::is_finite(self.0).all()
     }
 
     /// Returns `true` if any elements are `NaN`.
     #[inline]
+    #[must_use]
     pub fn is_nan(self) -> bool {
         self.is_nan_mask().any()
     }
@@ -300,6 +337,7 @@
     ///
     /// In other words, this computes `[x.is_nan(), y.is_nan(), z.is_nan(), w.is_nan()]`.
     #[inline]
+    #[must_use]
     pub fn is_nan_mask(self) -> BVec4A {
         BVec4A(f32x4::is_nan(self.0))
     }
@@ -307,6 +345,7 @@
     /// Computes the length of `self`.
     #[doc(alias = "magnitude")]
     #[inline]
+    #[must_use]
     pub fn length(self) -> f32 {
         let dot = dot4_in_x(self.0, self.0);
         dot.sqrt()[0]
@@ -317,6 +356,7 @@
     /// This is faster than `length()` as it avoids a square root operation.
     #[doc(alias = "magnitude2")]
     #[inline]
+    #[must_use]
     pub fn length_squared(self) -> f32 {
         self.dot(self)
     }
@@ -325,6 +365,7 @@
     ///
     /// For valid results, `self` must _not_ be of length zero.
     #[inline]
+    #[must_use]
     pub fn length_recip(self) -> f32 {
         let dot = dot4_in_x(self.0, self.0);
         dot.sqrt().recip()[0]
@@ -332,27 +373,55 @@
 
     /// Computes the Euclidean distance between two points in space.
     #[inline]
+    #[must_use]
     pub fn distance(self, rhs: Self) -> f32 {
         (self - rhs).length()
     }
 
     /// Compute the squared euclidean distance between two points in space.
     #[inline]
+    #[must_use]
     pub fn distance_squared(self, rhs: Self) -> f32 {
         (self - rhs).length_squared()
     }
 
+    /// Returns the element-wise quotient of [Euclidean division] of `self` by `rhs`.
+    #[inline]
+    #[must_use]
+    pub fn div_euclid(self, rhs: Self) -> Self {
+        Self::new(
+            math::div_euclid(self.x, rhs.x),
+            math::div_euclid(self.y, rhs.y),
+            math::div_euclid(self.z, rhs.z),
+            math::div_euclid(self.w, rhs.w),
+        )
+    }
+
+    /// Returns the element-wise remainder of [Euclidean division] of `self` by `rhs`.
+    ///
+    /// [Euclidean division]: f32::rem_euclid
+    #[inline]
+    #[must_use]
+    pub fn rem_euclid(self, rhs: Self) -> Self {
+        Self::new(
+            math::rem_euclid(self.x, rhs.x),
+            math::rem_euclid(self.y, rhs.y),
+            math::rem_euclid(self.z, rhs.z),
+            math::rem_euclid(self.w, rhs.w),
+        )
+    }
+
     /// Returns `self` normalized to length 1.0.
     ///
     /// For valid results, `self` must _not_ be of length zero, nor very close to zero.
     ///
-    /// See also [`Self::try_normalize`] and [`Self::normalize_or_zero`].
+    /// See also [`Self::try_normalize()`] and [`Self::normalize_or_zero()`].
     ///
     /// Panics
     ///
     /// Will panic if `self` is zero length when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn normalize(self) -> Self {
         let length = dot4_into_f32x4(self.0, self.0).sqrt();
         #[allow(clippy::let_and_return)]
@@ -366,9 +435,9 @@
     /// In particular, if the input is zero (or very close to zero), or non-finite,
     /// the result of this operation will be `None`.
     ///
-    /// See also [`Self::normalize_or_zero`].
-    #[must_use]
+    /// See also [`Self::normalize_or_zero()`].
     #[inline]
+    #[must_use]
     pub fn try_normalize(self) -> Option<Self> {
         let rcp = self.length_recip();
         if rcp.is_finite() && rcp > 0.0 {
@@ -383,9 +452,9 @@
     /// In particular, if the input is zero (or very close to zero), or non-finite,
     /// the result of this operation will be zero.
     ///
-    /// See also [`Self::try_normalize`].
-    #[must_use]
+    /// See also [`Self::try_normalize()`].
     #[inline]
+    #[must_use]
     pub fn normalize_or_zero(self) -> Self {
         let rcp = self.length_recip();
         if rcp.is_finite() && rcp > 0.0 {
@@ -399,9 +468,10 @@
     ///
     /// Uses a precision threshold of `1e-6`.
     #[inline]
+    #[must_use]
     pub fn is_normalized(self) -> bool {
         // TODO: do something with epsilon
-        (self.length_squared() - 1.0).abs() <= 1e-4
+        math::abs(self.length_squared() - 1.0) <= 1e-4
     }
 
     /// Returns the vector projection of `self` onto `rhs`.
@@ -411,8 +481,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` is zero length when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn project_onto(self, rhs: Self) -> Self {
         let other_len_sq_rcp = rhs.dot(rhs).recip();
         glam_assert!(other_len_sq_rcp.is_finite());
@@ -429,8 +499,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` has a length of zero when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn reject_from(self, rhs: Self) -> Self {
         self - self.project_onto(rhs)
     }
@@ -442,8 +512,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` is not normalized when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn project_onto_normalized(self, rhs: Self) -> Self {
         glam_assert!(rhs.is_normalized());
         rhs * self.dot(rhs)
@@ -459,8 +529,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` is not normalized when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn reject_from_normalized(self, rhs: Self) -> Self {
         self - self.project_onto_normalized(rhs)
     }
@@ -468,6 +538,7 @@
     /// Returns a vector containing the nearest integer to a number for each element of `self`.
     /// Round half-way cases away from 0.0.
     #[inline]
+    #[must_use]
     pub fn round(self) -> Self {
         Self(self.0.round())
     }
@@ -475,6 +546,7 @@
     /// Returns a vector containing the largest integer less than or equal to a number for each
     /// element of `self`.
     #[inline]
+    #[must_use]
     pub fn floor(self) -> Self {
         Self(self.0.floor())
     }
@@ -482,15 +554,25 @@
     /// Returns a vector containing the smallest integer greater than or equal to a number for
     /// each element of `self`.
     #[inline]
+    #[must_use]
     pub fn ceil(self) -> Self {
         Self(self.0.ceil())
     }
 
+    /// Returns a vector containing the integer part each element of `self`. This means numbers are
+    /// always truncated towards zero.
+    #[inline]
+    #[must_use]
+    pub fn trunc(self) -> Self {
+        Self(self.0.trunc())
+    }
+
     /// Returns a vector containing the fractional part of the vector, e.g. `self -
     /// self.floor()`.
     ///
     /// Note that this is fast but not precise for large numbers.
     #[inline]
+    #[must_use]
     pub fn fract(self) -> Self {
         self - self.floor()
     }
@@ -498,23 +580,31 @@
     /// Returns a vector containing `e^self` (the exponential function) for each element of
     /// `self`.
     #[inline]
+    #[must_use]
     pub fn exp(self) -> Self {
-        Self::new(self.x.exp(), self.y.exp(), self.z.exp(), self.w.exp())
+        Self::new(
+            math::exp(self.x),
+            math::exp(self.y),
+            math::exp(self.z),
+            math::exp(self.w),
+        )
     }
 
     /// Returns a vector containing each element of `self` raised to the power of `n`.
     #[inline]
+    #[must_use]
     pub fn powf(self, n: f32) -> Self {
         Self::new(
-            self.x.powf(n),
-            self.y.powf(n),
-            self.z.powf(n),
-            self.w.powf(n),
+            math::powf(self.x, n),
+            math::powf(self.y, n),
+            math::powf(self.z, n),
+            math::powf(self.w, n),
         )
     }
 
     /// Returns a vector containing the reciprocal `1.0/n` of each element of `self`.
     #[inline]
+    #[must_use]
     pub fn recip(self) -> Self {
         Self(self.0.recip())
     }
@@ -526,6 +616,7 @@
     /// extrapolated.
     #[doc(alias = "mix")]
     #[inline]
+    #[must_use]
     pub fn lerp(self, rhs: Self, s: f32) -> Self {
         self + ((rhs - self) * s)
     }
@@ -540,6 +631,7 @@
     /// For more see
     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
     #[inline]
+    #[must_use]
     pub fn abs_diff_eq(self, rhs: Self, max_abs_diff: f32) -> bool {
         self.sub(rhs).abs().cmple(Self::splat(max_abs_diff)).all()
     }
@@ -550,33 +642,38 @@
     ///
     /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn clamp_length(self, min: f32, max: f32) -> Self {
         glam_assert!(min <= max);
         let length_sq = self.length_squared();
         if length_sq < min * min {
-            self * (length_sq.sqrt().recip() * min)
+            min * (self / math::sqrt(length_sq))
         } else if length_sq > max * max {
-            self * (length_sq.sqrt().recip() * max)
+            max * (self / math::sqrt(length_sq))
         } else {
             self
         }
     }
 
     /// Returns a vector with a length no more than `max`
+    #[inline]
+    #[must_use]
     pub fn clamp_length_max(self, max: f32) -> Self {
         let length_sq = self.length_squared();
         if length_sq > max * max {
-            self * (length_sq.sqrt().recip() * max)
+            max * (self / math::sqrt(length_sq))
         } else {
             self
         }
     }
 
     /// Returns a vector with a length no less than `min`
+    #[inline]
+    #[must_use]
     pub fn clamp_length_min(self, min: f32) -> Self {
         let length_sq = self.length_squared();
         if length_sq < min * min {
-            self * (length_sq.sqrt().recip() * min)
+            min * (self / math::sqrt(length_sq))
         } else {
             self
         }
@@ -590,27 +687,59 @@
     /// and will be heavily dependant on designing algorithms with specific target hardware in
     /// mind.
     #[inline]
+    #[must_use]
     pub fn mul_add(self, a: Self, b: Self) -> Self {
         Self(self.0.mul_add(a.0, b.0))
     }
 
     /// Casts all elements of `self` to `f64`.
     #[inline]
+    #[must_use]
     pub fn as_dvec4(&self) -> crate::DVec4 {
         crate::DVec4::new(self.x as f64, self.y as f64, self.z as f64, self.w as f64)
     }
 
+    /// Casts all elements of `self` to `i16`.
+    #[inline]
+    #[must_use]
+    pub fn as_i16vec4(&self) -> crate::I16Vec4 {
+        crate::I16Vec4::new(self.x as i16, self.y as i16, self.z as i16, self.w as i16)
+    }
+
+    /// Casts all elements of `self` to `u16`.
+    #[inline]
+    #[must_use]
+    pub fn as_u16vec4(&self) -> crate::U16Vec4 {
+        crate::U16Vec4::new(self.x as u16, self.y as u16, self.z as u16, self.w as u16)
+    }
+
     /// Casts all elements of `self` to `i32`.
     #[inline]
+    #[must_use]
     pub fn as_ivec4(&self) -> crate::IVec4 {
         crate::IVec4::new(self.x as i32, self.y as i32, self.z as i32, self.w as i32)
     }
 
     /// Casts all elements of `self` to `u32`.
     #[inline]
+    #[must_use]
     pub fn as_uvec4(&self) -> crate::UVec4 {
         crate::UVec4::new(self.x as u32, self.y as u32, self.z as u32, self.w as u32)
     }
+
+    /// Casts all elements of `self` to `i64`.
+    #[inline]
+    #[must_use]
+    pub fn as_i64vec4(&self) -> crate::I64Vec4 {
+        crate::I64Vec4::new(self.x as i64, self.y as i64, self.z as i64, self.w as i64)
+    }
+
+    /// Casts all elements of `self` to `u64`.
+    #[inline]
+    #[must_use]
+    pub fn as_u64vec4(&self) -> crate::U64Vec4 {
+        crate::U64Vec4::new(self.x as u64, self.y as u64, self.z as u64, self.w as u64)
+    }
 }
 
 impl Default for Vec4 {
diff --git a/src/f32/float.rs b/src/f32/float.rs
new file mode 100644
index 0000000..290552c
--- /dev/null
+++ b/src/f32/float.rs
@@ -0,0 +1,21 @@
+// Generated from float.rs.tera template. Edit the template, not the generated file.
+
+use crate::float::FloatExt;
+
+impl FloatExt for f32 {
+    #[inline]
+    fn lerp(self, rhs: f32, t: f32) -> f32 {
+        self + (rhs - self) * t
+    }
+
+    #[inline]
+    fn inverse_lerp(a: f32, b: f32, v: f32) -> f32 {
+        (v - a) / (b - a)
+    }
+
+    #[inline]
+    fn remap(self, in_start: f32, in_end: f32, out_start: f32, out_end: f32) -> f32 {
+        let t = f32::inverse_lerp(in_start, in_end, self);
+        f32::lerp(out_start, out_end, t)
+    }
+}
diff --git a/src/f32/mat3.rs b/src/f32/mat3.rs
index 6c2ed4d..20b3c53 100644
--- a/src/f32/mat3.rs
+++ b/src/f32/mat3.rs
@@ -1,17 +1,14 @@
 // Generated from mat.rs.tera template. Edit the template, not the generated file.
 
-use crate::{swizzles::*, DMat3, EulerRot, Mat2, Mat3A, Mat4, Quat, Vec2, Vec3, Vec3A};
+use crate::{f32::math, swizzles::*, DMat3, EulerRot, Mat2, Mat3A, Mat4, Quat, Vec2, Vec3, Vec3A};
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
 use core::iter::{Product, Sum};
 use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
 
-#[cfg(feature = "libm")]
-#[allow(unused_imports)]
-use num_traits::Float;
-
-/// Creates a 3x3 matrix from column vectors.
+/// Creates a 3x3 matrix from three column vectors.
 #[inline(always)]
+#[must_use]
 pub const fn mat3(x_axis: Vec3, y_axis: Vec3, z_axis: Vec3) -> Mat3 {
     Mat3::from_cols(x_axis, y_axis, z_axis)
 }
@@ -60,6 +57,7 @@
 
     #[allow(clippy::too_many_arguments)]
     #[inline(always)]
+    #[must_use]
     const fn new(
         m00: f32,
         m01: f32,
@@ -78,8 +76,9 @@
         }
     }
 
-    /// Creates a 3x3 matrix from two column vectors.
+    /// Creates a 3x3 matrix from three column vectors.
     #[inline(always)]
+    #[must_use]
     pub const fn from_cols(x_axis: Vec3, y_axis: Vec3, z_axis: Vec3) -> Self {
         Self {
             x_axis,
@@ -92,6 +91,7 @@
     /// If your data is stored in row major you will need to `transpose` the returned
     /// matrix.
     #[inline]
+    #[must_use]
     pub const fn from_cols_array(m: &[f32; 9]) -> Self {
         Self::new(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8])
     }
@@ -99,6 +99,7 @@
     /// Creates a `[f32; 9]` array storing data in column major order.
     /// If you require data in row major order `transpose` the matrix first.
     #[inline]
+    #[must_use]
     pub const fn to_cols_array(&self) -> [f32; 9] {
         [
             self.x_axis.x,
@@ -117,6 +118,7 @@
     /// If your data is in row major order you will need to `transpose` the returned
     /// matrix.
     #[inline]
+    #[must_use]
     pub const fn from_cols_array_2d(m: &[[f32; 3]; 3]) -> Self {
         Self::from_cols(
             Vec3::from_array(m[0]),
@@ -128,6 +130,7 @@
     /// Creates a `[[f32; 3]; 3]` 3D array storing data in column major order.
     /// If you require data in row major order `transpose` the matrix first.
     #[inline]
+    #[must_use]
     pub const fn to_cols_array_2d(&self) -> [[f32; 3]; 3] {
         [
             self.x_axis.to_array(),
@@ -139,6 +142,7 @@
     /// Creates a 3x3 matrix with its diagonal set to `diagonal` and all other entries set to 0.
     #[doc(alias = "scale")]
     #[inline]
+    #[must_use]
     pub const fn from_diagonal(diagonal: Vec3) -> Self {
         Self::new(
             diagonal.x, 0.0, 0.0, 0.0, diagonal.y, 0.0, 0.0, 0.0, diagonal.z,
@@ -146,6 +150,8 @@
     }
 
     /// Creates a 3x3 matrix from a 4x4 matrix, discarding the 4th row and column.
+    #[inline]
+    #[must_use]
     pub fn from_mat4(m: Mat4) -> Self {
         Self::from_cols(m.x_axis.xyz(), m.y_axis.xyz(), m.z_axis.xyz())
     }
@@ -156,6 +162,7 @@
     ///
     /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_quat(rotation: Quat) -> Self {
         glam_assert!(rotation.is_normalized());
 
@@ -186,10 +193,11 @@
     ///
     /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
         glam_assert!(axis.is_normalized());
 
-        let (sin, cos) = angle.sin_cos();
+        let (sin, cos) = math::sin_cos(angle);
         let (xsin, ysin, zsin) = axis.mul(sin).into();
         let (x, y, z) = axis.into();
         let (x2, y2, z2) = axis.mul(axis).into();
@@ -204,9 +212,10 @@
         )
     }
 
-    #[inline]
     /// Creates a 3D rotation matrix from the given euler rotation sequence and the angles (in
     /// radians).
+    #[inline]
+    #[must_use]
     pub fn from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self {
         let quat = Quat::from_euler(order, a, b, c);
         Self::from_quat(quat)
@@ -214,8 +223,9 @@
 
     /// Creates a 3D rotation matrix from `angle` (in radians) around the x axis.
     #[inline]
+    #[must_use]
     pub fn from_rotation_x(angle: f32) -> Self {
-        let (sina, cosa) = angle.sin_cos();
+        let (sina, cosa) = math::sin_cos(angle);
         Self::from_cols(
             Vec3::X,
             Vec3::new(0.0, cosa, sina),
@@ -225,8 +235,9 @@
 
     /// Creates a 3D rotation matrix from `angle` (in radians) around the y axis.
     #[inline]
+    #[must_use]
     pub fn from_rotation_y(angle: f32) -> Self {
-        let (sina, cosa) = angle.sin_cos();
+        let (sina, cosa) = math::sin_cos(angle);
         Self::from_cols(
             Vec3::new(cosa, 0.0, -sina),
             Vec3::Y,
@@ -236,8 +247,9 @@
 
     /// Creates a 3D rotation matrix from `angle` (in radians) around the z axis.
     #[inline]
+    #[must_use]
     pub fn from_rotation_z(angle: f32) -> Self {
-        let (sina, cosa) = angle.sin_cos();
+        let (sina, cosa) = math::sin_cos(angle);
         Self::from_cols(
             Vec3::new(cosa, sina, 0.0),
             Vec3::new(-sina, cosa, 0.0),
@@ -250,6 +262,7 @@
     /// The resulting matrix can be used to transform 2D points and vectors. See
     /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
     #[inline]
+    #[must_use]
     pub fn from_translation(translation: Vec2) -> Self {
         Self::from_cols(
             Vec3::X,
@@ -264,8 +277,9 @@
     /// The resulting matrix can be used to transform 2D points and vectors. See
     /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
     #[inline]
+    #[must_use]
     pub fn from_angle(angle: f32) -> Self {
-        let (sin, cos) = angle.sin_cos();
+        let (sin, cos) = math::sin_cos(angle);
         Self::from_cols(Vec3::new(cos, sin, 0.0), Vec3::new(-sin, cos, 0.0), Vec3::Z)
     }
 
@@ -275,8 +289,9 @@
     /// The resulting matrix can be used to transform 2D points and vectors. See
     /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
     #[inline]
+    #[must_use]
     pub fn from_scale_angle_translation(scale: Vec2, angle: f32, translation: Vec2) -> Self {
-        let (sin, cos) = angle.sin_cos();
+        let (sin, cos) = math::sin_cos(angle);
         Self::from_cols(
             Vec3::new(cos * scale.x, sin * scale.x, 0.0),
             Vec3::new(-sin * scale.y, cos * scale.y, 0.0),
@@ -293,6 +308,7 @@
     ///
     /// Will panic if all elements of `scale` are zero when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_scale(scale: Vec2) -> Self {
         // Do not panic as long as any component is non-zero
         glam_assert!(scale.cmpne(Vec2::ZERO).any());
@@ -319,6 +335,7 @@
     ///
     /// Panics if `slice` is less than 9 elements long.
     #[inline]
+    #[must_use]
     pub const fn from_cols_slice(slice: &[f32]) -> Self {
         Self::new(
             slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
@@ -350,6 +367,7 @@
     ///
     /// Panics if `index` is greater than 2.
     #[inline]
+    #[must_use]
     pub fn col(&self, index: usize) -> Vec3 {
         match index {
             0 => self.x_axis,
@@ -380,6 +398,7 @@
     ///
     /// Panics if `index` is greater than 2.
     #[inline]
+    #[must_use]
     pub fn row(&self, index: usize) -> Vec3 {
         match index {
             0 => Vec3::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
@@ -392,19 +411,21 @@
     /// Returns `true` if, and only if, all elements are finite.
     /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
     #[inline]
+    #[must_use]
     pub fn is_finite(&self) -> bool {
         self.x_axis.is_finite() && self.y_axis.is_finite() && self.z_axis.is_finite()
     }
 
     /// Returns `true` if any elements are `NaN`.
     #[inline]
+    #[must_use]
     pub fn is_nan(&self) -> bool {
         self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan()
     }
 
     /// Returns the transpose of `self`.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn transpose(&self) -> Self {
         Self {
             x_axis: Vec3::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
@@ -415,6 +436,7 @@
 
     /// Returns the determinant of `self`.
     #[inline]
+    #[must_use]
     pub fn determinant(&self) -> f32 {
         self.z_axis.dot(self.x_axis.cross(self.y_axis))
     }
@@ -426,8 +448,8 @@
     /// # Panics
     ///
     /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn inverse(&self) -> Self {
         let tmp0 = self.y_axis.cross(self.z_axis);
         let tmp1 = self.z_axis.cross(self.x_axis);
@@ -448,6 +470,7 @@
     ///
     /// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn transform_point2(&self, rhs: Vec2) -> Vec2 {
         glam_assert!(self.row(2).abs_diff_eq(Vec3::Z, 1e-6));
         Mat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs + self.z_axis.xy()
@@ -463,6 +486,7 @@
     ///
     /// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn transform_vector2(&self, rhs: Vec2) -> Vec2 {
         glam_assert!(self.row(2).abs_diff_eq(Vec3::Z, 1e-6));
         Mat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs
@@ -470,6 +494,7 @@
 
     /// Transforms a 3D vector.
     #[inline]
+    #[must_use]
     pub fn mul_vec3(&self, rhs: Vec3) -> Vec3 {
         let mut res = self.x_axis.mul(rhs.x);
         res = res.add(self.y_axis.mul(rhs.y));
@@ -477,14 +502,16 @@
         res
     }
 
-    /// Transforms a `Vec3A`.
+    /// Transforms a [`Vec3A`].
     #[inline]
+    #[must_use]
     pub fn mul_vec3a(&self, rhs: Vec3A) -> Vec3A {
         self.mul_vec3(rhs.into()).into()
     }
 
     /// Multiplies two 3x3 matrices.
     #[inline]
+    #[must_use]
     pub fn mul_mat3(&self, rhs: &Self) -> Self {
         Self::from_cols(
             self.mul(rhs.x_axis),
@@ -495,6 +522,7 @@
 
     /// Adds two 3x3 matrices.
     #[inline]
+    #[must_use]
     pub fn add_mat3(&self, rhs: &Self) -> Self {
         Self::from_cols(
             self.x_axis.add(rhs.x_axis),
@@ -505,6 +533,7 @@
 
     /// Subtracts two 3x3 matrices.
     #[inline]
+    #[must_use]
     pub fn sub_mat3(&self, rhs: &Self) -> Self {
         Self::from_cols(
             self.x_axis.sub(rhs.x_axis),
@@ -515,6 +544,7 @@
 
     /// Multiplies a 3x3 matrix by a scalar.
     #[inline]
+    #[must_use]
     pub fn mul_scalar(&self, rhs: f32) -> Self {
         Self::from_cols(
             self.x_axis.mul(rhs),
@@ -533,6 +563,7 @@
     /// For more see
     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
     #[inline]
+    #[must_use]
     pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
         self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
             && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
diff --git a/src/f32/math.rs b/src/f32/math.rs
new file mode 100644
index 0000000..3e25875
--- /dev/null
+++ b/src/f32/math.rs
@@ -0,0 +1,251 @@
+/// Returns a very close approximation of `self.clamp(-1.0, 1.0).acos()`.
+#[inline]
+fn acos_approx_f32(v: f32) -> f32 {
+    // Based on https://github.com/microsoft/DirectXMath `XMScalarAcos`
+    // Clamp input to [-1,1].
+    let nonnegative = v >= 0.0;
+    let x = abs(v);
+    let mut omx = 1.0 - x;
+    if omx < 0.0 {
+        omx = 0.0;
+    }
+    let root = sqrt(omx);
+
+    // 7-degree minimax approximation
+    #[allow(clippy::approx_constant)]
+    let mut result =
+        ((((((-0.001_262_491_1 * x + 0.006_670_09) * x - 0.017_088_126) * x + 0.030_891_88) * x
+            - 0.050_174_303)
+            * x
+            + 0.088_978_99)
+            * x
+            - 0.214_598_8)
+            * x
+            + 1.570_796_3;
+    result *= root;
+
+    // acos(x) = pi - acos(-x) when x < 0
+    if nonnegative {
+        result
+    } else {
+        core::f32::consts::PI - result
+    }
+}
+
+#[cfg(feature = "libm")]
+mod libm_math {
+    #[inline(always)]
+    pub(crate) fn abs(f: f32) -> f32 {
+        libm::fabsf(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn acos_approx(f: f32) -> f32 {
+        super::acos_approx_f32(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn asin(f: f32) -> f32 {
+        libm::asinf(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn atan2(f: f32, other: f32) -> f32 {
+        libm::atan2f(f, other)
+    }
+
+    #[allow(unused)]
+    #[inline(always)]
+    pub(crate) fn sin(f: f32) -> f32 {
+        libm::sinf(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn sin_cos(f: f32) -> (f32, f32) {
+        libm::sincosf(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn tan(f: f32) -> f32 {
+        libm::tanf(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn sqrt(f: f32) -> f32 {
+        libm::sqrtf(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn copysign(f: f32, sign: f32) -> f32 {
+        libm::copysignf(f, sign)
+    }
+
+    #[inline(always)]
+    pub(crate) fn signum(f: f32) -> f32 {
+        if f.is_nan() {
+            f32::NAN
+        } else {
+            copysign(1.0, f)
+        }
+    }
+
+    #[inline(always)]
+    pub(crate) fn round(f: f32) -> f32 {
+        libm::roundf(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn trunc(f: f32) -> f32 {
+        libm::truncf(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn ceil(f: f32) -> f32 {
+        libm::ceilf(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn floor(f: f32) -> f32 {
+        libm::floorf(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn exp(f: f32) -> f32 {
+        libm::expf(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn powf(f: f32, n: f32) -> f32 {
+        libm::powf(f, n)
+    }
+
+    #[inline(always)]
+    pub(crate) fn mul_add(a: f32, b: f32, c: f32) -> f32 {
+        libm::fmaf(a, b, c)
+    }
+
+    #[inline]
+    pub fn div_euclid(a: f32, b: f32) -> f32 {
+        // Based on https://doc.rust-lang.org/src/std/f32.rs.html#293
+        let q = libm::truncf(a / b);
+        if a % b < 0.0 {
+            return if b > 0.0 { q - 1.0 } else { q + 1.0 };
+        }
+        q
+    }
+
+    #[inline]
+    pub fn rem_euclid(a: f32, b: f32) -> f32 {
+        let r = a % b;
+        if r < 0.0 {
+            r + abs(b)
+        } else {
+            r
+        }
+    }
+}
+
+#[cfg(not(feature = "libm"))]
+mod std_math {
+    #[inline(always)]
+    pub(crate) fn abs(f: f32) -> f32 {
+        f32::abs(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn acos_approx(f: f32) -> f32 {
+        super::acos_approx_f32(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn asin(f: f32) -> f32 {
+        f32::asin(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn atan2(f: f32, other: f32) -> f32 {
+        f32::atan2(f, other)
+    }
+
+    #[allow(unused)]
+    #[inline(always)]
+    pub(crate) fn sin(f: f32) -> f32 {
+        f32::sin(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn sin_cos(f: f32) -> (f32, f32) {
+        f32::sin_cos(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn tan(f: f32) -> f32 {
+        f32::tan(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn sqrt(f: f32) -> f32 {
+        f32::sqrt(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn copysign(f: f32, sign: f32) -> f32 {
+        f32::copysign(f, sign)
+    }
+
+    #[inline(always)]
+    pub(crate) fn signum(f: f32) -> f32 {
+        f32::signum(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn round(f: f32) -> f32 {
+        f32::round(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn trunc(f: f32) -> f32 {
+        f32::trunc(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn ceil(f: f32) -> f32 {
+        f32::ceil(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn floor(f: f32) -> f32 {
+        f32::floor(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn exp(f: f32) -> f32 {
+        f32::exp(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn powf(f: f32, n: f32) -> f32 {
+        f32::powf(f, n)
+    }
+
+    #[inline(always)]
+    pub(crate) fn mul_add(a: f32, b: f32, c: f32) -> f32 {
+        f32::mul_add(a, b, c)
+    }
+
+    #[inline]
+    pub fn div_euclid(a: f32, b: f32) -> f32 {
+        f32::div_euclid(a, b)
+    }
+
+    #[inline]
+    pub fn rem_euclid(a: f32, b: f32) -> f32 {
+        f32::rem_euclid(a, b)
+    }
+}
+
+#[cfg(feature = "libm")]
+pub(crate) use libm_math::*;
+
+#[cfg(not(feature = "libm"))]
+pub(crate) use std_math::*;
diff --git a/src/f32/scalar/mat2.rs b/src/f32/scalar/mat2.rs
index 9c4c253..1205035 100644
--- a/src/f32/scalar/mat2.rs
+++ b/src/f32/scalar/mat2.rs
@@ -1,17 +1,14 @@
 // Generated from mat.rs.tera template. Edit the template, not the generated file.
 
-use crate::{swizzles::*, DMat2, Mat3, Mat3A, Vec2};
+use crate::{f32::math, swizzles::*, DMat2, Mat3, Mat3A, Vec2};
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
 use core::iter::{Product, Sum};
 use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
 
-#[cfg(feature = "libm")]
-#[allow(unused_imports)]
-use num_traits::Float;
-
-/// Creates a 2x2 matrix from column vectors.
+/// Creates a 2x2 matrix from two column vectors.
 #[inline(always)]
+#[must_use]
 pub const fn mat2(x_axis: Vec2, y_axis: Vec2) -> Mat2 {
     Mat2::from_cols(x_axis, y_axis)
 }
@@ -41,6 +38,7 @@
 
     #[allow(clippy::too_many_arguments)]
     #[inline(always)]
+    #[must_use]
     const fn new(m00: f32, m01: f32, m10: f32, m11: f32) -> Self {
         Self {
             x_axis: Vec2::new(m00, m01),
@@ -50,6 +48,7 @@
 
     /// Creates a 2x2 matrix from two column vectors.
     #[inline(always)]
+    #[must_use]
     pub const fn from_cols(x_axis: Vec2, y_axis: Vec2) -> Self {
         Self { x_axis, y_axis }
     }
@@ -58,6 +57,7 @@
     /// If your data is stored in row major you will need to `transpose` the returned
     /// matrix.
     #[inline]
+    #[must_use]
     pub const fn from_cols_array(m: &[f32; 4]) -> Self {
         Self::new(m[0], m[1], m[2], m[3])
     }
@@ -65,6 +65,7 @@
     /// Creates a `[f32; 4]` array storing data in column major order.
     /// If you require data in row major order `transpose` the matrix first.
     #[inline]
+    #[must_use]
     pub const fn to_cols_array(&self) -> [f32; 4] {
         [self.x_axis.x, self.x_axis.y, self.y_axis.x, self.y_axis.y]
     }
@@ -73,6 +74,7 @@
     /// If your data is in row major order you will need to `transpose` the returned
     /// matrix.
     #[inline]
+    #[must_use]
     pub const fn from_cols_array_2d(m: &[[f32; 2]; 2]) -> Self {
         Self::from_cols(Vec2::from_array(m[0]), Vec2::from_array(m[1]))
     }
@@ -80,6 +82,7 @@
     /// Creates a `[[f32; 2]; 2]` 2D array storing data in column major order.
     /// If you require data in row major order `transpose` the matrix first.
     #[inline]
+    #[must_use]
     pub const fn to_cols_array_2d(&self) -> [[f32; 2]; 2] {
         [self.x_axis.to_array(), self.y_axis.to_array()]
     }
@@ -87,6 +90,7 @@
     /// Creates a 2x2 matrix with its diagonal set to `diagonal` and all other entries set to 0.
     #[doc(alias = "scale")]
     #[inline]
+    #[must_use]
     pub const fn from_diagonal(diagonal: Vec2) -> Self {
         Self::new(diagonal.x, 0.0, 0.0, diagonal.y)
     }
@@ -94,26 +98,30 @@
     /// Creates a 2x2 matrix containing the combining non-uniform `scale` and rotation of
     /// `angle` (in radians).
     #[inline]
+    #[must_use]
     pub fn from_scale_angle(scale: Vec2, angle: f32) -> Self {
-        let (sin, cos) = angle.sin_cos();
+        let (sin, cos) = math::sin_cos(angle);
         Self::new(cos * scale.x, sin * scale.x, -sin * scale.y, cos * scale.y)
     }
 
     /// Creates a 2x2 matrix containing a rotation of `angle` (in radians).
     #[inline]
+    #[must_use]
     pub fn from_angle(angle: f32) -> Self {
-        let (sin, cos) = angle.sin_cos();
+        let (sin, cos) = math::sin_cos(angle);
         Self::new(cos, sin, -sin, cos)
     }
 
     /// Creates a 2x2 matrix from a 3x3 matrix, discarding the 2nd row and column.
     #[inline]
+    #[must_use]
     pub fn from_mat3(m: Mat3) -> Self {
         Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
     }
 
     /// 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())
     }
@@ -124,6 +132,7 @@
     ///
     /// Panics if `slice` is less than 4 elements long.
     #[inline]
+    #[must_use]
     pub const fn from_cols_slice(slice: &[f32]) -> Self {
         Self::new(slice[0], slice[1], slice[2], slice[3])
     }
@@ -147,6 +156,7 @@
     ///
     /// Panics if `index` is greater than 1.
     #[inline]
+    #[must_use]
     pub fn col(&self, index: usize) -> Vec2 {
         match index {
             0 => self.x_axis,
@@ -175,6 +185,7 @@
     ///
     /// Panics if `index` is greater than 1.
     #[inline]
+    #[must_use]
     pub fn row(&self, index: usize) -> Vec2 {
         match index {
             0 => Vec2::new(self.x_axis.x, self.y_axis.x),
@@ -186,19 +197,21 @@
     /// Returns `true` if, and only if, all elements are finite.
     /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
     #[inline]
+    #[must_use]
     pub fn is_finite(&self) -> bool {
         self.x_axis.is_finite() && self.y_axis.is_finite()
     }
 
     /// Returns `true` if any elements are `NaN`.
     #[inline]
+    #[must_use]
     pub fn is_nan(&self) -> bool {
         self.x_axis.is_nan() || self.y_axis.is_nan()
     }
 
     /// Returns the transpose of `self`.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn transpose(&self) -> Self {
         Self {
             x_axis: Vec2::new(self.x_axis.x, self.y_axis.x),
@@ -208,6 +221,7 @@
 
     /// Returns the determinant of `self`.
     #[inline]
+    #[must_use]
     pub fn determinant(&self) -> f32 {
         self.x_axis.x * self.y_axis.y - self.x_axis.y * self.y_axis.x
     }
@@ -219,8 +233,8 @@
     /// # Panics
     ///
     /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn inverse(&self) -> Self {
         let inv_det = {
             let det = self.determinant();
@@ -237,6 +251,7 @@
 
     /// Transforms a 2D vector.
     #[inline]
+    #[must_use]
     pub fn mul_vec2(&self, rhs: Vec2) -> Vec2 {
         #[allow(clippy::suspicious_operation_groupings)]
         Vec2::new(
@@ -247,24 +262,28 @@
 
     /// Multiplies two 2x2 matrices.
     #[inline]
+    #[must_use]
     pub fn mul_mat2(&self, rhs: &Self) -> Self {
         Self::from_cols(self.mul(rhs.x_axis), self.mul(rhs.y_axis))
     }
 
     /// Adds two 2x2 matrices.
     #[inline]
+    #[must_use]
     pub fn add_mat2(&self, rhs: &Self) -> Self {
         Self::from_cols(self.x_axis.add(rhs.x_axis), self.y_axis.add(rhs.y_axis))
     }
 
     /// Subtracts two 2x2 matrices.
     #[inline]
+    #[must_use]
     pub fn sub_mat2(&self, rhs: &Self) -> Self {
         Self::from_cols(self.x_axis.sub(rhs.x_axis), self.y_axis.sub(rhs.y_axis))
     }
 
     /// Multiplies a 2x2 matrix by a scalar.
     #[inline]
+    #[must_use]
     pub fn mul_scalar(&self, rhs: f32) -> Self {
         Self::from_cols(self.x_axis.mul(rhs), self.y_axis.mul(rhs))
     }
@@ -279,6 +298,7 @@
     /// For more see
     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
     #[inline]
+    #[must_use]
     pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
         self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
             && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
diff --git a/src/f32/scalar/mat3a.rs b/src/f32/scalar/mat3a.rs
index ea56981..b443ae0 100644
--- a/src/f32/scalar/mat3a.rs
+++ b/src/f32/scalar/mat3a.rs
@@ -1,17 +1,14 @@
 // Generated from mat.rs.tera template. Edit the template, not the generated file.
 
-use crate::{swizzles::*, DMat3, EulerRot, Mat2, Mat3, Mat4, Quat, Vec2, Vec3, Vec3A};
+use crate::{f32::math, swizzles::*, DMat3, EulerRot, Mat2, Mat3, Mat4, Quat, Vec2, Vec3, Vec3A};
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
 use core::iter::{Product, Sum};
 use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
 
-#[cfg(feature = "libm")]
-#[allow(unused_imports)]
-use num_traits::Float;
-
-/// Creates a 3x3 matrix from column vectors.
+/// Creates a 3x3 matrix from three column vectors.
 #[inline(always)]
+#[must_use]
 pub const fn mat3a(x_axis: Vec3A, y_axis: Vec3A, z_axis: Vec3A) -> Mat3A {
     Mat3A::from_cols(x_axis, y_axis, z_axis)
 }
@@ -60,6 +57,7 @@
 
     #[allow(clippy::too_many_arguments)]
     #[inline(always)]
+    #[must_use]
     const fn new(
         m00: f32,
         m01: f32,
@@ -78,8 +76,9 @@
         }
     }
 
-    /// Creates a 3x3 matrix from two column vectors.
+    /// Creates a 3x3 matrix from three column vectors.
     #[inline(always)]
+    #[must_use]
     pub const fn from_cols(x_axis: Vec3A, y_axis: Vec3A, z_axis: Vec3A) -> Self {
         Self {
             x_axis,
@@ -92,6 +91,7 @@
     /// If your data is stored in row major you will need to `transpose` the returned
     /// matrix.
     #[inline]
+    #[must_use]
     pub const fn from_cols_array(m: &[f32; 9]) -> Self {
         Self::new(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8])
     }
@@ -99,6 +99,7 @@
     /// Creates a `[f32; 9]` array storing data in column major order.
     /// If you require data in row major order `transpose` the matrix first.
     #[inline]
+    #[must_use]
     pub const fn to_cols_array(&self) -> [f32; 9] {
         [
             self.x_axis.x,
@@ -117,6 +118,7 @@
     /// If your data is in row major order you will need to `transpose` the returned
     /// matrix.
     #[inline]
+    #[must_use]
     pub const fn from_cols_array_2d(m: &[[f32; 3]; 3]) -> Self {
         Self::from_cols(
             Vec3A::from_array(m[0]),
@@ -128,6 +130,7 @@
     /// Creates a `[[f32; 3]; 3]` 3D array storing data in column major order.
     /// If you require data in row major order `transpose` the matrix first.
     #[inline]
+    #[must_use]
     pub const fn to_cols_array_2d(&self) -> [[f32; 3]; 3] {
         [
             self.x_axis.to_array(),
@@ -139,6 +142,7 @@
     /// Creates a 3x3 matrix with its diagonal set to `diagonal` and all other entries set to 0.
     #[doc(alias = "scale")]
     #[inline]
+    #[must_use]
     pub const fn from_diagonal(diagonal: Vec3) -> Self {
         Self::new(
             diagonal.x, 0.0, 0.0, 0.0, diagonal.y, 0.0, 0.0, 0.0, diagonal.z,
@@ -146,6 +150,8 @@
     }
 
     /// Creates a 3x3 matrix from a 4x4 matrix, discarding the 4th row and column.
+    #[inline]
+    #[must_use]
     pub fn from_mat4(m: Mat4) -> Self {
         Self::from_cols(m.x_axis.into(), m.y_axis.into(), m.z_axis.into())
     }
@@ -156,6 +162,7 @@
     ///
     /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_quat(rotation: Quat) -> Self {
         glam_assert!(rotation.is_normalized());
 
@@ -186,10 +193,11 @@
     ///
     /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
         glam_assert!(axis.is_normalized());
 
-        let (sin, cos) = angle.sin_cos();
+        let (sin, cos) = math::sin_cos(angle);
         let (xsin, ysin, zsin) = axis.mul(sin).into();
         let (x, y, z) = axis.into();
         let (x2, y2, z2) = axis.mul(axis).into();
@@ -204,9 +212,10 @@
         )
     }
 
-    #[inline]
     /// Creates a 3D rotation matrix from the given euler rotation sequence and the angles (in
     /// radians).
+    #[inline]
+    #[must_use]
     pub fn from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self {
         let quat = Quat::from_euler(order, a, b, c);
         Self::from_quat(quat)
@@ -214,8 +223,9 @@
 
     /// Creates a 3D rotation matrix from `angle` (in radians) around the x axis.
     #[inline]
+    #[must_use]
     pub fn from_rotation_x(angle: f32) -> Self {
-        let (sina, cosa) = angle.sin_cos();
+        let (sina, cosa) = math::sin_cos(angle);
         Self::from_cols(
             Vec3A::X,
             Vec3A::new(0.0, cosa, sina),
@@ -225,8 +235,9 @@
 
     /// Creates a 3D rotation matrix from `angle` (in radians) around the y axis.
     #[inline]
+    #[must_use]
     pub fn from_rotation_y(angle: f32) -> Self {
-        let (sina, cosa) = angle.sin_cos();
+        let (sina, cosa) = math::sin_cos(angle);
         Self::from_cols(
             Vec3A::new(cosa, 0.0, -sina),
             Vec3A::Y,
@@ -236,8 +247,9 @@
 
     /// Creates a 3D rotation matrix from `angle` (in radians) around the z axis.
     #[inline]
+    #[must_use]
     pub fn from_rotation_z(angle: f32) -> Self {
-        let (sina, cosa) = angle.sin_cos();
+        let (sina, cosa) = math::sin_cos(angle);
         Self::from_cols(
             Vec3A::new(cosa, sina, 0.0),
             Vec3A::new(-sina, cosa, 0.0),
@@ -250,6 +262,7 @@
     /// The resulting matrix can be used to transform 2D points and vectors. See
     /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
     #[inline]
+    #[must_use]
     pub fn from_translation(translation: Vec2) -> Self {
         Self::from_cols(
             Vec3A::X,
@@ -264,8 +277,9 @@
     /// The resulting matrix can be used to transform 2D points and vectors. See
     /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
     #[inline]
+    #[must_use]
     pub fn from_angle(angle: f32) -> Self {
-        let (sin, cos) = angle.sin_cos();
+        let (sin, cos) = math::sin_cos(angle);
         Self::from_cols(
             Vec3A::new(cos, sin, 0.0),
             Vec3A::new(-sin, cos, 0.0),
@@ -279,8 +293,9 @@
     /// The resulting matrix can be used to transform 2D points and vectors. See
     /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
     #[inline]
+    #[must_use]
     pub fn from_scale_angle_translation(scale: Vec2, angle: f32, translation: Vec2) -> Self {
-        let (sin, cos) = angle.sin_cos();
+        let (sin, cos) = math::sin_cos(angle);
         Self::from_cols(
             Vec3A::new(cos * scale.x, sin * scale.x, 0.0),
             Vec3A::new(-sin * scale.y, cos * scale.y, 0.0),
@@ -297,6 +312,7 @@
     ///
     /// Will panic if all elements of `scale` are zero when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_scale(scale: Vec2) -> Self {
         // Do not panic as long as any component is non-zero
         glam_assert!(scale.cmpne(Vec2::ZERO).any());
@@ -323,6 +339,7 @@
     ///
     /// Panics if `slice` is less than 9 elements long.
     #[inline]
+    #[must_use]
     pub const fn from_cols_slice(slice: &[f32]) -> Self {
         Self::new(
             slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
@@ -354,6 +371,7 @@
     ///
     /// Panics if `index` is greater than 2.
     #[inline]
+    #[must_use]
     pub fn col(&self, index: usize) -> Vec3A {
         match index {
             0 => self.x_axis,
@@ -384,6 +402,7 @@
     ///
     /// Panics if `index` is greater than 2.
     #[inline]
+    #[must_use]
     pub fn row(&self, index: usize) -> Vec3A {
         match index {
             0 => Vec3A::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
@@ -396,19 +415,21 @@
     /// Returns `true` if, and only if, all elements are finite.
     /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
     #[inline]
+    #[must_use]
     pub fn is_finite(&self) -> bool {
         self.x_axis.is_finite() && self.y_axis.is_finite() && self.z_axis.is_finite()
     }
 
     /// Returns `true` if any elements are `NaN`.
     #[inline]
+    #[must_use]
     pub fn is_nan(&self) -> bool {
         self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan()
     }
 
     /// Returns the transpose of `self`.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn transpose(&self) -> Self {
         Self {
             x_axis: Vec3A::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
@@ -419,6 +440,7 @@
 
     /// Returns the determinant of `self`.
     #[inline]
+    #[must_use]
     pub fn determinant(&self) -> f32 {
         self.z_axis.dot(self.x_axis.cross(self.y_axis))
     }
@@ -430,8 +452,8 @@
     /// # Panics
     ///
     /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn inverse(&self) -> Self {
         let tmp0 = self.y_axis.cross(self.z_axis);
         let tmp1 = self.z_axis.cross(self.x_axis);
@@ -452,6 +474,7 @@
     ///
     /// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn transform_point2(&self, rhs: Vec2) -> Vec2 {
         glam_assert!(self.row(2).abs_diff_eq(Vec3A::Z, 1e-6));
         Mat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs + self.z_axis.xy()
@@ -467,6 +490,7 @@
     ///
     /// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn transform_vector2(&self, rhs: Vec2) -> Vec2 {
         glam_assert!(self.row(2).abs_diff_eq(Vec3A::Z, 1e-6));
         Mat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs
@@ -474,12 +498,14 @@
 
     /// Transforms a 3D vector.
     #[inline]
+    #[must_use]
     pub fn mul_vec3(&self, rhs: Vec3) -> Vec3 {
         self.mul_vec3a(rhs.into()).into()
     }
 
-    /// Transforms a `Vec3A`.
+    /// Transforms a [`Vec3A`].
     #[inline]
+    #[must_use]
     pub fn mul_vec3a(&self, rhs: Vec3A) -> Vec3A {
         let mut res = self.x_axis.mul(rhs.xxx());
         res = res.add(self.y_axis.mul(rhs.yyy()));
@@ -489,6 +515,7 @@
 
     /// Multiplies two 3x3 matrices.
     #[inline]
+    #[must_use]
     pub fn mul_mat3(&self, rhs: &Self) -> Self {
         Self::from_cols(
             self.mul(rhs.x_axis),
@@ -499,6 +526,7 @@
 
     /// Adds two 3x3 matrices.
     #[inline]
+    #[must_use]
     pub fn add_mat3(&self, rhs: &Self) -> Self {
         Self::from_cols(
             self.x_axis.add(rhs.x_axis),
@@ -509,6 +537,7 @@
 
     /// Subtracts two 3x3 matrices.
     #[inline]
+    #[must_use]
     pub fn sub_mat3(&self, rhs: &Self) -> Self {
         Self::from_cols(
             self.x_axis.sub(rhs.x_axis),
@@ -519,6 +548,7 @@
 
     /// Multiplies a 3x3 matrix by a scalar.
     #[inline]
+    #[must_use]
     pub fn mul_scalar(&self, rhs: f32) -> Self {
         Self::from_cols(
             self.x_axis.mul(rhs),
@@ -537,6 +567,7 @@
     /// For more see
     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
     #[inline]
+    #[must_use]
     pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
         self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
             && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
diff --git a/src/f32/scalar/mat4.rs b/src/f32/scalar/mat4.rs
index 78d7a52..9b1d115 100644
--- a/src/f32/scalar/mat4.rs
+++ b/src/f32/scalar/mat4.rs
@@ -1,17 +1,14 @@
 // Generated from mat.rs.tera template. Edit the template, not the generated file.
 
-use crate::{swizzles::*, DMat4, EulerRot, Mat3, Mat3A, Quat, Vec3, Vec3A, Vec4};
+use crate::{f32::math, swizzles::*, DMat4, EulerRot, Mat3, Mat3A, Quat, Vec3, Vec3A, Vec4};
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
 use core::iter::{Product, Sum};
 use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
 
-#[cfg(feature = "libm")]
-#[allow(unused_imports)]
-use num_traits::Float;
-
-/// Creates a 4x4 matrix from column vectors.
+/// Creates a 4x4 matrix from four column vectors.
 #[inline(always)]
+#[must_use]
 pub const fn mat4(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Mat4 {
     Mat4::from_cols(x_axis, y_axis, z_axis, w_axis)
 }
@@ -27,7 +24,7 @@
 /// using methods such as [`Self::from_translation()`], [`Self::from_quat()`],
 /// [`Self::from_scale()`] and [`Self::from_scale_rotation_translation()`].
 ///
-/// Othographic projections can be created using the methods [`Self::orthographic_lh()`] for
+/// Orthographic projections can be created using the methods [`Self::orthographic_lh()`] for
 /// left-handed coordinate systems and [`Self::orthographic_rh()`] for right-handed
 /// systems. The resulting matrix is also an affine transformation.
 ///
@@ -73,6 +70,7 @@
 
     #[allow(clippy::too_many_arguments)]
     #[inline(always)]
+    #[must_use]
     const fn new(
         m00: f32,
         m01: f32,
@@ -99,8 +97,9 @@
         }
     }
 
-    /// Creates a 4x4 matrix from two column vectors.
+    /// Creates a 4x4 matrix from four column vectors.
     #[inline(always)]
+    #[must_use]
     pub const fn from_cols(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Self {
         Self {
             x_axis,
@@ -114,6 +113,7 @@
     /// If your data is stored in row major you will need to `transpose` the returned
     /// matrix.
     #[inline]
+    #[must_use]
     pub const fn from_cols_array(m: &[f32; 16]) -> Self {
         Self::new(
             m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9], m[10], m[11], m[12], m[13],
@@ -124,6 +124,7 @@
     /// Creates a `[f32; 16]` array storing data in column major order.
     /// If you require data in row major order `transpose` the matrix first.
     #[inline]
+    #[must_use]
     pub const fn to_cols_array(&self) -> [f32; 16] {
         [
             self.x_axis.x,
@@ -149,6 +150,7 @@
     /// If your data is in row major order you will need to `transpose` the returned
     /// matrix.
     #[inline]
+    #[must_use]
     pub const fn from_cols_array_2d(m: &[[f32; 4]; 4]) -> Self {
         Self::from_cols(
             Vec4::from_array(m[0]),
@@ -161,6 +163,7 @@
     /// Creates a `[[f32; 4]; 4]` 4D array storing data in column major order.
     /// If you require data in row major order `transpose` the matrix first.
     #[inline]
+    #[must_use]
     pub const fn to_cols_array_2d(&self) -> [[f32; 4]; 4] {
         [
             self.x_axis.to_array(),
@@ -173,6 +176,7 @@
     /// Creates a 4x4 matrix with its diagonal set to `diagonal` and all other entries set to 0.
     #[doc(alias = "scale")]
     #[inline]
+    #[must_use]
     pub const fn from_diagonal(diagonal: Vec4) -> Self {
         Self::new(
             diagonal.x, 0.0, 0.0, 0.0, 0.0, diagonal.y, 0.0, 0.0, 0.0, 0.0, diagonal.z, 0.0, 0.0,
@@ -181,6 +185,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn quat_to_axes(rotation: Quat) -> (Vec4, Vec4, Vec4) {
         glam_assert!(rotation.is_normalized());
 
@@ -214,6 +219,7 @@
     ///
     /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_scale_rotation_translation(scale: Vec3, rotation: Quat, translation: Vec3) -> Self {
         let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
         Self::from_cols(
@@ -233,6 +239,7 @@
     ///
     /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_rotation_translation(rotation: Quat, translation: Vec3) -> Self {
         let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
         Self::from_cols(x_axis, y_axis, z_axis, Vec4::from((translation, 1.0)))
@@ -246,12 +253,13 @@
     /// Will panic if the determinant of `self` is zero or if the resulting scale vector
     /// contains any zero elements when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn to_scale_rotation_translation(&self) -> (Vec3, Quat, Vec3) {
         let det = self.determinant();
         glam_assert!(det != 0.0);
 
         let scale = Vec3::new(
-            self.x_axis.length() * det.signum(),
+            self.x_axis.length() * math::signum(det),
             self.y_axis.length(),
             self.z_axis.length(),
         );
@@ -280,6 +288,7 @@
     ///
     /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_quat(rotation: Quat) -> Self {
         let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
         Self::from_cols(x_axis, y_axis, z_axis, Vec4::W)
@@ -291,6 +300,7 @@
     /// The resulting matrix can be used to transform 3D points and vectors. See
     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
     #[inline]
+    #[must_use]
     pub fn from_mat3(m: Mat3) -> Self {
         Self::from_cols(
             Vec4::from((m.x_axis, 0.0)),
@@ -306,6 +316,7 @@
     /// The resulting matrix can be used to transform 3D points and vectors. See
     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
     #[inline]
+    #[must_use]
     pub fn from_mat3a(m: Mat3A) -> Self {
         Self::from_cols(
             Vec4::from((m.x_axis, 0.0)),
@@ -320,6 +331,7 @@
     /// The resulting matrix can be used to transform 3D points and vectors. See
     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
     #[inline]
+    #[must_use]
     pub fn from_translation(translation: Vec3) -> Self {
         Self::from_cols(
             Vec4::X,
@@ -339,10 +351,11 @@
     ///
     /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
         glam_assert!(axis.is_normalized());
 
-        let (sin, cos) = angle.sin_cos();
+        let (sin, cos) = math::sin_cos(angle);
         let axis_sin = axis.mul(sin);
         let axis_sq = axis.mul(axis);
         let omc = 1.0 - cos;
@@ -372,12 +385,13 @@
         )
     }
 
-    #[inline]
     /// Creates a affine transformation matrix containing a rotation from the given euler
     /// rotation sequence and angles (in radians).
     ///
     /// The resulting matrix can be used to transform 3D points and vectors. See
     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
+    #[inline]
+    #[must_use]
     pub fn from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self {
         let quat = Quat::from_euler(order, a, b, c);
         Self::from_quat(quat)
@@ -389,8 +403,9 @@
     /// The resulting matrix can be used to transform 3D points and vectors. See
     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
     #[inline]
+    #[must_use]
     pub fn from_rotation_x(angle: f32) -> Self {
-        let (sina, cosa) = angle.sin_cos();
+        let (sina, cosa) = math::sin_cos(angle);
         Self::from_cols(
             Vec4::X,
             Vec4::new(0.0, cosa, sina, 0.0),
@@ -405,8 +420,9 @@
     /// The resulting matrix can be used to transform 3D points and vectors. See
     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
     #[inline]
+    #[must_use]
     pub fn from_rotation_y(angle: f32) -> Self {
-        let (sina, cosa) = angle.sin_cos();
+        let (sina, cosa) = math::sin_cos(angle);
         Self::from_cols(
             Vec4::new(cosa, 0.0, -sina, 0.0),
             Vec4::Y,
@@ -421,8 +437,9 @@
     /// The resulting matrix can be used to transform 3D points and vectors. See
     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
     #[inline]
+    #[must_use]
     pub fn from_rotation_z(angle: f32) -> Self {
-        let (sina, cosa) = angle.sin_cos();
+        let (sina, cosa) = math::sin_cos(angle);
         Self::from_cols(
             Vec4::new(cosa, sina, 0.0, 0.0),
             Vec4::new(-sina, cosa, 0.0, 0.0),
@@ -440,6 +457,7 @@
     ///
     /// Will panic if all elements of `scale` are zero when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_scale(scale: Vec3) -> Self {
         // Do not panic as long as any component is non-zero
         glam_assert!(scale.cmpne(Vec3::ZERO).any());
@@ -458,6 +476,7 @@
     ///
     /// Panics if `slice` is less than 16 elements long.
     #[inline]
+    #[must_use]
     pub const fn from_cols_slice(slice: &[f32]) -> Self {
         Self::new(
             slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
@@ -496,6 +515,7 @@
     ///
     /// Panics if `index` is greater than 3.
     #[inline]
+    #[must_use]
     pub fn col(&self, index: usize) -> Vec4 {
         match index {
             0 => self.x_axis,
@@ -528,6 +548,7 @@
     ///
     /// Panics if `index` is greater than 3.
     #[inline]
+    #[must_use]
     pub fn row(&self, index: usize) -> Vec4 {
         match index {
             0 => Vec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
@@ -541,6 +562,7 @@
     /// Returns `true` if, and only if, all elements are finite.
     /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
     #[inline]
+    #[must_use]
     pub fn is_finite(&self) -> bool {
         self.x_axis.is_finite()
             && self.y_axis.is_finite()
@@ -550,13 +572,14 @@
 
     /// Returns `true` if any elements are `NaN`.
     #[inline]
+    #[must_use]
     pub fn is_nan(&self) -> bool {
         self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan() || self.w_axis.is_nan()
     }
 
     /// Returns the transpose of `self`.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn transpose(&self) -> Self {
         Self {
             x_axis: Vec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
@@ -567,6 +590,7 @@
     }
 
     /// Returns the determinant of `self`.
+    #[must_use]
     pub fn determinant(&self) -> f32 {
         let (m00, m01, m02, m03) = self.x_axis.into();
         let (m10, m11, m12, m13) = self.y_axis.into();
@@ -672,6 +696,7 @@
     ///
     /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
     #[inline]
+    #[must_use]
     pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
         Self::look_to_rh(eye, -dir, up)
     }
@@ -681,6 +706,7 @@
     ///
     /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
     #[inline]
+    #[must_use]
     pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
         let f = dir.normalize();
         let s = f.cross(up).normalize();
@@ -702,6 +728,7 @@
     ///
     /// Will panic if `up` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
         glam_assert!(up.is_normalized());
         Self::look_to_lh(eye, center.sub(eye), up)
@@ -724,6 +751,7 @@
     /// This is the same as the OpenGL `gluPerspective` function.
     /// See <https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml>
     #[inline]
+    #[must_use]
     pub fn perspective_rh_gl(
         fov_y_radians: f32,
         aspect_ratio: f32,
@@ -731,7 +759,7 @@
         z_far: f32,
     ) -> Self {
         let inv_length = 1.0 / (z_near - z_far);
-        let f = 1.0 / (0.5 * fov_y_radians).tan();
+        let f = 1.0 / math::tan(0.5 * fov_y_radians);
         let a = f / aspect_ratio;
         let b = (z_near + z_far) * inv_length;
         let c = (2.0 * z_near * z_far) * inv_length;
@@ -750,9 +778,10 @@
     /// Will panic if `z_near` or `z_far` are less than or equal to zero when `glam_assert` is
     /// enabled.
     #[inline]
+    #[must_use]
     pub fn perspective_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
         glam_assert!(z_near > 0.0 && z_far > 0.0);
-        let (sin_fov, cos_fov) = (0.5 * fov_y_radians).sin_cos();
+        let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
         let h = cos_fov / sin_fov;
         let w = h / aspect_ratio;
         let r = z_far / (z_far - z_near);
@@ -771,9 +800,10 @@
     /// Will panic if `z_near` or `z_far` are less than or equal to zero when `glam_assert` is
     /// enabled.
     #[inline]
+    #[must_use]
     pub fn perspective_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
         glam_assert!(z_near > 0.0 && z_far > 0.0);
-        let (sin_fov, cos_fov) = (0.5 * fov_y_radians).sin_cos();
+        let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
         let h = cos_fov / sin_fov;
         let w = h / aspect_ratio;
         let r = z_far / (z_near - z_far);
@@ -791,9 +821,10 @@
     ///
     /// Will panic if `z_near` is less than or equal to zero when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn perspective_infinite_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
         glam_assert!(z_near > 0.0);
-        let (sin_fov, cos_fov) = (0.5 * fov_y_radians).sin_cos();
+        let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
         let h = cos_fov / sin_fov;
         let w = h / aspect_ratio;
         Self::from_cols(
@@ -810,13 +841,14 @@
     ///
     /// Will panic if `z_near` is less than or equal to zero when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn perspective_infinite_reverse_lh(
         fov_y_radians: f32,
         aspect_ratio: f32,
         z_near: f32,
     ) -> Self {
         glam_assert!(z_near > 0.0);
-        let (sin_fov, cos_fov) = (0.5 * fov_y_radians).sin_cos();
+        let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
         let h = cos_fov / sin_fov;
         let w = h / aspect_ratio;
         Self::from_cols(
@@ -830,9 +862,10 @@
     /// Creates an infinite right-handed perspective projection matrix with
     /// `[0,1]` depth range.
     #[inline]
+    #[must_use]
     pub fn perspective_infinite_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
         glam_assert!(z_near > 0.0);
-        let f = 1.0 / (0.5 * fov_y_radians).tan();
+        let f = 1.0 / math::tan(0.5 * fov_y_radians);
         Self::from_cols(
             Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
             Vec4::new(0.0, f, 0.0, 0.0),
@@ -844,13 +877,14 @@
     /// Creates an infinite reverse right-handed perspective projection matrix
     /// with `[0,1]` depth range.
     #[inline]
+    #[must_use]
     pub fn perspective_infinite_reverse_rh(
         fov_y_radians: f32,
         aspect_ratio: f32,
         z_near: f32,
     ) -> Self {
         glam_assert!(z_near > 0.0);
-        let f = 1.0 / (0.5 * fov_y_radians).tan();
+        let f = 1.0 / math::tan(0.5 * fov_y_radians);
         Self::from_cols(
             Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
             Vec4::new(0.0, f, 0.0, 0.0),
@@ -864,6 +898,7 @@
     /// See
     /// <https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glOrtho.xml>
     #[inline]
+    #[must_use]
     pub fn orthographic_rh_gl(
         left: f32,
         right: f32,
@@ -889,6 +924,7 @@
 
     /// Creates a left-handed orthographic projection matrix with `[0,1]` depth range.
     #[inline]
+    #[must_use]
     pub fn orthographic_lh(
         left: f32,
         right: f32,
@@ -915,6 +951,7 @@
 
     /// Creates a right-handed orthographic projection matrix with `[0,1]` depth range.
     #[inline]
+    #[must_use]
     pub fn orthographic_rh(
         left: f32,
         right: f32,
@@ -946,6 +983,7 @@
     ///
     /// This method assumes that `self` contains a projective transform.
     #[inline]
+    #[must_use]
     pub fn project_point3(&self, rhs: Vec3) -> Vec3 {
         let mut res = self.x_axis.mul(rhs.x);
         res = self.y_axis.mul(rhs.y).add(res);
@@ -968,6 +1006,7 @@
     ///
     /// Will panic if the 3rd row of `self` is not `(0, 0, 0, 1)` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn transform_point3(&self, rhs: Vec3) -> Vec3 {
         glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
         let mut res = self.x_axis.mul(rhs.x);
@@ -988,6 +1027,7 @@
     ///
     /// Will panic if the 3rd row of `self` is not `(0, 0, 0, 1)` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn transform_vector3(&self, rhs: Vec3) -> Vec3 {
         glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
         let mut res = self.x_axis.mul(rhs.x);
@@ -996,24 +1036,27 @@
         res.xyz()
     }
 
-    /// Transforms the given `Vec3A` as 3D point.
+    /// Transforms the given [`Vec3A`] as 3D point.
     ///
-    /// This is the equivalent of multiplying the `Vec3A` as a 4D vector where `w` is `1.0`.
+    /// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `1.0`.
     #[inline]
+    #[must_use]
     pub fn transform_point3a(&self, rhs: Vec3A) -> Vec3A {
         self.transform_point3(rhs.into()).into()
     }
 
-    /// Transforms the give `Vec3A` as 3D vector.
+    /// Transforms the give [`Vec3A`] as 3D vector.
     ///
-    /// This is the equivalent of multiplying the `Vec3A` as a 4D vector where `w` is `0.0`.
+    /// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `0.0`.
     #[inline]
+    #[must_use]
     pub fn transform_vector3a(&self, rhs: Vec3A) -> Vec3A {
         self.transform_vector3(rhs.into()).into()
     }
 
     /// Transforms a 4D vector.
     #[inline]
+    #[must_use]
     pub fn mul_vec4(&self, rhs: Vec4) -> Vec4 {
         let mut res = self.x_axis.mul(rhs.x);
         res = res.add(self.y_axis.mul(rhs.y));
@@ -1024,6 +1067,7 @@
 
     /// Multiplies two 4x4 matrices.
     #[inline]
+    #[must_use]
     pub fn mul_mat4(&self, rhs: &Self) -> Self {
         Self::from_cols(
             self.mul(rhs.x_axis),
@@ -1035,6 +1079,7 @@
 
     /// Adds two 4x4 matrices.
     #[inline]
+    #[must_use]
     pub fn add_mat4(&self, rhs: &Self) -> Self {
         Self::from_cols(
             self.x_axis.add(rhs.x_axis),
@@ -1046,6 +1091,7 @@
 
     /// Subtracts two 4x4 matrices.
     #[inline]
+    #[must_use]
     pub fn sub_mat4(&self, rhs: &Self) -> Self {
         Self::from_cols(
             self.x_axis.sub(rhs.x_axis),
@@ -1057,6 +1103,7 @@
 
     /// Multiplies a 4x4 matrix by a scalar.
     #[inline]
+    #[must_use]
     pub fn mul_scalar(&self, rhs: f32) -> Self {
         Self::from_cols(
             self.x_axis.mul(rhs),
@@ -1076,6 +1123,7 @@
     /// For more see
     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
     #[inline]
+    #[must_use]
     pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
         self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
             && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
diff --git a/src/f32/scalar/quat.rs b/src/f32/scalar/quat.rs
index 0b72e8f..d30e4a6 100644
--- a/src/f32/scalar/quat.rs
+++ b/src/f32/scalar/quat.rs
@@ -2,13 +2,10 @@
 
 use crate::{
     euler::{EulerFromQuaternion, EulerRot, EulerToQuaternion},
-    DQuat, FloatEx, Mat3, Mat3A, Mat4, Vec2, Vec3, Vec3A, Vec4,
+    f32::math,
+    DQuat, Mat3, Mat3A, Mat4, Vec2, Vec3, Vec3A, Vec4,
 };
 
-#[cfg(feature = "libm")]
-#[allow(unused_imports)]
-use num_traits::Float;
-
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
 use core::iter::{Product, Sum};
@@ -19,6 +16,7 @@
 /// This should generally not be called manually unless you know what you are doing. Use
 /// one of the other constructors instead such as `identity` or `from_axis_angle`.
 #[inline]
+#[must_use]
 pub const fn quat(x: f32, y: f32, z: f32, w: f32) -> Quat {
     Quat::from_xyzw(x, y, z, w)
 }
@@ -64,6 +62,7 @@
     /// This function does not check if the input is normalized, it is up to the user to
     /// provide normalized input or to normalized the resulting quaternion.
     #[inline(always)]
+    #[must_use]
     pub const fn from_xyzw(x: f32, y: f32, z: f32, w: f32) -> Self {
         Self { x, y, z, w }
     }
@@ -75,6 +74,7 @@
     /// This function does not check if the input is normalized, it is up to the user to
     /// provide normalized input or to normalized the resulting quaternion.
     #[inline]
+    #[must_use]
     pub const fn from_array(a: [f32; 4]) -> Self {
         Self::from_xyzw(a[0], a[1], a[2], a[3])
     }
@@ -86,7 +86,8 @@
     /// This function does not check if the input is normalized, it is up to the user to
     /// provide normalized input or to normalized the resulting quaternion.
     #[inline]
-    pub fn from_vec4(v: Vec4) -> Self {
+    #[must_use]
+    pub const fn from_vec4(v: Vec4) -> Self {
         Self {
             x: v.x,
             y: v.y,
@@ -106,6 +107,7 @@
     ///
     /// Panics if `slice` length is less than 4.
     #[inline]
+    #[must_use]
     pub fn from_slice(slice: &[f32]) -> Self {
         Self::from_xyzw(slice[0], slice[1], slice[2], slice[3])
     }
@@ -124,15 +126,17 @@
     }
 
     /// Create a quaternion for a normalized rotation `axis` and `angle` (in radians).
-    /// The axis must be normalized (unit-length).
+    ///
+    /// The axis must be a unit vector.
     ///
     /// # Panics
     ///
     /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
         glam_assert!(axis.is_normalized());
-        let (s, c) = (angle * 0.5).sin_cos();
+        let (s, c) = math::sin_cos(angle * 0.5);
         let v = axis * s;
         Self::from_xyzw(v.x, v.y, v.z, c)
     }
@@ -141,6 +145,7 @@
     ///
     /// `from_scaled_axis(Vec3::ZERO)` results in the identity quaternion.
     #[inline]
+    #[must_use]
     pub fn from_scaled_axis(v: Vec3) -> Self {
         let length = v.length();
         if length == 0.0 {
@@ -152,33 +157,38 @@
 
     /// Creates a quaternion from the `angle` (in radians) around the x axis.
     #[inline]
+    #[must_use]
     pub fn from_rotation_x(angle: f32) -> Self {
-        let (s, c) = (angle * 0.5).sin_cos();
+        let (s, c) = math::sin_cos(angle * 0.5);
         Self::from_xyzw(s, 0.0, 0.0, c)
     }
 
     /// Creates a quaternion from the `angle` (in radians) around the y axis.
     #[inline]
+    #[must_use]
     pub fn from_rotation_y(angle: f32) -> Self {
-        let (s, c) = (angle * 0.5).sin_cos();
+        let (s, c) = math::sin_cos(angle * 0.5);
         Self::from_xyzw(0.0, s, 0.0, c)
     }
 
     /// Creates a quaternion from the `angle` (in radians) around the z axis.
     #[inline]
+    #[must_use]
     pub fn from_rotation_z(angle: f32) -> Self {
-        let (s, c) = (angle * 0.5).sin_cos();
+        let (s, c) = math::sin_cos(angle * 0.5);
         Self::from_xyzw(0.0, 0.0, s, c)
     }
 
-    #[inline]
     /// Creates a quaternion from the given Euler rotation sequence and the angles (in radians).
+    #[inline]
+    #[must_use]
     pub fn from_euler(euler: EulerRot, a: f32, b: f32, c: f32) -> Self {
         euler.new_quat(a, b, c)
     }
 
     /// From the columns of a 3x3 rotation matrix.
     #[inline]
+    #[must_use]
     pub(crate) fn from_rotation_axes(x_axis: Vec3, y_axis: Vec3, z_axis: Vec3) -> Self {
         // Based on https://github.com/microsoft/DirectXMath `XM$quaternionRotationMatrix`
         let (m00, m01, m02) = x_axis.into();
@@ -191,7 +201,7 @@
             if dif10 <= 0.0 {
                 // x^2 >= y^2
                 let four_xsq = omm22 - dif10;
-                let inv4x = 0.5 / four_xsq.sqrt();
+                let inv4x = 0.5 / math::sqrt(four_xsq);
                 Self::from_xyzw(
                     four_xsq * inv4x,
                     (m01 + m10) * inv4x,
@@ -201,7 +211,7 @@
             } else {
                 // y^2 >= x^2
                 let four_ysq = omm22 + dif10;
-                let inv4y = 0.5 / four_ysq.sqrt();
+                let inv4y = 0.5 / math::sqrt(four_ysq);
                 Self::from_xyzw(
                     (m01 + m10) * inv4y,
                     four_ysq * inv4y,
@@ -216,7 +226,7 @@
             if sum10 <= 0.0 {
                 // z^2 >= w^2
                 let four_zsq = opm22 - sum10;
-                let inv4z = 0.5 / four_zsq.sqrt();
+                let inv4z = 0.5 / math::sqrt(four_zsq);
                 Self::from_xyzw(
                     (m02 + m20) * inv4z,
                     (m12 + m21) * inv4z,
@@ -226,7 +236,7 @@
             } else {
                 // w^2 >= z^2
                 let four_wsq = opm22 + sum10;
-                let inv4w = 0.5 / four_wsq.sqrt();
+                let inv4w = 0.5 / math::sqrt(four_wsq);
                 Self::from_xyzw(
                     (m12 - m21) * inv4w,
                     (m20 - m02) * inv4w,
@@ -239,18 +249,21 @@
 
     /// Creates a quaternion from a 3x3 rotation matrix.
     #[inline]
+    #[must_use]
     pub fn from_mat3(mat: &Mat3) -> Self {
         Self::from_rotation_axes(mat.x_axis, mat.y_axis, mat.z_axis)
     }
 
     /// Creates a quaternion from a 3x3 SIMD aligned rotation matrix.
     #[inline]
+    #[must_use]
     pub fn from_mat3a(mat: &Mat3A) -> Self {
         Self::from_rotation_axes(mat.x_axis.into(), mat.y_axis.into(), mat.z_axis.into())
     }
 
     /// Creates a quaternion from a 3x3 rotation matrix inside a homogeneous 4x4 matrix.
     #[inline]
+    #[must_use]
     pub fn from_mat4(mat: &Mat4) -> Self {
         Self::from_rotation_axes(
             mat.x_axis.truncate(),
@@ -262,7 +275,7 @@
     /// Gets the minimal rotation for transforming `from` to `to`.  The rotation is in the
     /// plane spanned by the two vectors.  Will rotate at most 180 degrees.
     ///
-    /// The input vectors must be normalized (unit-length).
+    /// The inputs must be unit vectors.
     ///
     /// `from_rotation_arc(from, to) * from ≈ to`.
     ///
@@ -272,6 +285,7 @@
     /// # Panics
     ///
     /// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
+    #[must_use]
     pub fn from_rotation_arc(from: Vec3, to: Vec3) -> Self {
         glam_assert!(from.is_normalized());
         glam_assert!(to.is_normalized());
@@ -297,7 +311,7 @@
     /// The rotation is in the plane spanned by the two vectors.  Will rotate at most 90
     /// degrees.
     ///
-    /// The input vectors must be normalized (unit-length).
+    /// The inputs must be unit vectors.
     ///
     /// `to.dot(from_rotation_arc_colinear(from, to) * from).abs() ≈ 1`.
     ///
@@ -305,6 +319,7 @@
     ///
     /// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_rotation_arc_colinear(from: Vec3, to: Vec3) -> Self {
         if from.dot(to) < 0.0 {
             Self::from_rotation_arc(from, -to)
@@ -316,7 +331,7 @@
     /// Gets the minimal rotation for transforming `from` to `to`.  The resulting rotation is
     /// around the z axis. Will rotate at most 180 degrees.
     ///
-    /// The input vectors must be normalized (unit-length).
+    /// The inputs must be unit vectors.
     ///
     /// `from_rotation_arc_2d(from, to) * from ≈ to`.
     ///
@@ -326,6 +341,7 @@
     /// # Panics
     ///
     /// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
+    #[must_use]
     pub fn from_rotation_arc_2d(from: Vec2, to: Vec2) -> Self {
         glam_assert!(from.is_normalized());
         glam_assert!(to.is_normalized());
@@ -346,31 +362,30 @@
             let z = from.x * to.y - to.x * from.y;
             let w = 1.0 + dot;
             // calculate length with x=0 and y=0 to normalize
-            let len_rcp = 1.0 / (z * z + w * w).sqrt();
+            let len_rcp = 1.0 / math::sqrt(z * z + w * w);
             Self::from_xyzw(0.0, 0.0, z * len_rcp, w * len_rcp)
         }
     }
 
-    /// Returns the rotation axis and angle (in radians) of `self`.
+    /// Returns the rotation axis (normalized) and angle (in radians) of `self`.
     #[inline]
+    #[must_use]
     pub fn to_axis_angle(self) -> (Vec3, f32) {
         const EPSILON: f32 = 1.0e-8;
-        const EPSILON_SQUARED: f32 = EPSILON * EPSILON;
-        let w = self.w;
-        let angle = w.acos_approx() * 2.0;
-        let scale_sq = f32::max(1.0 - w * w, 0.0);
-        if scale_sq >= EPSILON_SQUARED {
-            (
-                Vec3::new(self.x, self.y, self.z) * scale_sq.sqrt().recip(),
-                angle,
-            )
+        let v = Vec3::new(self.x, self.y, self.z);
+        let length = v.length();
+        if length >= EPSILON {
+            let angle = 2.0 * math::atan2(length, self.w);
+            let axis = v / length;
+            (axis, angle)
         } else {
-            (Vec3::X, angle)
+            (Vec3::X, 0.0)
         }
     }
 
     /// Returns the rotation axis scaled by the rotation in radians.
     #[inline]
+    #[must_use]
     pub fn to_scaled_axis(self) -> Vec3 {
         let (axis, angle) = self.to_axis_angle();
         axis * angle
@@ -378,26 +393,29 @@
 
     /// Returns the rotation angles for the given euler rotation sequence.
     #[inline]
+    #[must_use]
     pub fn to_euler(self, euler: EulerRot) -> (f32, f32, f32) {
         euler.convert_quat(self)
     }
 
     /// `[x, y, z, w]`
     #[inline]
+    #[must_use]
     pub fn to_array(&self) -> [f32; 4] {
         [self.x, self.y, self.z, self.w]
     }
 
     /// Returns the vector part of the quaternion.
     #[inline]
+    #[must_use]
     pub fn xyz(self) -> Vec3 {
         Vec3::new(self.x, self.y, self.z)
     }
 
     /// Returns the quaternion conjugate of `self`. For a unit quaternion the
     /// conjugate is also the inverse.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn conjugate(self) -> Self {
         Self {
             x: -self.x,
@@ -416,8 +434,8 @@
     /// # Panics
     ///
     /// Will panic if `self` is not normalized when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn inverse(self) -> Self {
         glam_assert!(self.is_normalized());
         self.conjugate()
@@ -426,6 +444,7 @@
     /// Computes the dot product of `self` and `rhs`. The dot product is
     /// equal to the cosine of the angle between two quaternion rotations.
     #[inline]
+    #[must_use]
     pub fn dot(self, rhs: Self) -> f32 {
         Vec4::from(self).dot(Vec4::from(rhs))
     }
@@ -433,6 +452,7 @@
     /// Computes the length of `self`.
     #[doc(alias = "magnitude")]
     #[inline]
+    #[must_use]
     pub fn length(self) -> f32 {
         Vec4::from(self).length()
     }
@@ -443,6 +463,7 @@
     /// root operation.
     #[doc(alias = "magnitude2")]
     #[inline]
+    #[must_use]
     pub fn length_squared(self) -> f32 {
         Vec4::from(self).length_squared()
     }
@@ -451,6 +472,7 @@
     ///
     /// For valid results, `self` must _not_ be of length zero.
     #[inline]
+    #[must_use]
     pub fn length_recip(self) -> f32 {
         Vec4::from(self).length_recip()
     }
@@ -462,8 +484,8 @@
     /// Panics
     ///
     /// Will panic if `self` is zero length when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn normalize(self) -> Self {
         Self::from_vec4(Vec4::from(self).normalize())
     }
@@ -471,11 +493,13 @@
     /// Returns `true` if, and only if, all elements are finite.
     /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
     #[inline]
+    #[must_use]
     pub fn is_finite(self) -> bool {
         Vec4::from(self).is_finite()
     }
 
     #[inline]
+    #[must_use]
     pub fn is_nan(self) -> bool {
         Vec4::from(self).is_nan()
     }
@@ -484,11 +508,13 @@
     ///
     /// Uses a precision threshold of `1e-6`.
     #[inline]
+    #[must_use]
     pub fn is_normalized(self) -> bool {
         Vec4::from(self).is_normalized()
     }
 
     #[inline]
+    #[must_use]
     pub fn is_near_identity(self) -> bool {
         // Based on https://github.com/nfrechette/rtm `rtm::quat_near_identity`
         let threshold_angle = 0.002_847_144_6;
@@ -505,7 +531,7 @@
         // If the quat.w is close to -1.0, the angle will be near 2*PI which is close to
         // a negative 0 rotation. By forcing quat.w to be positive, we'll end up with
         // the shortest path.
-        let positive_w_angle = self.w.abs().acos_approx() * 2.0;
+        let positive_w_angle = math::acos_approx(math::abs(self.w)) * 2.0;
         positive_w_angle < threshold_angle
     }
 
@@ -518,9 +544,10 @@
     ///
     /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn angle_between(self, rhs: Self) -> f32 {
         glam_assert!(self.is_normalized() && rhs.is_normalized());
-        self.dot(rhs).abs().acos_approx() * 2.0
+        math::acos_approx(math::abs(self.dot(rhs))) * 2.0
     }
 
     /// Returns true if the absolute difference of all elements between `self` and `rhs`
@@ -533,6 +560,7 @@
     /// For more see
     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
     #[inline]
+    #[must_use]
     pub fn abs_diff_eq(self, rhs: Self, max_abs_diff: f32) -> bool {
         Vec4::from(self).abs_diff_eq(Vec4::from(rhs), max_abs_diff)
     }
@@ -546,8 +574,9 @@
     /// # Panics
     ///
     /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
-    #[inline]
     #[doc(alias = "mix")]
+    #[inline]
+    #[must_use]
     pub fn lerp(self, end: Self, s: f32) -> Self {
         glam_assert!(self.is_normalized());
         glam_assert!(end.is_normalized());
@@ -569,6 +598,7 @@
     ///
     /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn slerp(self, mut end: Self, s: f32) -> Self {
         // http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/
         glam_assert!(self.is_normalized());
@@ -592,13 +622,13 @@
             // assumes lerp returns a normalized quaternion
             self.lerp(end, s)
         } else {
-            let theta = dot.acos_approx();
+            let theta = math::acos_approx(dot);
 
-            let scale1 = (theta * (1.0 - s)).sin();
-            let scale2 = (theta * s).sin();
-            let theta_sin = theta.sin();
+            let scale1 = math::sin(theta * (1.0 - s));
+            let scale2 = math::sin(theta * s);
+            let theta_sin = math::sin(theta);
 
-            self.mul(scale1).add(end.mul(scale2)).mul(theta_sin.recip())
+            self.mul(scale1).add(end.mul(scale2)).mul(1.0 / theta_sin)
         }
     }
 
@@ -608,6 +638,7 @@
     ///
     /// Will panic if `self` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn mul_vec3(self, rhs: Vec3) -> Vec3 {
         glam_assert!(self.is_normalized());
 
@@ -628,6 +659,7 @@
     ///
     /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn mul_quat(self, rhs: Self) -> Self {
         glam_assert!(self.is_normalized());
         glam_assert!(rhs.is_normalized());
@@ -644,6 +676,7 @@
 
     /// Creates a quaternion from a 3x3 rotation matrix inside a 3D affine transform.
     #[inline]
+    #[must_use]
     pub fn from_affine3(a: &crate::Affine3A) -> Self {
         #[allow(clippy::useless_conversion)]
         Self::from_rotation_axes(
@@ -655,14 +688,23 @@
 
     /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
     #[inline]
+    #[must_use]
     pub fn mul_vec3a(self, rhs: Vec3A) -> Vec3A {
         self.mul_vec3(rhs.into()).into()
     }
 
     #[inline]
-    pub fn as_f64(self) -> DQuat {
+    #[must_use]
+    pub fn as_dquat(self) -> DQuat {
         DQuat::from_xyzw(self.x as f64, self.y as f64, self.z as f64, self.w as f64)
     }
+
+    #[inline]
+    #[must_use]
+    #[deprecated(since = "0.24.2", note = "Use as_dquat() instead")]
+    pub fn as_f64(self) -> DQuat {
+        self.as_dquat()
+    }
 }
 
 #[cfg(not(target_arch = "spirv"))]
diff --git a/src/f32/scalar/vec3a.rs b/src/f32/scalar/vec3a.rs
index 311e1e0..040a140 100644
--- a/src/f32/scalar/vec3a.rs
+++ b/src/f32/scalar/vec3a.rs
@@ -1,28 +1,28 @@
 // Generated from vec.rs.tera template. Edit the template, not the generated file.
 
-use crate::{BVec3A, Vec2, Vec3, Vec4};
+use crate::{f32::math, BVec3A, Vec2, Vec3, Vec4};
 
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
 use core::iter::{Product, Sum};
 use core::{f32, ops::*};
 
-#[cfg(feature = "libm")]
-#[allow(unused_imports)]
-use num_traits::Float;
-
 /// Creates a 3-dimensional vector.
 #[inline(always)]
+#[must_use]
 pub const fn vec3a(x: f32, y: f32, z: f32) -> Vec3A {
     Vec3A::new(x, y, z)
 }
 
-/// A 3-dimensional vector with SIMD support.
+/// A 3-dimensional vector.
 ///
-/// This type is 16 byte aligned. A SIMD vector type is used for storage on supported platforms for
-/// better performance than the `Vec3` type.
+/// SIMD vector types are used for storage on supported platforms for better
+/// performance than the [`Vec3`] type.
 ///
-/// It is possible to convert between `Vec3` and `Vec3A` types using `From` trait implementations.
+/// It is possible to convert between [`Vec3`] and [`Vec3A`] types using [`From`]
+/// or [`Into`] trait implementations.
+///
+/// This type is 16 byte aligned.
 #[derive(Clone, Copy, PartialEq)]
 #[cfg_attr(not(target_arch = "spirv"), repr(align(16)))]
 #[cfg_attr(not(target_arch = "spirv"), repr(C))]
@@ -43,25 +43,37 @@
     /// All negative ones.
     pub const NEG_ONE: Self = Self::splat(-1.0);
 
-    /// All NAN.
+    /// All `f32::MIN`.
+    pub const MIN: Self = Self::splat(f32::MIN);
+
+    /// All `f32::MAX`.
+    pub const MAX: Self = Self::splat(f32::MAX);
+
+    /// All `f32::NAN`.
     pub const NAN: Self = Self::splat(f32::NAN);
 
-    /// A unit-length vector pointing along the positive X axis.
+    /// All `f32::INFINITY`.
+    pub const INFINITY: Self = Self::splat(f32::INFINITY);
+
+    /// All `f32::NEG_INFINITY`.
+    pub const NEG_INFINITY: Self = Self::splat(f32::NEG_INFINITY);
+
+    /// A unit vector pointing along the positive X axis.
     pub const X: Self = Self::new(1.0, 0.0, 0.0);
 
-    /// A unit-length vector pointing along the positive Y axis.
+    /// A unit vector pointing along the positive Y axis.
     pub const Y: Self = Self::new(0.0, 1.0, 0.0);
 
-    /// A unit-length vector pointing along the positive Z axis.
+    /// A unit vector pointing along the positive Z axis.
     pub const Z: Self = Self::new(0.0, 0.0, 1.0);
 
-    /// A unit-length vector pointing along the negative X axis.
+    /// A unit vector pointing along the negative X axis.
     pub const NEG_X: Self = Self::new(-1.0, 0.0, 0.0);
 
-    /// A unit-length vector pointing along the negative Y axis.
+    /// A unit vector pointing along the negative Y axis.
     pub const NEG_Y: Self = Self::new(0.0, -1.0, 0.0);
 
-    /// A unit-length vector pointing along the negative Z axis.
+    /// A unit vector pointing along the negative Z axis.
     pub const NEG_Z: Self = Self::new(0.0, 0.0, -1.0);
 
     /// The unit axes.
@@ -69,12 +81,14 @@
 
     /// Creates a new vector.
     #[inline(always)]
+    #[must_use]
     pub const fn new(x: f32, y: f32, z: f32) -> Self {
         Self { x, y, z }
     }
 
     /// Creates a vector with all elements set to `v`.
     #[inline]
+    #[must_use]
     pub const fn splat(v: f32) -> Self {
         Self { x: v, y: v, z: v }
     }
@@ -85,22 +99,25 @@
     /// A true element in the mask uses the corresponding element from `if_true`, and false
     /// uses the element from `if_false`.
     #[inline]
+    #[must_use]
     pub fn select(mask: BVec3A, if_true: Self, if_false: Self) -> Self {
         Self {
-            x: if mask.x != 0 { if_true.x } else { if_false.x },
-            y: if mask.y != 0 { if_true.y } else { if_false.y },
-            z: if mask.z != 0 { if_true.z } else { if_false.z },
+            x: if mask.test(0) { if_true.x } else { if_false.x },
+            y: if mask.test(1) { if_true.y } else { if_false.y },
+            z: if mask.test(2) { if_true.z } else { if_false.z },
         }
     }
 
     /// Creates a new vector from an array.
     #[inline]
+    #[must_use]
     pub const fn from_array(a: [f32; 3]) -> Self {
         Self::new(a[0], a[1], a[2])
     }
 
     /// `[x, y, z]`
     #[inline]
+    #[must_use]
     pub const fn to_array(&self) -> [f32; 3] {
         [self.x, self.y, self.z]
     }
@@ -111,6 +128,7 @@
     ///
     /// Panics if `slice` is less than 3 elements long.
     #[inline]
+    #[must_use]
     pub const fn from_slice(slice: &[f32]) -> Self {
         Self::new(slice[0], slice[1], slice[2])
     }
@@ -130,6 +148,7 @@
     /// Internal method for creating a 3D vector from a 4D vector, discarding `w`.
     #[allow(dead_code)]
     #[inline]
+    #[must_use]
     pub(crate) fn from_vec4(v: Vec4) -> Self {
         Self {
             x: v.x,
@@ -140,14 +159,16 @@
 
     /// Creates a 4D vector from `self` and the given `w` value.
     #[inline]
+    #[must_use]
     pub fn extend(self, w: f32) -> Vec4 {
         Vec4::new(self.x, self.y, self.z, w)
     }
 
     /// Creates a 2D vector from the `x` and `y` elements of `self`, discarding `z`.
     ///
-    /// Truncation may also be performed by using `self.xy()` or `Vec2::from()`.
+    /// Truncation may also be performed by using [`self.xy()`][crate::swizzles::Vec3Swizzles::xy()].
     #[inline]
+    #[must_use]
     pub fn truncate(self) -> Vec2 {
         use crate::swizzles::Vec3Swizzles;
         self.xy()
@@ -155,18 +176,21 @@
 
     /// Computes the dot product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn dot(self, rhs: Self) -> f32 {
         (self.x * rhs.x) + (self.y * rhs.y) + (self.z * rhs.z)
     }
 
     /// Returns a vector where every component is the dot product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn dot_into_vec(self, rhs: Self) -> Self {
         Self::splat(self.dot(rhs))
     }
 
     /// Computes the cross product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn cross(self, rhs: Self) -> Self {
         Self {
             x: self.y * rhs.z - rhs.y * self.z,
@@ -179,6 +203,7 @@
     ///
     /// In other words this computes `[self.x.min(rhs.x), self.y.min(rhs.y), ..]`.
     #[inline]
+    #[must_use]
     pub fn min(self, rhs: Self) -> Self {
         Self {
             x: self.x.min(rhs.x),
@@ -191,6 +216,7 @@
     ///
     /// In other words this computes `[self.x.max(rhs.x), self.y.max(rhs.y), ..]`.
     #[inline]
+    #[must_use]
     pub fn max(self, rhs: Self) -> Self {
         Self {
             x: self.x.max(rhs.x),
@@ -207,6 +233,7 @@
     ///
     /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn clamp(self, min: Self, max: Self) -> Self {
         glam_assert!(min.cmple(max).all(), "clamp: expected min <= max");
         self.max(min).min(max)
@@ -216,6 +243,7 @@
     ///
     /// In other words this computes `min(x, y, ..)`.
     #[inline]
+    #[must_use]
     pub fn min_element(self) -> f32 {
         self.x.min(self.y.min(self.z))
     }
@@ -224,6 +252,7 @@
     ///
     /// In other words this computes `max(x, y, ..)`.
     #[inline]
+    #[must_use]
     pub fn max_element(self) -> f32 {
         self.x.max(self.y.max(self.z))
     }
@@ -234,6 +263,7 @@
     /// In other words, this computes `[self.x == rhs.x, self.y == rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpeq(self, rhs: Self) -> BVec3A {
         BVec3A::new(self.x.eq(&rhs.x), self.y.eq(&rhs.y), self.z.eq(&rhs.z))
     }
@@ -244,6 +274,7 @@
     /// In other words this computes `[self.x != rhs.x, self.y != rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpne(self, rhs: Self) -> BVec3A {
         BVec3A::new(self.x.ne(&rhs.x), self.y.ne(&rhs.y), self.z.ne(&rhs.z))
     }
@@ -254,6 +285,7 @@
     /// In other words this computes `[self.x >= rhs.x, self.y >= rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpge(self, rhs: Self) -> BVec3A {
         BVec3A::new(self.x.ge(&rhs.x), self.y.ge(&rhs.y), self.z.ge(&rhs.z))
     }
@@ -264,6 +296,7 @@
     /// In other words this computes `[self.x > rhs.x, self.y > rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpgt(self, rhs: Self) -> BVec3A {
         BVec3A::new(self.x.gt(&rhs.x), self.y.gt(&rhs.y), self.z.gt(&rhs.z))
     }
@@ -274,6 +307,7 @@
     /// In other words this computes `[self.x <= rhs.x, self.y <= rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmple(self, rhs: Self) -> BVec3A {
         BVec3A::new(self.x.le(&rhs.x), self.y.le(&rhs.y), self.z.le(&rhs.z))
     }
@@ -284,17 +318,19 @@
     /// In other words this computes `[self.x < rhs.x, self.y < rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmplt(self, rhs: Self) -> BVec3A {
         BVec3A::new(self.x.lt(&rhs.x), self.y.lt(&rhs.y), self.z.lt(&rhs.z))
     }
 
     /// Returns a vector containing the absolute value of each element of `self`.
     #[inline]
+    #[must_use]
     pub fn abs(self) -> Self {
         Self {
-            x: self.x.abs(),
-            y: self.y.abs(),
-            z: self.z.abs(),
+            x: math::abs(self.x),
+            y: math::abs(self.y),
+            z: math::abs(self.z),
         }
     }
 
@@ -304,21 +340,23 @@
     /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
     /// - `NAN` if the number is `NAN`
     #[inline]
+    #[must_use]
     pub fn signum(self) -> Self {
         Self {
-            x: self.x.signum(),
-            y: self.y.signum(),
-            z: self.z.signum(),
+            x: math::signum(self.x),
+            y: math::signum(self.y),
+            z: math::signum(self.z),
         }
     }
 
     /// Returns a vector with signs of `rhs` and the magnitudes of `self`.
     #[inline]
+    #[must_use]
     pub fn copysign(self, rhs: Self) -> Self {
         Self {
-            x: self.x.copysign(rhs.x),
-            y: self.y.copysign(rhs.y),
-            z: self.z.copysign(rhs.z),
+            x: math::copysign(self.x, rhs.x),
+            y: math::copysign(self.y, rhs.y),
+            z: math::copysign(self.z, rhs.z),
         }
     }
 
@@ -327,6 +365,7 @@
     /// A negative element results in a `1` bit and a positive element in a `0` bit.  Element `x` goes
     /// into the first lowest bit, element `y` into the second, etc.
     #[inline]
+    #[must_use]
     pub fn is_negative_bitmask(self) -> u32 {
         (self.x.is_sign_negative() as u32)
             | (self.y.is_sign_negative() as u32) << 1
@@ -336,12 +375,14 @@
     /// Returns `true` if, and only if, all elements are finite.  If any element is either
     /// `NaN`, positive or negative infinity, this will return `false`.
     #[inline]
+    #[must_use]
     pub fn is_finite(self) -> bool {
         self.x.is_finite() && self.y.is_finite() && self.z.is_finite()
     }
 
     /// Returns `true` if any elements are `NaN`.
     #[inline]
+    #[must_use]
     pub fn is_nan(self) -> bool {
         self.x.is_nan() || self.y.is_nan() || self.z.is_nan()
     }
@@ -350,6 +391,7 @@
     ///
     /// In other words, this computes `[x.is_nan(), y.is_nan(), z.is_nan(), w.is_nan()]`.
     #[inline]
+    #[must_use]
     pub fn is_nan_mask(self) -> BVec3A {
         BVec3A::new(self.x.is_nan(), self.y.is_nan(), self.z.is_nan())
     }
@@ -357,8 +399,9 @@
     /// Computes the length of `self`.
     #[doc(alias = "magnitude")]
     #[inline]
+    #[must_use]
     pub fn length(self) -> f32 {
-        self.dot(self).sqrt()
+        math::sqrt(self.dot(self))
     }
 
     /// Computes the squared length of `self`.
@@ -366,6 +409,7 @@
     /// This is faster than `length()` as it avoids a square root operation.
     #[doc(alias = "magnitude2")]
     #[inline]
+    #[must_use]
     pub fn length_squared(self) -> f32 {
         self.dot(self)
     }
@@ -374,33 +418,60 @@
     ///
     /// For valid results, `self` must _not_ be of length zero.
     #[inline]
+    #[must_use]
     pub fn length_recip(self) -> f32 {
         self.length().recip()
     }
 
     /// Computes the Euclidean distance between two points in space.
     #[inline]
+    #[must_use]
     pub fn distance(self, rhs: Self) -> f32 {
         (self - rhs).length()
     }
 
     /// Compute the squared euclidean distance between two points in space.
     #[inline]
+    #[must_use]
     pub fn distance_squared(self, rhs: Self) -> f32 {
         (self - rhs).length_squared()
     }
 
+    /// Returns the element-wise quotient of [Euclidean division] of `self` by `rhs`.
+    #[inline]
+    #[must_use]
+    pub fn div_euclid(self, rhs: Self) -> Self {
+        Self::new(
+            math::div_euclid(self.x, rhs.x),
+            math::div_euclid(self.y, rhs.y),
+            math::div_euclid(self.z, rhs.z),
+        )
+    }
+
+    /// Returns the element-wise remainder of [Euclidean division] of `self` by `rhs`.
+    ///
+    /// [Euclidean division]: f32::rem_euclid
+    #[inline]
+    #[must_use]
+    pub fn rem_euclid(self, rhs: Self) -> Self {
+        Self::new(
+            math::rem_euclid(self.x, rhs.x),
+            math::rem_euclid(self.y, rhs.y),
+            math::rem_euclid(self.z, rhs.z),
+        )
+    }
+
     /// Returns `self` normalized to length 1.0.
     ///
     /// For valid results, `self` must _not_ be of length zero, nor very close to zero.
     ///
-    /// See also [`Self::try_normalize`] and [`Self::normalize_or_zero`].
+    /// See also [`Self::try_normalize()`] and [`Self::normalize_or_zero()`].
     ///
     /// Panics
     ///
     /// Will panic if `self` is zero length when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn normalize(self) -> Self {
         #[allow(clippy::let_and_return)]
         let normalized = self.mul(self.length_recip());
@@ -413,9 +484,9 @@
     /// In particular, if the input is zero (or very close to zero), or non-finite,
     /// the result of this operation will be `None`.
     ///
-    /// See also [`Self::normalize_or_zero`].
-    #[must_use]
+    /// See also [`Self::normalize_or_zero()`].
     #[inline]
+    #[must_use]
     pub fn try_normalize(self) -> Option<Self> {
         let rcp = self.length_recip();
         if rcp.is_finite() && rcp > 0.0 {
@@ -430,9 +501,9 @@
     /// In particular, if the input is zero (or very close to zero), or non-finite,
     /// the result of this operation will be zero.
     ///
-    /// See also [`Self::try_normalize`].
-    #[must_use]
+    /// See also [`Self::try_normalize()`].
     #[inline]
+    #[must_use]
     pub fn normalize_or_zero(self) -> Self {
         let rcp = self.length_recip();
         if rcp.is_finite() && rcp > 0.0 {
@@ -446,9 +517,10 @@
     ///
     /// Uses a precision threshold of `1e-6`.
     #[inline]
+    #[must_use]
     pub fn is_normalized(self) -> bool {
         // TODO: do something with epsilon
-        (self.length_squared() - 1.0).abs() <= 1e-4
+        math::abs(self.length_squared() - 1.0) <= 1e-4
     }
 
     /// Returns the vector projection of `self` onto `rhs`.
@@ -458,8 +530,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` is zero length when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn project_onto(self, rhs: Self) -> Self {
         let other_len_sq_rcp = rhs.dot(rhs).recip();
         glam_assert!(other_len_sq_rcp.is_finite());
@@ -476,8 +548,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` has a length of zero when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn reject_from(self, rhs: Self) -> Self {
         self - self.project_onto(rhs)
     }
@@ -489,8 +561,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` is not normalized when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn project_onto_normalized(self, rhs: Self) -> Self {
         glam_assert!(rhs.is_normalized());
         rhs * self.dot(rhs)
@@ -506,8 +578,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` is not normalized when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn reject_from_normalized(self, rhs: Self) -> Self {
         self - self.project_onto_normalized(rhs)
     }
@@ -515,33 +587,48 @@
     /// Returns a vector containing the nearest integer to a number for each element of `self`.
     /// Round half-way cases away from 0.0.
     #[inline]
+    #[must_use]
     pub fn round(self) -> Self {
         Self {
-            x: self.x.round(),
-            y: self.y.round(),
-            z: self.z.round(),
+            x: math::round(self.x),
+            y: math::round(self.y),
+            z: math::round(self.z),
         }
     }
 
     /// Returns a vector containing the largest integer less than or equal to a number for each
     /// element of `self`.
     #[inline]
+    #[must_use]
     pub fn floor(self) -> Self {
         Self {
-            x: self.x.floor(),
-            y: self.y.floor(),
-            z: self.z.floor(),
+            x: math::floor(self.x),
+            y: math::floor(self.y),
+            z: math::floor(self.z),
         }
     }
 
     /// Returns a vector containing the smallest integer greater than or equal to a number for
     /// each element of `self`.
     #[inline]
+    #[must_use]
     pub fn ceil(self) -> Self {
         Self {
-            x: self.x.ceil(),
-            y: self.y.ceil(),
-            z: self.z.ceil(),
+            x: math::ceil(self.x),
+            y: math::ceil(self.y),
+            z: math::ceil(self.z),
+        }
+    }
+
+    /// Returns a vector containing the integer part each element of `self`. This means numbers are
+    /// always truncated towards zero.
+    #[inline]
+    #[must_use]
+    pub fn trunc(self) -> Self {
+        Self {
+            x: math::trunc(self.x),
+            y: math::trunc(self.y),
+            z: math::trunc(self.z),
         }
     }
 
@@ -550,6 +637,7 @@
     ///
     /// Note that this is fast but not precise for large numbers.
     #[inline]
+    #[must_use]
     pub fn fract(self) -> Self {
         self - self.floor()
     }
@@ -557,23 +645,30 @@
     /// Returns a vector containing `e^self` (the exponential function) for each element of
     /// `self`.
     #[inline]
+    #[must_use]
     pub fn exp(self) -> Self {
-        Self::new(self.x.exp(), self.y.exp(), self.z.exp())
+        Self::new(math::exp(self.x), math::exp(self.y), math::exp(self.z))
     }
 
     /// Returns a vector containing each element of `self` raised to the power of `n`.
     #[inline]
+    #[must_use]
     pub fn powf(self, n: f32) -> Self {
-        Self::new(self.x.powf(n), self.y.powf(n), self.z.powf(n))
+        Self::new(
+            math::powf(self.x, n),
+            math::powf(self.y, n),
+            math::powf(self.z, n),
+        )
     }
 
     /// Returns a vector containing the reciprocal `1.0/n` of each element of `self`.
     #[inline]
+    #[must_use]
     pub fn recip(self) -> Self {
         Self {
-            x: self.x.recip(),
-            y: self.y.recip(),
-            z: self.z.recip(),
+            x: 1.0 / self.x,
+            y: 1.0 / self.y,
+            z: 1.0 / self.z,
         }
     }
 
@@ -584,6 +679,7 @@
     /// extrapolated.
     #[doc(alias = "mix")]
     #[inline]
+    #[must_use]
     pub fn lerp(self, rhs: Self, s: f32) -> Self {
         self + ((rhs - self) * s)
     }
@@ -598,6 +694,7 @@
     /// For more see
     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
     #[inline]
+    #[must_use]
     pub fn abs_diff_eq(self, rhs: Self, max_abs_diff: f32) -> bool {
         self.sub(rhs).abs().cmple(Self::splat(max_abs_diff)).all()
     }
@@ -608,33 +705,38 @@
     ///
     /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn clamp_length(self, min: f32, max: f32) -> Self {
         glam_assert!(min <= max);
         let length_sq = self.length_squared();
         if length_sq < min * min {
-            self * (length_sq.sqrt().recip() * min)
+            min * (self / math::sqrt(length_sq))
         } else if length_sq > max * max {
-            self * (length_sq.sqrt().recip() * max)
+            max * (self / math::sqrt(length_sq))
         } else {
             self
         }
     }
 
     /// Returns a vector with a length no more than `max`
+    #[inline]
+    #[must_use]
     pub fn clamp_length_max(self, max: f32) -> Self {
         let length_sq = self.length_squared();
         if length_sq > max * max {
-            self * (length_sq.sqrt().recip() * max)
+            max * (self / math::sqrt(length_sq))
         } else {
             self
         }
     }
 
     /// Returns a vector with a length no less than `min`
+    #[inline]
+    #[must_use]
     pub fn clamp_length_min(self, min: f32) -> Self {
         let length_sq = self.length_squared();
         if length_sq < min * min {
-            self * (length_sq.sqrt().recip() * min)
+            min * (self / math::sqrt(length_sq))
         } else {
             self
         }
@@ -648,74 +750,74 @@
     /// and will be heavily dependant on designing algorithms with specific target hardware in
     /// mind.
     #[inline]
+    #[must_use]
     pub fn mul_add(self, a: Self, b: Self) -> Self {
         Self::new(
-            self.x.mul_add(a.x, b.x),
-            self.y.mul_add(a.y, b.y),
-            self.z.mul_add(a.z, b.z),
+            math::mul_add(self.x, a.x, b.x),
+            math::mul_add(self.y, a.y, b.y),
+            math::mul_add(self.z, a.z, b.z),
         )
     }
 
     /// Returns the angle (in radians) between two vectors.
     ///
-    /// The input vectors do not need to be unit length however they must be non-zero.
+    /// The inputs do not need to be unit vectors however they must be non-zero.
     #[inline]
+    #[must_use]
     pub fn angle_between(self, rhs: Self) -> f32 {
-        use crate::FloatEx;
-        self.dot(rhs)
-            .div(self.length_squared().mul(rhs.length_squared()).sqrt())
-            .acos_approx()
+        math::acos_approx(
+            self.dot(rhs)
+                .div(math::sqrt(self.length_squared().mul(rhs.length_squared()))),
+        )
     }
 
     /// Returns some vector that is orthogonal to the given one.
     ///
     /// The input vector must be finite and non-zero.
     ///
-    /// The output vector is not necessarily unit-length.
-    /// For that use [`Self::any_orthonormal_vector`] instead.
+    /// The output vector is not necessarily unit length. For that use
+    /// [`Self::any_orthonormal_vector()`] instead.
     #[inline]
+    #[must_use]
     pub fn any_orthogonal_vector(&self) -> Self {
         // This can probably be optimized
-        if self.x.abs() > self.y.abs() {
+        if math::abs(self.x) > math::abs(self.y) {
             Self::new(-self.z, 0.0, self.x) // self.cross(Self::Y)
         } else {
             Self::new(0.0, self.z, -self.y) // self.cross(Self::X)
         }
     }
 
-    /// Returns any unit-length vector that is orthogonal to the given one.
-    /// The input vector must be finite and non-zero.
+    /// Returns any unit vector that is orthogonal to the given one.
+    ///
+    /// The input vector must be unit length.
     ///
     /// # Panics
     ///
     /// Will panic if `self` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn any_orthonormal_vector(&self) -> Self {
         glam_assert!(self.is_normalized());
         // From https://graphics.pixar.com/library/OrthonormalB/paper.pdf
-        #[cfg(feature = "std")]
-        let sign = (1.0_f32).copysign(self.z);
-        #[cfg(not(feature = "std"))]
-        let sign = self.z.signum();
+        let sign = math::signum(self.z);
         let a = -1.0 / (sign + self.z);
         let b = self.x * self.y * a;
         Self::new(b, sign + self.y * self.y * a, -self.y)
     }
 
-    /// Given a unit-length vector return two other vectors that together form an orthonormal
-    /// basis.  That is, all three vectors are orthogonal to each other and are normalized.
+    /// Given a unit vector return two other vectors that together form an orthonormal
+    /// basis. That is, all three vectors are orthogonal to each other and are normalized.
     ///
     /// # Panics
     ///
     /// Will panic if `self` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn any_orthonormal_pair(&self) -> (Self, Self) {
         glam_assert!(self.is_normalized());
         // From https://graphics.pixar.com/library/OrthonormalB/paper.pdf
-        #[cfg(feature = "std")]
-        let sign = (1.0_f32).copysign(self.z);
-        #[cfg(not(feature = "std"))]
-        let sign = self.z.signum();
+        let sign = math::signum(self.z);
         let a = -1.0 / (sign + self.z);
         let b = self.x * self.y * a;
         (
@@ -726,21 +828,52 @@
 
     /// Casts all elements of `self` to `f64`.
     #[inline]
+    #[must_use]
     pub fn as_dvec3(&self) -> crate::DVec3 {
         crate::DVec3::new(self.x as f64, self.y as f64, self.z as f64)
     }
 
+    /// Casts all elements of `self` to `i16`.
+    #[inline]
+    #[must_use]
+    pub fn as_i16vec3(&self) -> crate::I16Vec3 {
+        crate::I16Vec3::new(self.x as i16, self.y as i16, self.z as i16)
+    }
+
+    /// Casts all elements of `self` to `u16`.
+    #[inline]
+    #[must_use]
+    pub fn as_u16vec3(&self) -> crate::U16Vec3 {
+        crate::U16Vec3::new(self.x as u16, self.y as u16, self.z as u16)
+    }
+
     /// Casts all elements of `self` to `i32`.
     #[inline]
+    #[must_use]
     pub fn as_ivec3(&self) -> crate::IVec3 {
         crate::IVec3::new(self.x as i32, self.y as i32, self.z as i32)
     }
 
     /// Casts all elements of `self` to `u32`.
     #[inline]
+    #[must_use]
     pub fn as_uvec3(&self) -> crate::UVec3 {
         crate::UVec3::new(self.x as u32, self.y as u32, self.z as u32)
     }
+
+    /// Casts all elements of `self` to `i64`.
+    #[inline]
+    #[must_use]
+    pub fn as_i64vec3(&self) -> crate::I64Vec3 {
+        crate::I64Vec3::new(self.x as i64, self.y as i64, self.z as i64)
+    }
+
+    /// Casts all elements of `self` to `u64`.
+    #[inline]
+    #[must_use]
+    pub fn as_u64vec3(&self) -> crate::U64Vec3 {
+        crate::U64Vec3::new(self.x as u64, self.y as u64, self.z as u64)
+    }
 }
 
 impl Default for Vec3A {
@@ -1167,7 +1300,7 @@
 }
 
 impl From<Vec4> for Vec3A {
-    /// Creates a `Vec3A` from the `x`, `y` and `z` elements of `self` discarding `w`.
+    /// Creates a [`Vec3A`] from the `x`, `y` and `z` elements of `self` discarding `w`.
     ///
     /// On architectures where SIMD is supported such as SSE2 on `x86_64` this conversion is a noop.
     #[inline]
diff --git a/src/f32/scalar/vec4.rs b/src/f32/scalar/vec4.rs
index 17c84a4..499c3cc 100644
--- a/src/f32/scalar/vec4.rs
+++ b/src/f32/scalar/vec4.rs
@@ -1,18 +1,19 @@
 // Generated from vec.rs.tera template. Edit the template, not the generated file.
 
-use crate::{BVec4, Vec2, Vec3, Vec3A};
+#[cfg(feature = "scalar-math")]
+use crate::BVec4 as BVec4A;
+#[cfg(not(feature = "scalar-math"))]
+use crate::BVec4A;
+use crate::{f32::math, Vec2, Vec3, Vec3A};
 
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
 use core::iter::{Product, Sum};
 use core::{f32, ops::*};
 
-#[cfg(feature = "libm")]
-#[allow(unused_imports)]
-use num_traits::Float;
-
 /// Creates a 4-dimensional vector.
 #[inline(always)]
+#[must_use]
 pub const fn vec4(x: f32, y: f32, z: f32, w: f32) -> Vec4 {
     Vec4::new(x, y, z, w)
 }
@@ -45,31 +46,43 @@
     /// All negative ones.
     pub const NEG_ONE: Self = Self::splat(-1.0);
 
-    /// All NAN.
+    /// All `f32::MIN`.
+    pub const MIN: Self = Self::splat(f32::MIN);
+
+    /// All `f32::MAX`.
+    pub const MAX: Self = Self::splat(f32::MAX);
+
+    /// All `f32::NAN`.
     pub const NAN: Self = Self::splat(f32::NAN);
 
-    /// A unit-length vector pointing along the positive X axis.
+    /// All `f32::INFINITY`.
+    pub const INFINITY: Self = Self::splat(f32::INFINITY);
+
+    /// All `f32::NEG_INFINITY`.
+    pub const NEG_INFINITY: Self = Self::splat(f32::NEG_INFINITY);
+
+    /// A unit vector pointing along the positive X axis.
     pub const X: Self = Self::new(1.0, 0.0, 0.0, 0.0);
 
-    /// A unit-length vector pointing along the positive Y axis.
+    /// A unit vector pointing along the positive Y axis.
     pub const Y: Self = Self::new(0.0, 1.0, 0.0, 0.0);
 
-    /// A unit-length vector pointing along the positive Z axis.
+    /// A unit vector pointing along the positive Z axis.
     pub const Z: Self = Self::new(0.0, 0.0, 1.0, 0.0);
 
-    /// A unit-length vector pointing along the positive W axis.
+    /// A unit vector pointing along the positive W axis.
     pub const W: Self = Self::new(0.0, 0.0, 0.0, 1.0);
 
-    /// A unit-length vector pointing along the negative X axis.
+    /// A unit vector pointing along the negative X axis.
     pub const NEG_X: Self = Self::new(-1.0, 0.0, 0.0, 0.0);
 
-    /// A unit-length vector pointing along the negative Y axis.
+    /// A unit vector pointing along the negative Y axis.
     pub const NEG_Y: Self = Self::new(0.0, -1.0, 0.0, 0.0);
 
-    /// A unit-length vector pointing along the negative Z axis.
+    /// A unit vector pointing along the negative Z axis.
     pub const NEG_Z: Self = Self::new(0.0, 0.0, -1.0, 0.0);
 
-    /// A unit-length vector pointing along the negative W axis.
+    /// A unit vector pointing along the negative W axis.
     pub const NEG_W: Self = Self::new(0.0, 0.0, 0.0, -1.0);
 
     /// The unit axes.
@@ -77,12 +90,14 @@
 
     /// Creates a new vector.
     #[inline(always)]
+    #[must_use]
     pub const fn new(x: f32, y: f32, z: f32, w: f32) -> Self {
         Self { x, y, z, w }
     }
 
     /// Creates a vector with all elements set to `v`.
     #[inline]
+    #[must_use]
     pub const fn splat(v: f32) -> Self {
         Self {
             x: v,
@@ -101,23 +116,26 @@
     /// A true element in the mask uses the corresponding element from `if_true`, and false
     /// uses the element from `if_false`.
     #[inline]
-    pub fn select(mask: BVec4, if_true: Self, if_false: Self) -> Self {
+    #[must_use]
+    pub fn select(mask: BVec4A, if_true: Self, if_false: Self) -> Self {
         Self {
-            x: if mask.x { if_true.x } else { if_false.x },
-            y: if mask.y { if_true.y } else { if_false.y },
-            z: if mask.z { if_true.z } else { if_false.z },
-            w: if mask.w { if_true.w } else { if_false.w },
+            x: if mask.test(0) { if_true.x } else { if_false.x },
+            y: if mask.test(1) { if_true.y } else { if_false.y },
+            z: if mask.test(2) { if_true.z } else { if_false.z },
+            w: if mask.test(3) { if_true.w } else { if_false.w },
         }
     }
 
     /// Creates a new vector from an array.
     #[inline]
+    #[must_use]
     pub const fn from_array(a: [f32; 4]) -> Self {
         Self::new(a[0], a[1], a[2], a[3])
     }
 
     /// `[x, y, z, w]`
     #[inline]
+    #[must_use]
     pub const fn to_array(&self) -> [f32; 4] {
         [self.x, self.y, self.z, self.w]
     }
@@ -128,6 +146,7 @@
     ///
     /// Panics if `slice` is less than 4 elements long.
     #[inline]
+    #[must_use]
     pub const fn from_slice(slice: &[f32]) -> Self {
         Self::new(slice[0], slice[1], slice[2], slice[3])
     }
@@ -145,12 +164,13 @@
         slice[3] = self.w;
     }
 
-    /// Creates a 2D vector from the `x`, `y` and `z` elements of `self`, discarding `w`.
+    /// Creates a 3D vector from the `x`, `y` and `z` elements of `self`, discarding `w`.
     ///
-    /// Truncation to `Vec3` may also be performed by using `self.xyz()` or `Vec3::from()`.
+    /// Truncation to [`Vec3`] may also be performed by using [`self.xyz()`][crate::swizzles::Vec4Swizzles::xyz()].
     ///
-    /// To truncate to `Vec3A` use `Vec3A::from()`.
+    /// To truncate to [`Vec3A`] use [`Vec3A::from()`].
     #[inline]
+    #[must_use]
     pub fn truncate(self) -> Vec3 {
         use crate::swizzles::Vec4Swizzles;
         self.xyz()
@@ -158,12 +178,14 @@
 
     /// Computes the dot product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn dot(self, rhs: Self) -> f32 {
         (self.x * rhs.x) + (self.y * rhs.y) + (self.z * rhs.z) + (self.w * rhs.w)
     }
 
     /// Returns a vector where every component is the dot product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn dot_into_vec(self, rhs: Self) -> Self {
         Self::splat(self.dot(rhs))
     }
@@ -172,6 +194,7 @@
     ///
     /// In other words this computes `[self.x.min(rhs.x), self.y.min(rhs.y), ..]`.
     #[inline]
+    #[must_use]
     pub fn min(self, rhs: Self) -> Self {
         Self {
             x: self.x.min(rhs.x),
@@ -185,6 +208,7 @@
     ///
     /// In other words this computes `[self.x.max(rhs.x), self.y.max(rhs.y), ..]`.
     #[inline]
+    #[must_use]
     pub fn max(self, rhs: Self) -> Self {
         Self {
             x: self.x.max(rhs.x),
@@ -202,6 +226,7 @@
     ///
     /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn clamp(self, min: Self, max: Self) -> Self {
         glam_assert!(min.cmple(max).all(), "clamp: expected min <= max");
         self.max(min).min(max)
@@ -211,6 +236,7 @@
     ///
     /// In other words this computes `min(x, y, ..)`.
     #[inline]
+    #[must_use]
     pub fn min_element(self) -> f32 {
         self.x.min(self.y.min(self.z.min(self.w)))
     }
@@ -219,6 +245,7 @@
     ///
     /// In other words this computes `max(x, y, ..)`.
     #[inline]
+    #[must_use]
     pub fn max_element(self) -> f32 {
         self.x.max(self.y.max(self.z.max(self.w)))
     }
@@ -229,8 +256,9 @@
     /// In other words, this computes `[self.x == rhs.x, self.y == rhs.y, ..]` for all
     /// elements.
     #[inline]
-    pub fn cmpeq(self, rhs: Self) -> BVec4 {
-        BVec4::new(
+    #[must_use]
+    pub fn cmpeq(self, rhs: Self) -> BVec4A {
+        BVec4A::new(
             self.x.eq(&rhs.x),
             self.y.eq(&rhs.y),
             self.z.eq(&rhs.z),
@@ -244,8 +272,9 @@
     /// In other words this computes `[self.x != rhs.x, self.y != rhs.y, ..]` for all
     /// elements.
     #[inline]
-    pub fn cmpne(self, rhs: Self) -> BVec4 {
-        BVec4::new(
+    #[must_use]
+    pub fn cmpne(self, rhs: Self) -> BVec4A {
+        BVec4A::new(
             self.x.ne(&rhs.x),
             self.y.ne(&rhs.y),
             self.z.ne(&rhs.z),
@@ -259,8 +288,9 @@
     /// In other words this computes `[self.x >= rhs.x, self.y >= rhs.y, ..]` for all
     /// elements.
     #[inline]
-    pub fn cmpge(self, rhs: Self) -> BVec4 {
-        BVec4::new(
+    #[must_use]
+    pub fn cmpge(self, rhs: Self) -> BVec4A {
+        BVec4A::new(
             self.x.ge(&rhs.x),
             self.y.ge(&rhs.y),
             self.z.ge(&rhs.z),
@@ -274,8 +304,9 @@
     /// In other words this computes `[self.x > rhs.x, self.y > rhs.y, ..]` for all
     /// elements.
     #[inline]
-    pub fn cmpgt(self, rhs: Self) -> BVec4 {
-        BVec4::new(
+    #[must_use]
+    pub fn cmpgt(self, rhs: Self) -> BVec4A {
+        BVec4A::new(
             self.x.gt(&rhs.x),
             self.y.gt(&rhs.y),
             self.z.gt(&rhs.z),
@@ -289,8 +320,9 @@
     /// In other words this computes `[self.x <= rhs.x, self.y <= rhs.y, ..]` for all
     /// elements.
     #[inline]
-    pub fn cmple(self, rhs: Self) -> BVec4 {
-        BVec4::new(
+    #[must_use]
+    pub fn cmple(self, rhs: Self) -> BVec4A {
+        BVec4A::new(
             self.x.le(&rhs.x),
             self.y.le(&rhs.y),
             self.z.le(&rhs.z),
@@ -304,8 +336,9 @@
     /// In other words this computes `[self.x < rhs.x, self.y < rhs.y, ..]` for all
     /// elements.
     #[inline]
-    pub fn cmplt(self, rhs: Self) -> BVec4 {
-        BVec4::new(
+    #[must_use]
+    pub fn cmplt(self, rhs: Self) -> BVec4A {
+        BVec4A::new(
             self.x.lt(&rhs.x),
             self.y.lt(&rhs.y),
             self.z.lt(&rhs.z),
@@ -315,12 +348,13 @@
 
     /// Returns a vector containing the absolute value of each element of `self`.
     #[inline]
+    #[must_use]
     pub fn abs(self) -> Self {
         Self {
-            x: self.x.abs(),
-            y: self.y.abs(),
-            z: self.z.abs(),
-            w: self.w.abs(),
+            x: math::abs(self.x),
+            y: math::abs(self.y),
+            z: math::abs(self.z),
+            w: math::abs(self.w),
         }
     }
 
@@ -330,23 +364,25 @@
     /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
     /// - `NAN` if the number is `NAN`
     #[inline]
+    #[must_use]
     pub fn signum(self) -> Self {
         Self {
-            x: self.x.signum(),
-            y: self.y.signum(),
-            z: self.z.signum(),
-            w: self.w.signum(),
+            x: math::signum(self.x),
+            y: math::signum(self.y),
+            z: math::signum(self.z),
+            w: math::signum(self.w),
         }
     }
 
     /// Returns a vector with signs of `rhs` and the magnitudes of `self`.
     #[inline]
+    #[must_use]
     pub fn copysign(self, rhs: Self) -> Self {
         Self {
-            x: self.x.copysign(rhs.x),
-            y: self.y.copysign(rhs.y),
-            z: self.z.copysign(rhs.z),
-            w: self.w.copysign(rhs.w),
+            x: math::copysign(self.x, rhs.x),
+            y: math::copysign(self.y, rhs.y),
+            z: math::copysign(self.z, rhs.z),
+            w: math::copysign(self.w, rhs.w),
         }
     }
 
@@ -355,6 +391,7 @@
     /// A negative element results in a `1` bit and a positive element in a `0` bit.  Element `x` goes
     /// into the first lowest bit, element `y` into the second, etc.
     #[inline]
+    #[must_use]
     pub fn is_negative_bitmask(self) -> u32 {
         (self.x.is_sign_negative() as u32)
             | (self.y.is_sign_negative() as u32) << 1
@@ -365,12 +402,14 @@
     /// Returns `true` if, and only if, all elements are finite.  If any element is either
     /// `NaN`, positive or negative infinity, this will return `false`.
     #[inline]
+    #[must_use]
     pub fn is_finite(self) -> bool {
         self.x.is_finite() && self.y.is_finite() && self.z.is_finite() && self.w.is_finite()
     }
 
     /// Returns `true` if any elements are `NaN`.
     #[inline]
+    #[must_use]
     pub fn is_nan(self) -> bool {
         self.x.is_nan() || self.y.is_nan() || self.z.is_nan() || self.w.is_nan()
     }
@@ -379,8 +418,9 @@
     ///
     /// In other words, this computes `[x.is_nan(), y.is_nan(), z.is_nan(), w.is_nan()]`.
     #[inline]
-    pub fn is_nan_mask(self) -> BVec4 {
-        BVec4::new(
+    #[must_use]
+    pub fn is_nan_mask(self) -> BVec4A {
+        BVec4A::new(
             self.x.is_nan(),
             self.y.is_nan(),
             self.z.is_nan(),
@@ -391,8 +431,9 @@
     /// Computes the length of `self`.
     #[doc(alias = "magnitude")]
     #[inline]
+    #[must_use]
     pub fn length(self) -> f32 {
-        self.dot(self).sqrt()
+        math::sqrt(self.dot(self))
     }
 
     /// Computes the squared length of `self`.
@@ -400,6 +441,7 @@
     /// This is faster than `length()` as it avoids a square root operation.
     #[doc(alias = "magnitude2")]
     #[inline]
+    #[must_use]
     pub fn length_squared(self) -> f32 {
         self.dot(self)
     }
@@ -408,33 +450,62 @@
     ///
     /// For valid results, `self` must _not_ be of length zero.
     #[inline]
+    #[must_use]
     pub fn length_recip(self) -> f32 {
         self.length().recip()
     }
 
     /// Computes the Euclidean distance between two points in space.
     #[inline]
+    #[must_use]
     pub fn distance(self, rhs: Self) -> f32 {
         (self - rhs).length()
     }
 
     /// Compute the squared euclidean distance between two points in space.
     #[inline]
+    #[must_use]
     pub fn distance_squared(self, rhs: Self) -> f32 {
         (self - rhs).length_squared()
     }
 
+    /// Returns the element-wise quotient of [Euclidean division] of `self` by `rhs`.
+    #[inline]
+    #[must_use]
+    pub fn div_euclid(self, rhs: Self) -> Self {
+        Self::new(
+            math::div_euclid(self.x, rhs.x),
+            math::div_euclid(self.y, rhs.y),
+            math::div_euclid(self.z, rhs.z),
+            math::div_euclid(self.w, rhs.w),
+        )
+    }
+
+    /// Returns the element-wise remainder of [Euclidean division] of `self` by `rhs`.
+    ///
+    /// [Euclidean division]: f32::rem_euclid
+    #[inline]
+    #[must_use]
+    pub fn rem_euclid(self, rhs: Self) -> Self {
+        Self::new(
+            math::rem_euclid(self.x, rhs.x),
+            math::rem_euclid(self.y, rhs.y),
+            math::rem_euclid(self.z, rhs.z),
+            math::rem_euclid(self.w, rhs.w),
+        )
+    }
+
     /// Returns `self` normalized to length 1.0.
     ///
     /// For valid results, `self` must _not_ be of length zero, nor very close to zero.
     ///
-    /// See also [`Self::try_normalize`] and [`Self::normalize_or_zero`].
+    /// See also [`Self::try_normalize()`] and [`Self::normalize_or_zero()`].
     ///
     /// Panics
     ///
     /// Will panic if `self` is zero length when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn normalize(self) -> Self {
         #[allow(clippy::let_and_return)]
         let normalized = self.mul(self.length_recip());
@@ -447,9 +518,9 @@
     /// In particular, if the input is zero (or very close to zero), or non-finite,
     /// the result of this operation will be `None`.
     ///
-    /// See also [`Self::normalize_or_zero`].
-    #[must_use]
+    /// See also [`Self::normalize_or_zero()`].
     #[inline]
+    #[must_use]
     pub fn try_normalize(self) -> Option<Self> {
         let rcp = self.length_recip();
         if rcp.is_finite() && rcp > 0.0 {
@@ -464,9 +535,9 @@
     /// In particular, if the input is zero (or very close to zero), or non-finite,
     /// the result of this operation will be zero.
     ///
-    /// See also [`Self::try_normalize`].
-    #[must_use]
+    /// See also [`Self::try_normalize()`].
     #[inline]
+    #[must_use]
     pub fn normalize_or_zero(self) -> Self {
         let rcp = self.length_recip();
         if rcp.is_finite() && rcp > 0.0 {
@@ -480,9 +551,10 @@
     ///
     /// Uses a precision threshold of `1e-6`.
     #[inline]
+    #[must_use]
     pub fn is_normalized(self) -> bool {
         // TODO: do something with epsilon
-        (self.length_squared() - 1.0).abs() <= 1e-4
+        math::abs(self.length_squared() - 1.0) <= 1e-4
     }
 
     /// Returns the vector projection of `self` onto `rhs`.
@@ -492,8 +564,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` is zero length when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn project_onto(self, rhs: Self) -> Self {
         let other_len_sq_rcp = rhs.dot(rhs).recip();
         glam_assert!(other_len_sq_rcp.is_finite());
@@ -510,8 +582,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` has a length of zero when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn reject_from(self, rhs: Self) -> Self {
         self - self.project_onto(rhs)
     }
@@ -523,8 +595,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` is not normalized when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn project_onto_normalized(self, rhs: Self) -> Self {
         glam_assert!(rhs.is_normalized());
         rhs * self.dot(rhs)
@@ -540,8 +612,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` is not normalized when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn reject_from_normalized(self, rhs: Self) -> Self {
         self - self.project_onto_normalized(rhs)
     }
@@ -549,36 +621,52 @@
     /// Returns a vector containing the nearest integer to a number for each element of `self`.
     /// Round half-way cases away from 0.0.
     #[inline]
+    #[must_use]
     pub fn round(self) -> Self {
         Self {
-            x: self.x.round(),
-            y: self.y.round(),
-            z: self.z.round(),
-            w: self.w.round(),
+            x: math::round(self.x),
+            y: math::round(self.y),
+            z: math::round(self.z),
+            w: math::round(self.w),
         }
     }
 
     /// Returns a vector containing the largest integer less than or equal to a number for each
     /// element of `self`.
     #[inline]
+    #[must_use]
     pub fn floor(self) -> Self {
         Self {
-            x: self.x.floor(),
-            y: self.y.floor(),
-            z: self.z.floor(),
-            w: self.w.floor(),
+            x: math::floor(self.x),
+            y: math::floor(self.y),
+            z: math::floor(self.z),
+            w: math::floor(self.w),
         }
     }
 
     /// Returns a vector containing the smallest integer greater than or equal to a number for
     /// each element of `self`.
     #[inline]
+    #[must_use]
     pub fn ceil(self) -> Self {
         Self {
-            x: self.x.ceil(),
-            y: self.y.ceil(),
-            z: self.z.ceil(),
-            w: self.w.ceil(),
+            x: math::ceil(self.x),
+            y: math::ceil(self.y),
+            z: math::ceil(self.z),
+            w: math::ceil(self.w),
+        }
+    }
+
+    /// Returns a vector containing the integer part each element of `self`. This means numbers are
+    /// always truncated towards zero.
+    #[inline]
+    #[must_use]
+    pub fn trunc(self) -> Self {
+        Self {
+            x: math::trunc(self.x),
+            y: math::trunc(self.y),
+            z: math::trunc(self.z),
+            w: math::trunc(self.w),
         }
     }
 
@@ -587,6 +675,7 @@
     ///
     /// Note that this is fast but not precise for large numbers.
     #[inline]
+    #[must_use]
     pub fn fract(self) -> Self {
         self - self.floor()
     }
@@ -594,29 +683,37 @@
     /// Returns a vector containing `e^self` (the exponential function) for each element of
     /// `self`.
     #[inline]
+    #[must_use]
     pub fn exp(self) -> Self {
-        Self::new(self.x.exp(), self.y.exp(), self.z.exp(), self.w.exp())
+        Self::new(
+            math::exp(self.x),
+            math::exp(self.y),
+            math::exp(self.z),
+            math::exp(self.w),
+        )
     }
 
     /// Returns a vector containing each element of `self` raised to the power of `n`.
     #[inline]
+    #[must_use]
     pub fn powf(self, n: f32) -> Self {
         Self::new(
-            self.x.powf(n),
-            self.y.powf(n),
-            self.z.powf(n),
-            self.w.powf(n),
+            math::powf(self.x, n),
+            math::powf(self.y, n),
+            math::powf(self.z, n),
+            math::powf(self.w, n),
         )
     }
 
     /// Returns a vector containing the reciprocal `1.0/n` of each element of `self`.
     #[inline]
+    #[must_use]
     pub fn recip(self) -> Self {
         Self {
-            x: self.x.recip(),
-            y: self.y.recip(),
-            z: self.z.recip(),
-            w: self.w.recip(),
+            x: 1.0 / self.x,
+            y: 1.0 / self.y,
+            z: 1.0 / self.z,
+            w: 1.0 / self.w,
         }
     }
 
@@ -627,6 +724,7 @@
     /// extrapolated.
     #[doc(alias = "mix")]
     #[inline]
+    #[must_use]
     pub fn lerp(self, rhs: Self, s: f32) -> Self {
         self + ((rhs - self) * s)
     }
@@ -641,6 +739,7 @@
     /// For more see
     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
     #[inline]
+    #[must_use]
     pub fn abs_diff_eq(self, rhs: Self, max_abs_diff: f32) -> bool {
         self.sub(rhs).abs().cmple(Self::splat(max_abs_diff)).all()
     }
@@ -651,33 +750,38 @@
     ///
     /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn clamp_length(self, min: f32, max: f32) -> Self {
         glam_assert!(min <= max);
         let length_sq = self.length_squared();
         if length_sq < min * min {
-            self * (length_sq.sqrt().recip() * min)
+            min * (self / math::sqrt(length_sq))
         } else if length_sq > max * max {
-            self * (length_sq.sqrt().recip() * max)
+            max * (self / math::sqrt(length_sq))
         } else {
             self
         }
     }
 
     /// Returns a vector with a length no more than `max`
+    #[inline]
+    #[must_use]
     pub fn clamp_length_max(self, max: f32) -> Self {
         let length_sq = self.length_squared();
         if length_sq > max * max {
-            self * (length_sq.sqrt().recip() * max)
+            max * (self / math::sqrt(length_sq))
         } else {
             self
         }
     }
 
     /// Returns a vector with a length no less than `min`
+    #[inline]
+    #[must_use]
     pub fn clamp_length_min(self, min: f32) -> Self {
         let length_sq = self.length_squared();
         if length_sq < min * min {
-            self * (length_sq.sqrt().recip() * min)
+            min * (self / math::sqrt(length_sq))
         } else {
             self
         }
@@ -691,32 +795,64 @@
     /// and will be heavily dependant on designing algorithms with specific target hardware in
     /// mind.
     #[inline]
+    #[must_use]
     pub fn mul_add(self, a: Self, b: Self) -> Self {
         Self::new(
-            self.x.mul_add(a.x, b.x),
-            self.y.mul_add(a.y, b.y),
-            self.z.mul_add(a.z, b.z),
-            self.w.mul_add(a.w, b.w),
+            math::mul_add(self.x, a.x, b.x),
+            math::mul_add(self.y, a.y, b.y),
+            math::mul_add(self.z, a.z, b.z),
+            math::mul_add(self.w, a.w, b.w),
         )
     }
 
     /// Casts all elements of `self` to `f64`.
     #[inline]
+    #[must_use]
     pub fn as_dvec4(&self) -> crate::DVec4 {
         crate::DVec4::new(self.x as f64, self.y as f64, self.z as f64, self.w as f64)
     }
 
+    /// Casts all elements of `self` to `i16`.
+    #[inline]
+    #[must_use]
+    pub fn as_i16vec4(&self) -> crate::I16Vec4 {
+        crate::I16Vec4::new(self.x as i16, self.y as i16, self.z as i16, self.w as i16)
+    }
+
+    /// Casts all elements of `self` to `u16`.
+    #[inline]
+    #[must_use]
+    pub fn as_u16vec4(&self) -> crate::U16Vec4 {
+        crate::U16Vec4::new(self.x as u16, self.y as u16, self.z as u16, self.w as u16)
+    }
+
     /// Casts all elements of `self` to `i32`.
     #[inline]
+    #[must_use]
     pub fn as_ivec4(&self) -> crate::IVec4 {
         crate::IVec4::new(self.x as i32, self.y as i32, self.z as i32, self.w as i32)
     }
 
     /// Casts all elements of `self` to `u32`.
     #[inline]
+    #[must_use]
     pub fn as_uvec4(&self) -> crate::UVec4 {
         crate::UVec4::new(self.x as u32, self.y as u32, self.z as u32, self.w as u32)
     }
+
+    /// Casts all elements of `self` to `i64`.
+    #[inline]
+    #[must_use]
+    pub fn as_i64vec4(&self) -> crate::I64Vec4 {
+        crate::I64Vec4::new(self.x as i64, self.y as i64, self.z as i64, self.w as i64)
+    }
+
+    /// Casts all elements of `self` to `u64`.
+    #[inline]
+    #[must_use]
+    pub fn as_u64vec4(&self) -> crate::U64Vec4 {
+        crate::U64Vec4::new(self.x as u64, self.y as u64, self.z as u64, self.w as u64)
+    }
 }
 
 impl Default for Vec4 {
diff --git a/src/f32/sse2/mat2.rs b/src/f32/sse2/mat2.rs
index 0222bdd..ab63731 100644
--- a/src/f32/sse2/mat2.rs
+++ b/src/f32/sse2/mat2.rs
@@ -1,6 +1,6 @@
 // Generated from mat.rs.tera template. Edit the template, not the generated file.
 
-use crate::{swizzles::*, DMat2, Mat3, Mat3A, Vec2};
+use crate::{f32::math, swizzles::*, DMat2, Mat3, Mat3A, Vec2};
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
 use core::iter::{Product, Sum};
@@ -11,22 +11,24 @@
 #[cfg(target_arch = "x86_64")]
 use core::arch::x86_64::*;
 
-#[cfg(feature = "libm")]
-#[allow(unused_imports)]
-use num_traits::Float;
-
+#[repr(C)]
 union UnionCast {
     a: [f32; 4],
     v: Mat2,
 }
 
-/// Creates a 2x2 matrix from column vectors.
+/// Creates a 2x2 matrix from two column vectors.
 #[inline(always)]
+#[must_use]
 pub const fn mat2(x_axis: Vec2, y_axis: Vec2) -> Mat2 {
     Mat2::from_cols(x_axis, y_axis)
 }
 
 /// A 2x2 column major matrix.
+///
+/// SIMD vector types are used for storage on supported platforms.
+///
+/// This type is 16 byte aligned.
 #[derive(Clone, Copy)]
 #[repr(transparent)]
 pub struct Mat2(pub(crate) __m128);
@@ -43,6 +45,7 @@
 
     #[allow(clippy::too_many_arguments)]
     #[inline(always)]
+    #[must_use]
     const fn new(m00: f32, m01: f32, m10: f32, m11: f32) -> Self {
         unsafe {
             UnionCast {
@@ -54,6 +57,7 @@
 
     /// Creates a 2x2 matrix from two column vectors.
     #[inline(always)]
+    #[must_use]
     pub const fn from_cols(x_axis: Vec2, y_axis: Vec2) -> Self {
         unsafe {
             UnionCast {
@@ -67,6 +71,7 @@
     /// If your data is stored in row major you will need to `transpose` the returned
     /// matrix.
     #[inline]
+    #[must_use]
     pub const fn from_cols_array(m: &[f32; 4]) -> Self {
         Self::new(m[0], m[1], m[2], m[3])
     }
@@ -74,6 +79,7 @@
     /// Creates a `[f32; 4]` array storing data in column major order.
     /// If you require data in row major order `transpose` the matrix first.
     #[inline]
+    #[must_use]
     pub const fn to_cols_array(&self) -> [f32; 4] {
         unsafe { *(self as *const Self as *const [f32; 4]) }
     }
@@ -82,6 +88,7 @@
     /// If your data is in row major order you will need to `transpose` the returned
     /// matrix.
     #[inline]
+    #[must_use]
     pub const fn from_cols_array_2d(m: &[[f32; 2]; 2]) -> Self {
         Self::from_cols(Vec2::from_array(m[0]), Vec2::from_array(m[1]))
     }
@@ -89,6 +96,7 @@
     /// Creates a `[[f32; 2]; 2]` 2D array storing data in column major order.
     /// If you require data in row major order `transpose` the matrix first.
     #[inline]
+    #[must_use]
     pub const fn to_cols_array_2d(&self) -> [[f32; 2]; 2] {
         unsafe { *(self as *const Self as *const [[f32; 2]; 2]) }
     }
@@ -96,6 +104,7 @@
     /// Creates a 2x2 matrix with its diagonal set to `diagonal` and all other entries set to 0.
     #[doc(alias = "scale")]
     #[inline]
+    #[must_use]
     pub const fn from_diagonal(diagonal: Vec2) -> Self {
         Self::new(diagonal.x, 0.0, 0.0, diagonal.y)
     }
@@ -103,26 +112,30 @@
     /// Creates a 2x2 matrix containing the combining non-uniform `scale` and rotation of
     /// `angle` (in radians).
     #[inline]
+    #[must_use]
     pub fn from_scale_angle(scale: Vec2, angle: f32) -> Self {
-        let (sin, cos) = angle.sin_cos();
+        let (sin, cos) = math::sin_cos(angle);
         Self::new(cos * scale.x, sin * scale.x, -sin * scale.y, cos * scale.y)
     }
 
     /// Creates a 2x2 matrix containing a rotation of `angle` (in radians).
     #[inline]
+    #[must_use]
     pub fn from_angle(angle: f32) -> Self {
-        let (sin, cos) = angle.sin_cos();
+        let (sin, cos) = math::sin_cos(angle);
         Self::new(cos, sin, -sin, cos)
     }
 
     /// Creates a 2x2 matrix from a 3x3 matrix, discarding the 2nd row and column.
     #[inline]
+    #[must_use]
     pub fn from_mat3(m: Mat3) -> Self {
         Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
     }
 
     /// 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())
     }
@@ -133,6 +146,7 @@
     ///
     /// Panics if `slice` is less than 4 elements long.
     #[inline]
+    #[must_use]
     pub const fn from_cols_slice(slice: &[f32]) -> Self {
         Self::new(slice[0], slice[1], slice[2], slice[3])
     }
@@ -156,6 +170,7 @@
     ///
     /// Panics if `index` is greater than 1.
     #[inline]
+    #[must_use]
     pub fn col(&self, index: usize) -> Vec2 {
         match index {
             0 => self.x_axis,
@@ -184,6 +199,7 @@
     ///
     /// Panics if `index` is greater than 1.
     #[inline]
+    #[must_use]
     pub fn row(&self, index: usize) -> Vec2 {
         match index {
             0 => Vec2::new(self.x_axis.x, self.y_axis.x),
@@ -195,25 +211,28 @@
     /// Returns `true` if, and only if, all elements are finite.
     /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
     #[inline]
+    #[must_use]
     pub fn is_finite(&self) -> bool {
         self.x_axis.is_finite() && self.y_axis.is_finite()
     }
 
     /// Returns `true` if any elements are `NaN`.
     #[inline]
+    #[must_use]
     pub fn is_nan(&self) -> bool {
         self.x_axis.is_nan() || self.y_axis.is_nan()
     }
 
     /// Returns the transpose of `self`.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn transpose(&self) -> Self {
         Self(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_01_10_00) })
     }
 
     /// Returns the determinant of `self`.
     #[inline]
+    #[must_use]
     pub fn determinant(&self) -> f32 {
         unsafe {
             let abcd = self.0;
@@ -231,8 +250,8 @@
     /// # Panics
     ///
     /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn inverse(&self) -> Self {
         unsafe {
             const SIGN: __m128 = crate::sse2::m128_from_f32x4([1.0, -1.0, -1.0, 1.0]);
@@ -250,6 +269,7 @@
 
     /// Transforms a 2D vector.
     #[inline]
+    #[must_use]
     pub fn mul_vec2(&self, rhs: Vec2) -> Vec2 {
         unsafe {
             use crate::Align16;
@@ -267,6 +287,7 @@
 
     /// Multiplies two 2x2 matrices.
     #[inline]
+    #[must_use]
     pub fn mul_mat2(&self, rhs: &Self) -> Self {
         unsafe {
             let abcd = self.0;
@@ -285,18 +306,21 @@
 
     /// Adds two 2x2 matrices.
     #[inline]
+    #[must_use]
     pub fn add_mat2(&self, rhs: &Self) -> Self {
         Self(unsafe { _mm_add_ps(self.0, rhs.0) })
     }
 
     /// Subtracts two 2x2 matrices.
     #[inline]
+    #[must_use]
     pub fn sub_mat2(&self, rhs: &Self) -> Self {
         Self(unsafe { _mm_sub_ps(self.0, rhs.0) })
     }
 
     /// Multiplies a 2x2 matrix by a scalar.
     #[inline]
+    #[must_use]
     pub fn mul_scalar(&self, rhs: f32) -> Self {
         Self(unsafe { _mm_mul_ps(self.0, _mm_set_ps1(rhs)) })
     }
@@ -311,6 +335,7 @@
     /// For more see
     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
     #[inline]
+    #[must_use]
     pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
         self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
             && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
diff --git a/src/f32/sse2/mat3a.rs b/src/f32/sse2/mat3a.rs
index 14912dd..56f762e 100644
--- a/src/f32/sse2/mat3a.rs
+++ b/src/f32/sse2/mat3a.rs
@@ -1,6 +1,6 @@
 // Generated from mat.rs.tera template. Edit the template, not the generated file.
 
-use crate::{swizzles::*, DMat3, EulerRot, Mat2, Mat3, Mat4, Quat, Vec2, Vec3, Vec3A};
+use crate::{f32::math, swizzles::*, DMat3, EulerRot, Mat2, Mat3, Mat4, Quat, Vec2, Vec3, Vec3A};
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
 use core::iter::{Product, Sum};
@@ -11,12 +11,9 @@
 #[cfg(target_arch = "x86_64")]
 use core::arch::x86_64::*;
 
-#[cfg(feature = "libm")]
-#[allow(unused_imports)]
-use num_traits::Float;
-
-/// Creates a 3x3 matrix from column vectors.
+/// Creates a 3x3 matrix from three column vectors.
 #[inline(always)]
+#[must_use]
 pub const fn mat3a(x_axis: Vec3A, y_axis: Vec3A, z_axis: Vec3A) -> Mat3A {
     Mat3A::from_cols(x_axis, y_axis, z_axis)
 }
@@ -65,6 +62,7 @@
 
     #[allow(clippy::too_many_arguments)]
     #[inline(always)]
+    #[must_use]
     const fn new(
         m00: f32,
         m01: f32,
@@ -83,8 +81,9 @@
         }
     }
 
-    /// Creates a 3x3 matrix from two column vectors.
+    /// Creates a 3x3 matrix from three column vectors.
     #[inline(always)]
+    #[must_use]
     pub const fn from_cols(x_axis: Vec3A, y_axis: Vec3A, z_axis: Vec3A) -> Self {
         Self {
             x_axis,
@@ -97,6 +96,7 @@
     /// If your data is stored in row major you will need to `transpose` the returned
     /// matrix.
     #[inline]
+    #[must_use]
     pub const fn from_cols_array(m: &[f32; 9]) -> Self {
         Self::new(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8])
     }
@@ -104,6 +104,7 @@
     /// Creates a `[f32; 9]` array storing data in column major order.
     /// If you require data in row major order `transpose` the matrix first.
     #[inline]
+    #[must_use]
     pub const fn to_cols_array(&self) -> [f32; 9] {
         let [x_axis_x, x_axis_y, x_axis_z] = self.x_axis.to_array();
         let [y_axis_x, y_axis_y, y_axis_z] = self.y_axis.to_array();
@@ -119,6 +120,7 @@
     /// If your data is in row major order you will need to `transpose` the returned
     /// matrix.
     #[inline]
+    #[must_use]
     pub const fn from_cols_array_2d(m: &[[f32; 3]; 3]) -> Self {
         Self::from_cols(
             Vec3A::from_array(m[0]),
@@ -130,6 +132,7 @@
     /// Creates a `[[f32; 3]; 3]` 3D array storing data in column major order.
     /// If you require data in row major order `transpose` the matrix first.
     #[inline]
+    #[must_use]
     pub const fn to_cols_array_2d(&self) -> [[f32; 3]; 3] {
         [
             self.x_axis.to_array(),
@@ -141,6 +144,7 @@
     /// Creates a 3x3 matrix with its diagonal set to `diagonal` and all other entries set to 0.
     #[doc(alias = "scale")]
     #[inline]
+    #[must_use]
     pub const fn from_diagonal(diagonal: Vec3) -> Self {
         Self::new(
             diagonal.x, 0.0, 0.0, 0.0, diagonal.y, 0.0, 0.0, 0.0, diagonal.z,
@@ -148,6 +152,8 @@
     }
 
     /// Creates a 3x3 matrix from a 4x4 matrix, discarding the 4th row and column.
+    #[inline]
+    #[must_use]
     pub fn from_mat4(m: Mat4) -> Self {
         Self::from_cols(m.x_axis.into(), m.y_axis.into(), m.z_axis.into())
     }
@@ -158,6 +164,7 @@
     ///
     /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_quat(rotation: Quat) -> Self {
         glam_assert!(rotation.is_normalized());
 
@@ -188,10 +195,11 @@
     ///
     /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
         glam_assert!(axis.is_normalized());
 
-        let (sin, cos) = angle.sin_cos();
+        let (sin, cos) = math::sin_cos(angle);
         let (xsin, ysin, zsin) = axis.mul(sin).into();
         let (x, y, z) = axis.into();
         let (x2, y2, z2) = axis.mul(axis).into();
@@ -206,9 +214,10 @@
         )
     }
 
-    #[inline]
     /// Creates a 3D rotation matrix from the given euler rotation sequence and the angles (in
     /// radians).
+    #[inline]
+    #[must_use]
     pub fn from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self {
         let quat = Quat::from_euler(order, a, b, c);
         Self::from_quat(quat)
@@ -216,8 +225,9 @@
 
     /// Creates a 3D rotation matrix from `angle` (in radians) around the x axis.
     #[inline]
+    #[must_use]
     pub fn from_rotation_x(angle: f32) -> Self {
-        let (sina, cosa) = angle.sin_cos();
+        let (sina, cosa) = math::sin_cos(angle);
         Self::from_cols(
             Vec3A::X,
             Vec3A::new(0.0, cosa, sina),
@@ -227,8 +237,9 @@
 
     /// Creates a 3D rotation matrix from `angle` (in radians) around the y axis.
     #[inline]
+    #[must_use]
     pub fn from_rotation_y(angle: f32) -> Self {
-        let (sina, cosa) = angle.sin_cos();
+        let (sina, cosa) = math::sin_cos(angle);
         Self::from_cols(
             Vec3A::new(cosa, 0.0, -sina),
             Vec3A::Y,
@@ -238,8 +249,9 @@
 
     /// Creates a 3D rotation matrix from `angle` (in radians) around the z axis.
     #[inline]
+    #[must_use]
     pub fn from_rotation_z(angle: f32) -> Self {
-        let (sina, cosa) = angle.sin_cos();
+        let (sina, cosa) = math::sin_cos(angle);
         Self::from_cols(
             Vec3A::new(cosa, sina, 0.0),
             Vec3A::new(-sina, cosa, 0.0),
@@ -252,6 +264,7 @@
     /// The resulting matrix can be used to transform 2D points and vectors. See
     /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
     #[inline]
+    #[must_use]
     pub fn from_translation(translation: Vec2) -> Self {
         Self::from_cols(
             Vec3A::X,
@@ -266,8 +279,9 @@
     /// The resulting matrix can be used to transform 2D points and vectors. See
     /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
     #[inline]
+    #[must_use]
     pub fn from_angle(angle: f32) -> Self {
-        let (sin, cos) = angle.sin_cos();
+        let (sin, cos) = math::sin_cos(angle);
         Self::from_cols(
             Vec3A::new(cos, sin, 0.0),
             Vec3A::new(-sin, cos, 0.0),
@@ -281,8 +295,9 @@
     /// The resulting matrix can be used to transform 2D points and vectors. See
     /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
     #[inline]
+    #[must_use]
     pub fn from_scale_angle_translation(scale: Vec2, angle: f32, translation: Vec2) -> Self {
-        let (sin, cos) = angle.sin_cos();
+        let (sin, cos) = math::sin_cos(angle);
         Self::from_cols(
             Vec3A::new(cos * scale.x, sin * scale.x, 0.0),
             Vec3A::new(-sin * scale.y, cos * scale.y, 0.0),
@@ -299,6 +314,7 @@
     ///
     /// Will panic if all elements of `scale` are zero when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_scale(scale: Vec2) -> Self {
         // Do not panic as long as any component is non-zero
         glam_assert!(scale.cmpne(Vec2::ZERO).any());
@@ -325,6 +341,7 @@
     ///
     /// Panics if `slice` is less than 9 elements long.
     #[inline]
+    #[must_use]
     pub const fn from_cols_slice(slice: &[f32]) -> Self {
         Self::new(
             slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
@@ -356,6 +373,7 @@
     ///
     /// Panics if `index` is greater than 2.
     #[inline]
+    #[must_use]
     pub fn col(&self, index: usize) -> Vec3A {
         match index {
             0 => self.x_axis,
@@ -386,6 +404,7 @@
     ///
     /// Panics if `index` is greater than 2.
     #[inline]
+    #[must_use]
     pub fn row(&self, index: usize) -> Vec3A {
         match index {
             0 => Vec3A::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
@@ -398,19 +417,21 @@
     /// Returns `true` if, and only if, all elements are finite.
     /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
     #[inline]
+    #[must_use]
     pub fn is_finite(&self) -> bool {
         self.x_axis.is_finite() && self.y_axis.is_finite() && self.z_axis.is_finite()
     }
 
     /// Returns `true` if any elements are `NaN`.
     #[inline]
+    #[must_use]
     pub fn is_nan(&self) -> bool {
         self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan()
     }
 
     /// Returns the transpose of `self`.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn transpose(&self) -> Self {
         unsafe {
             let tmp0 = _mm_shuffle_ps(self.x_axis.0, self.y_axis.0, 0b01_00_01_00);
@@ -426,6 +447,7 @@
 
     /// Returns the determinant of `self`.
     #[inline]
+    #[must_use]
     pub fn determinant(&self) -> f32 {
         self.z_axis.dot(self.x_axis.cross(self.y_axis))
     }
@@ -437,8 +459,8 @@
     /// # Panics
     ///
     /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn inverse(&self) -> Self {
         let tmp0 = self.y_axis.cross(self.z_axis);
         let tmp1 = self.z_axis.cross(self.x_axis);
@@ -459,6 +481,7 @@
     ///
     /// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn transform_point2(&self, rhs: Vec2) -> Vec2 {
         glam_assert!(self.row(2).abs_diff_eq(Vec3A::Z, 1e-6));
         Mat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs + self.z_axis.xy()
@@ -474,6 +497,7 @@
     ///
     /// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn transform_vector2(&self, rhs: Vec2) -> Vec2 {
         glam_assert!(self.row(2).abs_diff_eq(Vec3A::Z, 1e-6));
         Mat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs
@@ -481,12 +505,14 @@
 
     /// Transforms a 3D vector.
     #[inline]
+    #[must_use]
     pub fn mul_vec3(&self, rhs: Vec3) -> Vec3 {
         self.mul_vec3a(rhs.into()).into()
     }
 
-    /// Transforms a `Vec3A`.
+    /// Transforms a [`Vec3A`].
     #[inline]
+    #[must_use]
     pub fn mul_vec3a(&self, rhs: Vec3A) -> Vec3A {
         let mut res = self.x_axis.mul(rhs.xxx());
         res = res.add(self.y_axis.mul(rhs.yyy()));
@@ -496,6 +522,7 @@
 
     /// Multiplies two 3x3 matrices.
     #[inline]
+    #[must_use]
     pub fn mul_mat3(&self, rhs: &Self) -> Self {
         Self::from_cols(
             self.mul(rhs.x_axis),
@@ -506,6 +533,7 @@
 
     /// Adds two 3x3 matrices.
     #[inline]
+    #[must_use]
     pub fn add_mat3(&self, rhs: &Self) -> Self {
         Self::from_cols(
             self.x_axis.add(rhs.x_axis),
@@ -516,6 +544,7 @@
 
     /// Subtracts two 3x3 matrices.
     #[inline]
+    #[must_use]
     pub fn sub_mat3(&self, rhs: &Self) -> Self {
         Self::from_cols(
             self.x_axis.sub(rhs.x_axis),
@@ -526,6 +555,7 @@
 
     /// Multiplies a 3x3 matrix by a scalar.
     #[inline]
+    #[must_use]
     pub fn mul_scalar(&self, rhs: f32) -> Self {
         Self::from_cols(
             self.x_axis.mul(rhs),
@@ -544,6 +574,7 @@
     /// For more see
     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
     #[inline]
+    #[must_use]
     pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
         self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
             && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
diff --git a/src/f32/sse2/mat4.rs b/src/f32/sse2/mat4.rs
index aa69493..490b981 100644
--- a/src/f32/sse2/mat4.rs
+++ b/src/f32/sse2/mat4.rs
@@ -1,6 +1,8 @@
 // Generated from mat.rs.tera template. Edit the template, not the generated file.
 
-use crate::{sse2::*, swizzles::*, DMat4, EulerRot, Mat3, Mat3A, Quat, Vec3, Vec3A, Vec4};
+use crate::{
+    f32::math, sse2::*, swizzles::*, DMat4, EulerRot, Mat3, Mat3A, Quat, Vec3, Vec3A, Vec4,
+};
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
 use core::iter::{Product, Sum};
@@ -11,12 +13,9 @@
 #[cfg(target_arch = "x86_64")]
 use core::arch::x86_64::*;
 
-#[cfg(feature = "libm")]
-#[allow(unused_imports)]
-use num_traits::Float;
-
-/// Creates a 4x4 matrix from column vectors.
+/// Creates a 4x4 matrix from four column vectors.
 #[inline(always)]
+#[must_use]
 pub const fn mat4(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Mat4 {
     Mat4::from_cols(x_axis, y_axis, z_axis, w_axis)
 }
@@ -32,7 +31,7 @@
 /// using methods such as [`Self::from_translation()`], [`Self::from_quat()`],
 /// [`Self::from_scale()`] and [`Self::from_scale_rotation_translation()`].
 ///
-/// Othographic projections can be created using the methods [`Self::orthographic_lh()`] for
+/// Orthographic projections can be created using the methods [`Self::orthographic_lh()`] for
 /// left-handed coordinate systems and [`Self::orthographic_rh()`] for right-handed
 /// systems. The resulting matrix is also an affine transformation.
 ///
@@ -71,6 +70,7 @@
 
     #[allow(clippy::too_many_arguments)]
     #[inline(always)]
+    #[must_use]
     const fn new(
         m00: f32,
         m01: f32,
@@ -97,8 +97,9 @@
         }
     }
 
-    /// Creates a 4x4 matrix from two column vectors.
+    /// Creates a 4x4 matrix from four column vectors.
     #[inline(always)]
+    #[must_use]
     pub const fn from_cols(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Self {
         Self {
             x_axis,
@@ -112,6 +113,7 @@
     /// If your data is stored in row major you will need to `transpose` the returned
     /// matrix.
     #[inline]
+    #[must_use]
     pub const fn from_cols_array(m: &[f32; 16]) -> Self {
         Self::new(
             m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9], m[10], m[11], m[12], m[13],
@@ -122,6 +124,7 @@
     /// Creates a `[f32; 16]` array storing data in column major order.
     /// If you require data in row major order `transpose` the matrix first.
     #[inline]
+    #[must_use]
     pub const fn to_cols_array(&self) -> [f32; 16] {
         let [x_axis_x, x_axis_y, x_axis_z, x_axis_w] = self.x_axis.to_array();
         let [y_axis_x, y_axis_y, y_axis_z, y_axis_w] = self.y_axis.to_array();
@@ -138,6 +141,7 @@
     /// If your data is in row major order you will need to `transpose` the returned
     /// matrix.
     #[inline]
+    #[must_use]
     pub const fn from_cols_array_2d(m: &[[f32; 4]; 4]) -> Self {
         Self::from_cols(
             Vec4::from_array(m[0]),
@@ -150,6 +154,7 @@
     /// Creates a `[[f32; 4]; 4]` 4D array storing data in column major order.
     /// If you require data in row major order `transpose` the matrix first.
     #[inline]
+    #[must_use]
     pub const fn to_cols_array_2d(&self) -> [[f32; 4]; 4] {
         [
             self.x_axis.to_array(),
@@ -162,6 +167,7 @@
     /// Creates a 4x4 matrix with its diagonal set to `diagonal` and all other entries set to 0.
     #[doc(alias = "scale")]
     #[inline]
+    #[must_use]
     pub const fn from_diagonal(diagonal: Vec4) -> Self {
         // diagonal.x, diagonal.y etc can't be done in a const-context
         let [x, y, z, w] = diagonal.to_array();
@@ -171,6 +177,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn quat_to_axes(rotation: Quat) -> (Vec4, Vec4, Vec4) {
         glam_assert!(rotation.is_normalized());
 
@@ -204,6 +211,7 @@
     ///
     /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_scale_rotation_translation(scale: Vec3, rotation: Quat, translation: Vec3) -> Self {
         let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
         Self::from_cols(
@@ -223,6 +231,7 @@
     ///
     /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_rotation_translation(rotation: Quat, translation: Vec3) -> Self {
         let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
         Self::from_cols(x_axis, y_axis, z_axis, Vec4::from((translation, 1.0)))
@@ -236,12 +245,13 @@
     /// Will panic if the determinant of `self` is zero or if the resulting scale vector
     /// contains any zero elements when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn to_scale_rotation_translation(&self) -> (Vec3, Quat, Vec3) {
         let det = self.determinant();
         glam_assert!(det != 0.0);
 
         let scale = Vec3::new(
-            self.x_axis.length() * det.signum(),
+            self.x_axis.length() * math::signum(det),
             self.y_axis.length(),
             self.z_axis.length(),
         );
@@ -270,6 +280,7 @@
     ///
     /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_quat(rotation: Quat) -> Self {
         let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
         Self::from_cols(x_axis, y_axis, z_axis, Vec4::W)
@@ -281,6 +292,7 @@
     /// The resulting matrix can be used to transform 3D points and vectors. See
     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
     #[inline]
+    #[must_use]
     pub fn from_mat3(m: Mat3) -> Self {
         Self::from_cols(
             Vec4::from((m.x_axis, 0.0)),
@@ -296,6 +308,7 @@
     /// The resulting matrix can be used to transform 3D points and vectors. See
     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
     #[inline]
+    #[must_use]
     pub fn from_mat3a(m: Mat3A) -> Self {
         Self::from_cols(
             Vec4::from((m.x_axis, 0.0)),
@@ -310,6 +323,7 @@
     /// The resulting matrix can be used to transform 3D points and vectors. See
     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
     #[inline]
+    #[must_use]
     pub fn from_translation(translation: Vec3) -> Self {
         Self::from_cols(
             Vec4::X,
@@ -329,10 +343,11 @@
     ///
     /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
         glam_assert!(axis.is_normalized());
 
-        let (sin, cos) = angle.sin_cos();
+        let (sin, cos) = math::sin_cos(angle);
         let axis_sin = axis.mul(sin);
         let axis_sq = axis.mul(axis);
         let omc = 1.0 - cos;
@@ -362,12 +377,13 @@
         )
     }
 
-    #[inline]
     /// Creates a affine transformation matrix containing a rotation from the given euler
     /// rotation sequence and angles (in radians).
     ///
     /// The resulting matrix can be used to transform 3D points and vectors. See
     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
+    #[inline]
+    #[must_use]
     pub fn from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self {
         let quat = Quat::from_euler(order, a, b, c);
         Self::from_quat(quat)
@@ -379,8 +395,9 @@
     /// The resulting matrix can be used to transform 3D points and vectors. See
     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
     #[inline]
+    #[must_use]
     pub fn from_rotation_x(angle: f32) -> Self {
-        let (sina, cosa) = angle.sin_cos();
+        let (sina, cosa) = math::sin_cos(angle);
         Self::from_cols(
             Vec4::X,
             Vec4::new(0.0, cosa, sina, 0.0),
@@ -395,8 +412,9 @@
     /// The resulting matrix can be used to transform 3D points and vectors. See
     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
     #[inline]
+    #[must_use]
     pub fn from_rotation_y(angle: f32) -> Self {
-        let (sina, cosa) = angle.sin_cos();
+        let (sina, cosa) = math::sin_cos(angle);
         Self::from_cols(
             Vec4::new(cosa, 0.0, -sina, 0.0),
             Vec4::Y,
@@ -411,8 +429,9 @@
     /// The resulting matrix can be used to transform 3D points and vectors. See
     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
     #[inline]
+    #[must_use]
     pub fn from_rotation_z(angle: f32) -> Self {
-        let (sina, cosa) = angle.sin_cos();
+        let (sina, cosa) = math::sin_cos(angle);
         Self::from_cols(
             Vec4::new(cosa, sina, 0.0, 0.0),
             Vec4::new(-sina, cosa, 0.0, 0.0),
@@ -430,6 +449,7 @@
     ///
     /// Will panic if all elements of `scale` are zero when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_scale(scale: Vec3) -> Self {
         // Do not panic as long as any component is non-zero
         glam_assert!(scale.cmpne(Vec3::ZERO).any());
@@ -448,6 +468,7 @@
     ///
     /// Panics if `slice` is less than 16 elements long.
     #[inline]
+    #[must_use]
     pub const fn from_cols_slice(slice: &[f32]) -> Self {
         Self::new(
             slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
@@ -486,6 +507,7 @@
     ///
     /// Panics if `index` is greater than 3.
     #[inline]
+    #[must_use]
     pub fn col(&self, index: usize) -> Vec4 {
         match index {
             0 => self.x_axis,
@@ -518,6 +540,7 @@
     ///
     /// Panics if `index` is greater than 3.
     #[inline]
+    #[must_use]
     pub fn row(&self, index: usize) -> Vec4 {
         match index {
             0 => Vec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
@@ -531,6 +554,7 @@
     /// Returns `true` if, and only if, all elements are finite.
     /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
     #[inline]
+    #[must_use]
     pub fn is_finite(&self) -> bool {
         self.x_axis.is_finite()
             && self.y_axis.is_finite()
@@ -540,13 +564,14 @@
 
     /// Returns `true` if any elements are `NaN`.
     #[inline]
+    #[must_use]
     pub fn is_nan(&self) -> bool {
         self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan() || self.w_axis.is_nan()
     }
 
     /// Returns the transpose of `self`.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn transpose(&self) -> Self {
         unsafe {
             // Based on https://github.com/microsoft/DirectXMath `XMMatrixTranspose`
@@ -565,6 +590,7 @@
     }
 
     /// Returns the determinant of `self`.
+    #[must_use]
     pub fn determinant(&self) -> f32 {
         unsafe {
             // Based on https://github.com/g-truc/glm `glm_mat4_determinant_lowp`
@@ -758,6 +784,7 @@
     ///
     /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
     #[inline]
+    #[must_use]
     pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
         Self::look_to_rh(eye, -dir, up)
     }
@@ -767,6 +794,7 @@
     ///
     /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
     #[inline]
+    #[must_use]
     pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
         let f = dir.normalize();
         let s = f.cross(up).normalize();
@@ -788,6 +816,7 @@
     ///
     /// Will panic if `up` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
         glam_assert!(up.is_normalized());
         Self::look_to_lh(eye, center.sub(eye), up)
@@ -810,6 +839,7 @@
     /// This is the same as the OpenGL `gluPerspective` function.
     /// See <https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml>
     #[inline]
+    #[must_use]
     pub fn perspective_rh_gl(
         fov_y_radians: f32,
         aspect_ratio: f32,
@@ -817,7 +847,7 @@
         z_far: f32,
     ) -> Self {
         let inv_length = 1.0 / (z_near - z_far);
-        let f = 1.0 / (0.5 * fov_y_radians).tan();
+        let f = 1.0 / math::tan(0.5 * fov_y_radians);
         let a = f / aspect_ratio;
         let b = (z_near + z_far) * inv_length;
         let c = (2.0 * z_near * z_far) * inv_length;
@@ -836,9 +866,10 @@
     /// Will panic if `z_near` or `z_far` are less than or equal to zero when `glam_assert` is
     /// enabled.
     #[inline]
+    #[must_use]
     pub fn perspective_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
         glam_assert!(z_near > 0.0 && z_far > 0.0);
-        let (sin_fov, cos_fov) = (0.5 * fov_y_radians).sin_cos();
+        let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
         let h = cos_fov / sin_fov;
         let w = h / aspect_ratio;
         let r = z_far / (z_far - z_near);
@@ -857,9 +888,10 @@
     /// Will panic if `z_near` or `z_far` are less than or equal to zero when `glam_assert` is
     /// enabled.
     #[inline]
+    #[must_use]
     pub fn perspective_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
         glam_assert!(z_near > 0.0 && z_far > 0.0);
-        let (sin_fov, cos_fov) = (0.5 * fov_y_radians).sin_cos();
+        let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
         let h = cos_fov / sin_fov;
         let w = h / aspect_ratio;
         let r = z_far / (z_near - z_far);
@@ -877,9 +909,10 @@
     ///
     /// Will panic if `z_near` is less than or equal to zero when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn perspective_infinite_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
         glam_assert!(z_near > 0.0);
-        let (sin_fov, cos_fov) = (0.5 * fov_y_radians).sin_cos();
+        let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
         let h = cos_fov / sin_fov;
         let w = h / aspect_ratio;
         Self::from_cols(
@@ -896,13 +929,14 @@
     ///
     /// Will panic if `z_near` is less than or equal to zero when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn perspective_infinite_reverse_lh(
         fov_y_radians: f32,
         aspect_ratio: f32,
         z_near: f32,
     ) -> Self {
         glam_assert!(z_near > 0.0);
-        let (sin_fov, cos_fov) = (0.5 * fov_y_radians).sin_cos();
+        let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
         let h = cos_fov / sin_fov;
         let w = h / aspect_ratio;
         Self::from_cols(
@@ -916,9 +950,10 @@
     /// Creates an infinite right-handed perspective projection matrix with
     /// `[0,1]` depth range.
     #[inline]
+    #[must_use]
     pub fn perspective_infinite_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
         glam_assert!(z_near > 0.0);
-        let f = 1.0 / (0.5 * fov_y_radians).tan();
+        let f = 1.0 / math::tan(0.5 * fov_y_radians);
         Self::from_cols(
             Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
             Vec4::new(0.0, f, 0.0, 0.0),
@@ -930,13 +965,14 @@
     /// Creates an infinite reverse right-handed perspective projection matrix
     /// with `[0,1]` depth range.
     #[inline]
+    #[must_use]
     pub fn perspective_infinite_reverse_rh(
         fov_y_radians: f32,
         aspect_ratio: f32,
         z_near: f32,
     ) -> Self {
         glam_assert!(z_near > 0.0);
-        let f = 1.0 / (0.5 * fov_y_radians).tan();
+        let f = 1.0 / math::tan(0.5 * fov_y_radians);
         Self::from_cols(
             Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
             Vec4::new(0.0, f, 0.0, 0.0),
@@ -950,6 +986,7 @@
     /// See
     /// <https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glOrtho.xml>
     #[inline]
+    #[must_use]
     pub fn orthographic_rh_gl(
         left: f32,
         right: f32,
@@ -975,6 +1012,7 @@
 
     /// Creates a left-handed orthographic projection matrix with `[0,1]` depth range.
     #[inline]
+    #[must_use]
     pub fn orthographic_lh(
         left: f32,
         right: f32,
@@ -1001,6 +1039,7 @@
 
     /// Creates a right-handed orthographic projection matrix with `[0,1]` depth range.
     #[inline]
+    #[must_use]
     pub fn orthographic_rh(
         left: f32,
         right: f32,
@@ -1032,6 +1071,7 @@
     ///
     /// This method assumes that `self` contains a projective transform.
     #[inline]
+    #[must_use]
     pub fn project_point3(&self, rhs: Vec3) -> Vec3 {
         let mut res = self.x_axis.mul(rhs.x);
         res = self.y_axis.mul(rhs.y).add(res);
@@ -1054,6 +1094,7 @@
     ///
     /// Will panic if the 3rd row of `self` is not `(0, 0, 0, 1)` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn transform_point3(&self, rhs: Vec3) -> Vec3 {
         glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
         let mut res = self.x_axis.mul(rhs.x);
@@ -1074,6 +1115,7 @@
     ///
     /// Will panic if the 3rd row of `self` is not `(0, 0, 0, 1)` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn transform_vector3(&self, rhs: Vec3) -> Vec3 {
         glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
         let mut res = self.x_axis.mul(rhs.x);
@@ -1082,10 +1124,11 @@
         res.xyz()
     }
 
-    /// Transforms the given `Vec3A` as 3D point.
+    /// Transforms the given [`Vec3A`] as 3D point.
     ///
-    /// This is the equivalent of multiplying the `Vec3A` as a 4D vector where `w` is `1.0`.
+    /// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `1.0`.
     #[inline]
+    #[must_use]
     pub fn transform_point3a(&self, rhs: Vec3A) -> Vec3A {
         glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
         let mut res = self.x_axis.mul(rhs.xxxx());
@@ -1095,10 +1138,11 @@
         res.into()
     }
 
-    /// Transforms the give `Vec3A` as 3D vector.
+    /// Transforms the give [`Vec3A`] as 3D vector.
     ///
-    /// This is the equivalent of multiplying the `Vec3A` as a 4D vector where `w` is `0.0`.
+    /// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `0.0`.
     #[inline]
+    #[must_use]
     pub fn transform_vector3a(&self, rhs: Vec3A) -> Vec3A {
         glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
         let mut res = self.x_axis.mul(rhs.xxxx());
@@ -1109,6 +1153,7 @@
 
     /// Transforms a 4D vector.
     #[inline]
+    #[must_use]
     pub fn mul_vec4(&self, rhs: Vec4) -> Vec4 {
         let mut res = self.x_axis.mul(rhs.xxxx());
         res = res.add(self.y_axis.mul(rhs.yyyy()));
@@ -1119,6 +1164,7 @@
 
     /// Multiplies two 4x4 matrices.
     #[inline]
+    #[must_use]
     pub fn mul_mat4(&self, rhs: &Self) -> Self {
         Self::from_cols(
             self.mul(rhs.x_axis),
@@ -1130,6 +1176,7 @@
 
     /// Adds two 4x4 matrices.
     #[inline]
+    #[must_use]
     pub fn add_mat4(&self, rhs: &Self) -> Self {
         Self::from_cols(
             self.x_axis.add(rhs.x_axis),
@@ -1141,6 +1188,7 @@
 
     /// Subtracts two 4x4 matrices.
     #[inline]
+    #[must_use]
     pub fn sub_mat4(&self, rhs: &Self) -> Self {
         Self::from_cols(
             self.x_axis.sub(rhs.x_axis),
@@ -1152,6 +1200,7 @@
 
     /// Multiplies a 4x4 matrix by a scalar.
     #[inline]
+    #[must_use]
     pub fn mul_scalar(&self, rhs: f32) -> Self {
         Self::from_cols(
             self.x_axis.mul(rhs),
@@ -1171,6 +1220,7 @@
     /// For more see
     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
     #[inline]
+    #[must_use]
     pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
         self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
             && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
diff --git a/src/f32/sse2/quat.rs b/src/f32/sse2/quat.rs
index f7fbd8d..ce032fe 100644
--- a/src/f32/sse2/quat.rs
+++ b/src/f32/sse2/quat.rs
@@ -2,14 +2,11 @@
 
 use crate::{
     euler::{EulerFromQuaternion, EulerRot, EulerToQuaternion},
+    f32::math,
     sse2::*,
-    DQuat, FloatEx, Mat3, Mat3A, Mat4, Vec2, Vec3, Vec3A, Vec4,
+    DQuat, Mat3, Mat3A, Mat4, Vec2, Vec3, Vec3A, Vec4,
 };
 
-#[cfg(feature = "libm")]
-#[allow(unused_imports)]
-use num_traits::Float;
-
 #[cfg(target_arch = "x86")]
 use core::arch::x86::*;
 #[cfg(target_arch = "x86_64")]
@@ -20,6 +17,7 @@
 use core::iter::{Product, Sum};
 use core::ops::{Add, Deref, DerefMut, Div, Mul, MulAssign, Neg, Sub};
 
+#[repr(C)]
 union UnionCast {
     a: [f32; 4],
     v: Quat,
@@ -30,6 +28,7 @@
 /// This should generally not be called manually unless you know what you are doing. Use
 /// one of the other constructors instead such as `identity` or `from_axis_angle`.
 #[inline]
+#[must_use]
 pub const fn quat(x: f32, y: f32, z: f32, w: f32) -> Quat {
     Quat::from_xyzw(x, y, z, w)
 }
@@ -40,6 +39,8 @@
 /// floating point "error creep" which can occur when successive quaternion
 /// operations are applied.
 ///
+/// SIMD vector types are used for storage on supported platforms.
+///
 /// This type is 16 byte aligned.
 #[derive(Clone, Copy)]
 #[repr(transparent)]
@@ -67,6 +68,7 @@
     /// This function does not check if the input is normalized, it is up to the user to
     /// provide normalized input or to normalized the resulting quaternion.
     #[inline(always)]
+    #[must_use]
     pub const fn from_xyzw(x: f32, y: f32, z: f32, w: f32) -> Self {
         unsafe { UnionCast { a: [x, y, z, w] }.v }
     }
@@ -78,6 +80,7 @@
     /// This function does not check if the input is normalized, it is up to the user to
     /// provide normalized input or to normalized the resulting quaternion.
     #[inline]
+    #[must_use]
     pub const fn from_array(a: [f32; 4]) -> Self {
         Self::from_xyzw(a[0], a[1], a[2], a[3])
     }
@@ -89,7 +92,8 @@
     /// This function does not check if the input is normalized, it is up to the user to
     /// provide normalized input or to normalized the resulting quaternion.
     #[inline]
-    pub fn from_vec4(v: Vec4) -> Self {
+    #[must_use]
+    pub const fn from_vec4(v: Vec4) -> Self {
         Self(v.0)
     }
 
@@ -104,6 +108,7 @@
     ///
     /// Panics if `slice` length is less than 4.
     #[inline]
+    #[must_use]
     pub fn from_slice(slice: &[f32]) -> Self {
         assert!(slice.len() >= 4);
         Self(unsafe { _mm_loadu_ps(slice.as_ptr()) })
@@ -121,15 +126,17 @@
     }
 
     /// Create a quaternion for a normalized rotation `axis` and `angle` (in radians).
-    /// The axis must be normalized (unit-length).
+    ///
+    /// The axis must be a unit vector.
     ///
     /// # Panics
     ///
     /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
         glam_assert!(axis.is_normalized());
-        let (s, c) = (angle * 0.5).sin_cos();
+        let (s, c) = math::sin_cos(angle * 0.5);
         let v = axis * s;
         Self::from_xyzw(v.x, v.y, v.z, c)
     }
@@ -138,6 +145,7 @@
     ///
     /// `from_scaled_axis(Vec3::ZERO)` results in the identity quaternion.
     #[inline]
+    #[must_use]
     pub fn from_scaled_axis(v: Vec3) -> Self {
         let length = v.length();
         if length == 0.0 {
@@ -149,33 +157,38 @@
 
     /// Creates a quaternion from the `angle` (in radians) around the x axis.
     #[inline]
+    #[must_use]
     pub fn from_rotation_x(angle: f32) -> Self {
-        let (s, c) = (angle * 0.5).sin_cos();
+        let (s, c) = math::sin_cos(angle * 0.5);
         Self::from_xyzw(s, 0.0, 0.0, c)
     }
 
     /// Creates a quaternion from the `angle` (in radians) around the y axis.
     #[inline]
+    #[must_use]
     pub fn from_rotation_y(angle: f32) -> Self {
-        let (s, c) = (angle * 0.5).sin_cos();
+        let (s, c) = math::sin_cos(angle * 0.5);
         Self::from_xyzw(0.0, s, 0.0, c)
     }
 
     /// Creates a quaternion from the `angle` (in radians) around the z axis.
     #[inline]
+    #[must_use]
     pub fn from_rotation_z(angle: f32) -> Self {
-        let (s, c) = (angle * 0.5).sin_cos();
+        let (s, c) = math::sin_cos(angle * 0.5);
         Self::from_xyzw(0.0, 0.0, s, c)
     }
 
-    #[inline]
     /// Creates a quaternion from the given Euler rotation sequence and the angles (in radians).
+    #[inline]
+    #[must_use]
     pub fn from_euler(euler: EulerRot, a: f32, b: f32, c: f32) -> Self {
         euler.new_quat(a, b, c)
     }
 
     /// From the columns of a 3x3 rotation matrix.
     #[inline]
+    #[must_use]
     pub(crate) fn from_rotation_axes(x_axis: Vec3, y_axis: Vec3, z_axis: Vec3) -> Self {
         // Based on https://github.com/microsoft/DirectXMath `XM$quaternionRotationMatrix`
         let (m00, m01, m02) = x_axis.into();
@@ -188,7 +201,7 @@
             if dif10 <= 0.0 {
                 // x^2 >= y^2
                 let four_xsq = omm22 - dif10;
-                let inv4x = 0.5 / four_xsq.sqrt();
+                let inv4x = 0.5 / math::sqrt(four_xsq);
                 Self::from_xyzw(
                     four_xsq * inv4x,
                     (m01 + m10) * inv4x,
@@ -198,7 +211,7 @@
             } else {
                 // y^2 >= x^2
                 let four_ysq = omm22 + dif10;
-                let inv4y = 0.5 / four_ysq.sqrt();
+                let inv4y = 0.5 / math::sqrt(four_ysq);
                 Self::from_xyzw(
                     (m01 + m10) * inv4y,
                     four_ysq * inv4y,
@@ -213,7 +226,7 @@
             if sum10 <= 0.0 {
                 // z^2 >= w^2
                 let four_zsq = opm22 - sum10;
-                let inv4z = 0.5 / four_zsq.sqrt();
+                let inv4z = 0.5 / math::sqrt(four_zsq);
                 Self::from_xyzw(
                     (m02 + m20) * inv4z,
                     (m12 + m21) * inv4z,
@@ -223,7 +236,7 @@
             } else {
                 // w^2 >= z^2
                 let four_wsq = opm22 + sum10;
-                let inv4w = 0.5 / four_wsq.sqrt();
+                let inv4w = 0.5 / math::sqrt(four_wsq);
                 Self::from_xyzw(
                     (m12 - m21) * inv4w,
                     (m20 - m02) * inv4w,
@@ -236,18 +249,21 @@
 
     /// Creates a quaternion from a 3x3 rotation matrix.
     #[inline]
+    #[must_use]
     pub fn from_mat3(mat: &Mat3) -> Self {
         Self::from_rotation_axes(mat.x_axis, mat.y_axis, mat.z_axis)
     }
 
     /// Creates a quaternion from a 3x3 SIMD aligned rotation matrix.
     #[inline]
+    #[must_use]
     pub fn from_mat3a(mat: &Mat3A) -> Self {
         Self::from_rotation_axes(mat.x_axis.into(), mat.y_axis.into(), mat.z_axis.into())
     }
 
     /// Creates a quaternion from a 3x3 rotation matrix inside a homogeneous 4x4 matrix.
     #[inline]
+    #[must_use]
     pub fn from_mat4(mat: &Mat4) -> Self {
         Self::from_rotation_axes(
             mat.x_axis.truncate(),
@@ -259,7 +275,7 @@
     /// Gets the minimal rotation for transforming `from` to `to`.  The rotation is in the
     /// plane spanned by the two vectors.  Will rotate at most 180 degrees.
     ///
-    /// The input vectors must be normalized (unit-length).
+    /// The inputs must be unit vectors.
     ///
     /// `from_rotation_arc(from, to) * from ≈ to`.
     ///
@@ -269,6 +285,7 @@
     /// # Panics
     ///
     /// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
+    #[must_use]
     pub fn from_rotation_arc(from: Vec3, to: Vec3) -> Self {
         glam_assert!(from.is_normalized());
         glam_assert!(to.is_normalized());
@@ -294,7 +311,7 @@
     /// The rotation is in the plane spanned by the two vectors.  Will rotate at most 90
     /// degrees.
     ///
-    /// The input vectors must be normalized (unit-length).
+    /// The inputs must be unit vectors.
     ///
     /// `to.dot(from_rotation_arc_colinear(from, to) * from).abs() ≈ 1`.
     ///
@@ -302,6 +319,7 @@
     ///
     /// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_rotation_arc_colinear(from: Vec3, to: Vec3) -> Self {
         if from.dot(to) < 0.0 {
             Self::from_rotation_arc(from, -to)
@@ -313,7 +331,7 @@
     /// Gets the minimal rotation for transforming `from` to `to`.  The resulting rotation is
     /// around the z axis. Will rotate at most 180 degrees.
     ///
-    /// The input vectors must be normalized (unit-length).
+    /// The inputs must be unit vectors.
     ///
     /// `from_rotation_arc_2d(from, to) * from ≈ to`.
     ///
@@ -323,6 +341,7 @@
     /// # Panics
     ///
     /// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
+    #[must_use]
     pub fn from_rotation_arc_2d(from: Vec2, to: Vec2) -> Self {
         glam_assert!(from.is_normalized());
         glam_assert!(to.is_normalized());
@@ -343,31 +362,30 @@
             let z = from.x * to.y - to.x * from.y;
             let w = 1.0 + dot;
             // calculate length with x=0 and y=0 to normalize
-            let len_rcp = 1.0 / (z * z + w * w).sqrt();
+            let len_rcp = 1.0 / math::sqrt(z * z + w * w);
             Self::from_xyzw(0.0, 0.0, z * len_rcp, w * len_rcp)
         }
     }
 
-    /// Returns the rotation axis and angle (in radians) of `self`.
+    /// Returns the rotation axis (normalized) and angle (in radians) of `self`.
     #[inline]
+    #[must_use]
     pub fn to_axis_angle(self) -> (Vec3, f32) {
         const EPSILON: f32 = 1.0e-8;
-        const EPSILON_SQUARED: f32 = EPSILON * EPSILON;
-        let w = self.w;
-        let angle = w.acos_approx() * 2.0;
-        let scale_sq = f32::max(1.0 - w * w, 0.0);
-        if scale_sq >= EPSILON_SQUARED {
-            (
-                Vec3::new(self.x, self.y, self.z) * scale_sq.sqrt().recip(),
-                angle,
-            )
+        let v = Vec3::new(self.x, self.y, self.z);
+        let length = v.length();
+        if length >= EPSILON {
+            let angle = 2.0 * math::atan2(length, self.w);
+            let axis = v / length;
+            (axis, angle)
         } else {
-            (Vec3::X, angle)
+            (Vec3::X, 0.0)
         }
     }
 
     /// Returns the rotation axis scaled by the rotation in radians.
     #[inline]
+    #[must_use]
     pub fn to_scaled_axis(self) -> Vec3 {
         let (axis, angle) = self.to_axis_angle();
         axis * angle
@@ -375,26 +393,29 @@
 
     /// Returns the rotation angles for the given euler rotation sequence.
     #[inline]
+    #[must_use]
     pub fn to_euler(self, euler: EulerRot) -> (f32, f32, f32) {
         euler.convert_quat(self)
     }
 
     /// `[x, y, z, w]`
     #[inline]
+    #[must_use]
     pub fn to_array(&self) -> [f32; 4] {
         [self.x, self.y, self.z, self.w]
     }
 
     /// Returns the vector part of the quaternion.
     #[inline]
+    #[must_use]
     pub fn xyz(self) -> Vec3 {
         Vec3::new(self.x, self.y, self.z)
     }
 
     /// Returns the quaternion conjugate of `self`. For a unit quaternion the
     /// conjugate is also the inverse.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn conjugate(self) -> Self {
         const SIGN: __m128 = m128_from_f32x4([-0.0, -0.0, -0.0, 0.0]);
         Self(unsafe { _mm_xor_ps(self.0, SIGN) })
@@ -409,8 +430,8 @@
     /// # Panics
     ///
     /// Will panic if `self` is not normalized when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn inverse(self) -> Self {
         glam_assert!(self.is_normalized());
         self.conjugate()
@@ -419,6 +440,7 @@
     /// Computes the dot product of `self` and `rhs`. The dot product is
     /// equal to the cosine of the angle between two quaternion rotations.
     #[inline]
+    #[must_use]
     pub fn dot(self, rhs: Self) -> f32 {
         Vec4::from(self).dot(Vec4::from(rhs))
     }
@@ -426,6 +448,7 @@
     /// Computes the length of `self`.
     #[doc(alias = "magnitude")]
     #[inline]
+    #[must_use]
     pub fn length(self) -> f32 {
         Vec4::from(self).length()
     }
@@ -436,6 +459,7 @@
     /// root operation.
     #[doc(alias = "magnitude2")]
     #[inline]
+    #[must_use]
     pub fn length_squared(self) -> f32 {
         Vec4::from(self).length_squared()
     }
@@ -444,6 +468,7 @@
     ///
     /// For valid results, `self` must _not_ be of length zero.
     #[inline]
+    #[must_use]
     pub fn length_recip(self) -> f32 {
         Vec4::from(self).length_recip()
     }
@@ -455,8 +480,8 @@
     /// Panics
     ///
     /// Will panic if `self` is zero length when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn normalize(self) -> Self {
         Self::from_vec4(Vec4::from(self).normalize())
     }
@@ -464,11 +489,13 @@
     /// Returns `true` if, and only if, all elements are finite.
     /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
     #[inline]
+    #[must_use]
     pub fn is_finite(self) -> bool {
         Vec4::from(self).is_finite()
     }
 
     #[inline]
+    #[must_use]
     pub fn is_nan(self) -> bool {
         Vec4::from(self).is_nan()
     }
@@ -477,11 +504,13 @@
     ///
     /// Uses a precision threshold of `1e-6`.
     #[inline]
+    #[must_use]
     pub fn is_normalized(self) -> bool {
         Vec4::from(self).is_normalized()
     }
 
     #[inline]
+    #[must_use]
     pub fn is_near_identity(self) -> bool {
         // Based on https://github.com/nfrechette/rtm `rtm::quat_near_identity`
         let threshold_angle = 0.002_847_144_6;
@@ -498,7 +527,7 @@
         // If the quat.w is close to -1.0, the angle will be near 2*PI which is close to
         // a negative 0 rotation. By forcing quat.w to be positive, we'll end up with
         // the shortest path.
-        let positive_w_angle = self.w.abs().acos_approx() * 2.0;
+        let positive_w_angle = math::acos_approx(math::abs(self.w)) * 2.0;
         positive_w_angle < threshold_angle
     }
 
@@ -511,9 +540,10 @@
     ///
     /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn angle_between(self, rhs: Self) -> f32 {
         glam_assert!(self.is_normalized() && rhs.is_normalized());
-        self.dot(rhs).abs().acos_approx() * 2.0
+        math::acos_approx(math::abs(self.dot(rhs))) * 2.0
     }
 
     /// Returns true if the absolute difference of all elements between `self` and `rhs`
@@ -526,6 +556,7 @@
     /// For more see
     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
     #[inline]
+    #[must_use]
     pub fn abs_diff_eq(self, rhs: Self, max_abs_diff: f32) -> bool {
         Vec4::from(self).abs_diff_eq(Vec4::from(rhs), max_abs_diff)
     }
@@ -539,8 +570,9 @@
     /// # Panics
     ///
     /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
-    #[inline]
     #[doc(alias = "mix")]
+    #[inline]
+    #[must_use]
     pub fn lerp(self, end: Self, s: f32) -> Self {
         glam_assert!(self.is_normalized());
         glam_assert!(end.is_normalized());
@@ -571,6 +603,7 @@
     ///
     /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn slerp(self, mut end: Self, s: f32) -> Self {
         // http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/
         glam_assert!(self.is_normalized());
@@ -594,7 +627,7 @@
             // assumes lerp returns a normalized quaternion
             self.lerp(end, s)
         } else {
-            let theta = dot.acos_approx();
+            let theta = math::acos_approx(dot);
 
             let x = 1.0 - s;
             let y = s;
@@ -622,6 +655,7 @@
     ///
     /// Will panic if `self` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn mul_vec3(self, rhs: Vec3) -> Vec3 {
         glam_assert!(self.is_normalized());
 
@@ -637,6 +671,7 @@
     ///
     /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn mul_quat(self, rhs: Self) -> Self {
         glam_assert!(self.is_normalized());
         glam_assert!(rhs.is_normalized());
@@ -680,6 +715,7 @@
 
     /// Creates a quaternion from a 3x3 rotation matrix inside a 3D affine transform.
     #[inline]
+    #[must_use]
     pub fn from_affine3(a: &crate::Affine3A) -> Self {
         #[allow(clippy::useless_conversion)]
         Self::from_rotation_axes(
@@ -691,6 +727,7 @@
 
     /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
     #[inline]
+    #[must_use]
     pub fn mul_vec3a(self, rhs: Vec3A) -> Vec3A {
         unsafe {
             const TWO: __m128 = m128_from_f32x4([2.0; 4]);
@@ -708,9 +745,17 @@
     }
 
     #[inline]
-    pub fn as_f64(self) -> DQuat {
+    #[must_use]
+    pub fn as_dquat(self) -> DQuat {
         DQuat::from_xyzw(self.x as f64, self.y as f64, self.z as f64, self.w as f64)
     }
+
+    #[inline]
+    #[must_use]
+    #[deprecated(since = "0.24.2", note = "Use as_dquat() instead")]
+    pub fn as_f64(self) -> DQuat {
+        self.as_dquat()
+    }
 }
 
 #[cfg(not(target_arch = "spirv"))]
diff --git a/src/f32/sse2/vec3a.rs b/src/f32/sse2/vec3a.rs
index c13d9bf..96c62a7 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::{sse2::*, BVec3A, Vec2, Vec3, Vec4};
+use crate::{f32::math, sse2::*, BVec3A, Vec2, Vec3, Vec4};
 
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
@@ -12,10 +12,7 @@
 #[cfg(target_arch = "x86_64")]
 use core::arch::x86_64::*;
 
-#[cfg(feature = "libm")]
-#[allow(unused_imports)]
-use num_traits::Float;
-
+#[repr(C)]
 union UnionCast {
     a: [f32; 4],
     v: Vec3A,
@@ -23,16 +20,20 @@
 
 /// Creates a 3-dimensional vector.
 #[inline(always)]
+#[must_use]
 pub const fn vec3a(x: f32, y: f32, z: f32) -> Vec3A {
     Vec3A::new(x, y, z)
 }
 
-/// A 3-dimensional vector with SIMD support.
+/// A 3-dimensional vector.
 ///
-/// This type is 16 byte aligned. A SIMD vector type is used for storage on supported platforms for
-/// better performance than the `Vec3` type.
+/// SIMD vector types are used for storage on supported platforms for better
+/// performance than the [`Vec3`] type.
 ///
-/// It is possible to convert between `Vec3` and `Vec3A` types using `From` trait implementations.
+/// It is possible to convert between [`Vec3`] and [`Vec3A`] types using [`From`]
+/// or [`Into`] trait implementations.
+///
+/// This type is 16 byte aligned.
 #[derive(Clone, Copy)]
 #[repr(transparent)]
 pub struct Vec3A(pub(crate) __m128);
@@ -47,25 +48,37 @@
     /// All negative ones.
     pub const NEG_ONE: Self = Self::splat(-1.0);
 
-    /// All NAN.
+    /// All `f32::MIN`.
+    pub const MIN: Self = Self::splat(f32::MIN);
+
+    /// All `f32::MAX`.
+    pub const MAX: Self = Self::splat(f32::MAX);
+
+    /// All `f32::NAN`.
     pub const NAN: Self = Self::splat(f32::NAN);
 
-    /// A unit-length vector pointing along the positive X axis.
+    /// All `f32::INFINITY`.
+    pub const INFINITY: Self = Self::splat(f32::INFINITY);
+
+    /// All `f32::NEG_INFINITY`.
+    pub const NEG_INFINITY: Self = Self::splat(f32::NEG_INFINITY);
+
+    /// A unit vector pointing along the positive X axis.
     pub const X: Self = Self::new(1.0, 0.0, 0.0);
 
-    /// A unit-length vector pointing along the positive Y axis.
+    /// A unit vector pointing along the positive Y axis.
     pub const Y: Self = Self::new(0.0, 1.0, 0.0);
 
-    /// A unit-length vector pointing along the positive Z axis.
+    /// A unit vector pointing along the positive Z axis.
     pub const Z: Self = Self::new(0.0, 0.0, 1.0);
 
-    /// A unit-length vector pointing along the negative X axis.
+    /// A unit vector pointing along the negative X axis.
     pub const NEG_X: Self = Self::new(-1.0, 0.0, 0.0);
 
-    /// A unit-length vector pointing along the negative Y axis.
+    /// A unit vector pointing along the negative Y axis.
     pub const NEG_Y: Self = Self::new(0.0, -1.0, 0.0);
 
-    /// A unit-length vector pointing along the negative Z axis.
+    /// A unit vector pointing along the negative Z axis.
     pub const NEG_Z: Self = Self::new(0.0, 0.0, -1.0);
 
     /// The unit axes.
@@ -73,12 +86,14 @@
 
     /// Creates a new vector.
     #[inline(always)]
+    #[must_use]
     pub const fn new(x: f32, y: f32, z: f32) -> Self {
         unsafe { UnionCast { a: [x, y, z, z] }.v }
     }
 
     /// Creates a vector with all elements set to `v`.
     #[inline]
+    #[must_use]
     pub const fn splat(v: f32) -> Self {
         unsafe { UnionCast { a: [v; 4] }.v }
     }
@@ -89,6 +104,7 @@
     /// A true element in the mask uses the corresponding element from `if_true`, and false
     /// uses the element from `if_false`.
     #[inline]
+    #[must_use]
     pub fn select(mask: BVec3A, if_true: Self, if_false: Self) -> Self {
         Self(unsafe {
             _mm_or_ps(
@@ -100,12 +116,14 @@
 
     /// Creates a new vector from an array.
     #[inline]
+    #[must_use]
     pub const fn from_array(a: [f32; 3]) -> Self {
         Self::new(a[0], a[1], a[2])
     }
 
     /// `[x, y, z]`
     #[inline]
+    #[must_use]
     pub const fn to_array(&self) -> [f32; 3] {
         unsafe { *(self as *const Vec3A as *const [f32; 3]) }
     }
@@ -116,6 +134,7 @@
     ///
     /// Panics if `slice` is less than 3 elements long.
     #[inline]
+    #[must_use]
     pub const fn from_slice(slice: &[f32]) -> Self {
         Self::new(slice[0], slice[1], slice[2])
     }
@@ -135,20 +154,23 @@
     /// Internal method for creating a 3D vector from a 4D vector, discarding `w`.
     #[allow(dead_code)]
     #[inline]
+    #[must_use]
     pub(crate) fn from_vec4(v: Vec4) -> Self {
         Self(v.0)
     }
 
     /// Creates a 4D vector from `self` and the given `w` value.
     #[inline]
+    #[must_use]
     pub fn extend(self, w: f32) -> Vec4 {
         Vec4::new(self.x, self.y, self.z, w)
     }
 
     /// Creates a 2D vector from the `x` and `y` elements of `self`, discarding `z`.
     ///
-    /// Truncation may also be performed by using `self.xy()` or `Vec2::from()`.
+    /// Truncation may also be performed by using [`self.xy()`][crate::swizzles::Vec3Swizzles::xy()].
     #[inline]
+    #[must_use]
     pub fn truncate(self) -> Vec2 {
         use crate::swizzles::Vec3Swizzles;
         self.xy()
@@ -156,18 +178,21 @@
 
     /// Computes the dot product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn dot(self, rhs: Self) -> f32 {
         unsafe { dot3(self.0, rhs.0) }
     }
 
     /// Returns a vector where every component is the dot product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn dot_into_vec(self, rhs: Self) -> Self {
         Self(unsafe { dot3_into_m128(self.0, rhs.0) })
     }
 
     /// Computes the cross product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn cross(self, rhs: Self) -> Self {
         unsafe {
             // x  <-  a.y*b.z - a.z*b.y
@@ -188,6 +213,7 @@
     ///
     /// In other words this computes `[self.x.min(rhs.x), self.y.min(rhs.y), ..]`.
     #[inline]
+    #[must_use]
     pub fn min(self, rhs: Self) -> Self {
         Self(unsafe { _mm_min_ps(self.0, rhs.0) })
     }
@@ -196,6 +222,7 @@
     ///
     /// In other words this computes `[self.x.max(rhs.x), self.y.max(rhs.y), ..]`.
     #[inline]
+    #[must_use]
     pub fn max(self, rhs: Self) -> Self {
         Self(unsafe { _mm_max_ps(self.0, rhs.0) })
     }
@@ -208,6 +235,7 @@
     ///
     /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn clamp(self, min: Self, max: Self) -> Self {
         glam_assert!(min.cmple(max).all(), "clamp: expected min <= max");
         self.max(min).min(max)
@@ -217,6 +245,7 @@
     ///
     /// In other words this computes `min(x, y, ..)`.
     #[inline]
+    #[must_use]
     pub fn min_element(self) -> f32 {
         unsafe {
             let v = self.0;
@@ -230,6 +259,7 @@
     ///
     /// In other words this computes `max(x, y, ..)`.
     #[inline]
+    #[must_use]
     pub fn max_element(self) -> f32 {
         unsafe {
             let v = self.0;
@@ -245,6 +275,7 @@
     /// In other words, this computes `[self.x == rhs.x, self.y == rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpeq(self, rhs: Self) -> BVec3A {
         BVec3A(unsafe { _mm_cmpeq_ps(self.0, rhs.0) })
     }
@@ -255,6 +286,7 @@
     /// In other words this computes `[self.x != rhs.x, self.y != rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpne(self, rhs: Self) -> BVec3A {
         BVec3A(unsafe { _mm_cmpneq_ps(self.0, rhs.0) })
     }
@@ -265,6 +297,7 @@
     /// In other words this computes `[self.x >= rhs.x, self.y >= rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpge(self, rhs: Self) -> BVec3A {
         BVec3A(unsafe { _mm_cmpge_ps(self.0, rhs.0) })
     }
@@ -275,6 +308,7 @@
     /// In other words this computes `[self.x > rhs.x, self.y > rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpgt(self, rhs: Self) -> BVec3A {
         BVec3A(unsafe { _mm_cmpgt_ps(self.0, rhs.0) })
     }
@@ -285,6 +319,7 @@
     /// In other words this computes `[self.x <= rhs.x, self.y <= rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmple(self, rhs: Self) -> BVec3A {
         BVec3A(unsafe { _mm_cmple_ps(self.0, rhs.0) })
     }
@@ -295,12 +330,14 @@
     /// In other words this computes `[self.x < rhs.x, self.y < rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmplt(self, rhs: Self) -> BVec3A {
         BVec3A(unsafe { _mm_cmplt_ps(self.0, rhs.0) })
     }
 
     /// Returns a vector containing the absolute value of each element of `self`.
     #[inline]
+    #[must_use]
     pub fn abs(self) -> Self {
         Self(unsafe { crate::sse2::m128_abs(self.0) })
     }
@@ -311,6 +348,7 @@
     /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
     /// - `NAN` if the number is `NAN`
     #[inline]
+    #[must_use]
     pub fn signum(self) -> Self {
         unsafe {
             let result = Self(_mm_or_ps(_mm_and_ps(self.0, Self::NEG_ONE.0), Self::ONE.0));
@@ -321,6 +359,7 @@
 
     /// Returns a vector with signs of `rhs` and the magnitudes of `self`.
     #[inline]
+    #[must_use]
     pub fn copysign(self, rhs: Self) -> Self {
         unsafe {
             let mask = Self::splat(-0.0);
@@ -336,6 +375,7 @@
     /// A negative element results in a `1` bit and a positive element in a `0` bit.  Element `x` goes
     /// into the first lowest bit, element `y` into the second, etc.
     #[inline]
+    #[must_use]
     pub fn is_negative_bitmask(self) -> u32 {
         unsafe { (_mm_movemask_ps(self.0) as u32) & 0x7 }
     }
@@ -343,12 +383,14 @@
     /// Returns `true` if, and only if, all elements are finite.  If any element is either
     /// `NaN`, positive or negative infinity, this will return `false`.
     #[inline]
+    #[must_use]
     pub fn is_finite(self) -> bool {
         self.x.is_finite() && self.y.is_finite() && self.z.is_finite()
     }
 
     /// Returns `true` if any elements are `NaN`.
     #[inline]
+    #[must_use]
     pub fn is_nan(self) -> bool {
         self.is_nan_mask().any()
     }
@@ -357,6 +399,7 @@
     ///
     /// In other words, this computes `[x.is_nan(), y.is_nan(), z.is_nan(), w.is_nan()]`.
     #[inline]
+    #[must_use]
     pub fn is_nan_mask(self) -> BVec3A {
         BVec3A(unsafe { _mm_cmpunord_ps(self.0, self.0) })
     }
@@ -364,6 +407,7 @@
     /// Computes the length of `self`.
     #[doc(alias = "magnitude")]
     #[inline]
+    #[must_use]
     pub fn length(self) -> f32 {
         unsafe {
             let dot = dot3_in_x(self.0, self.0);
@@ -376,6 +420,7 @@
     /// This is faster than `length()` as it avoids a square root operation.
     #[doc(alias = "magnitude2")]
     #[inline]
+    #[must_use]
     pub fn length_squared(self) -> f32 {
         self.dot(self)
     }
@@ -384,6 +429,7 @@
     ///
     /// For valid results, `self` must _not_ be of length zero.
     #[inline]
+    #[must_use]
     pub fn length_recip(self) -> f32 {
         unsafe {
             let dot = dot3_in_x(self.0, self.0);
@@ -393,27 +439,53 @@
 
     /// Computes the Euclidean distance between two points in space.
     #[inline]
+    #[must_use]
     pub fn distance(self, rhs: Self) -> f32 {
         (self - rhs).length()
     }
 
     /// Compute the squared euclidean distance between two points in space.
     #[inline]
+    #[must_use]
     pub fn distance_squared(self, rhs: Self) -> f32 {
         (self - rhs).length_squared()
     }
 
+    /// Returns the element-wise quotient of [Euclidean division] of `self` by `rhs`.
+    #[inline]
+    #[must_use]
+    pub fn div_euclid(self, rhs: Self) -> Self {
+        Self::new(
+            math::div_euclid(self.x, rhs.x),
+            math::div_euclid(self.y, rhs.y),
+            math::div_euclid(self.z, rhs.z),
+        )
+    }
+
+    /// Returns the element-wise remainder of [Euclidean division] of `self` by `rhs`.
+    ///
+    /// [Euclidean division]: f32::rem_euclid
+    #[inline]
+    #[must_use]
+    pub fn rem_euclid(self, rhs: Self) -> Self {
+        Self::new(
+            math::rem_euclid(self.x, rhs.x),
+            math::rem_euclid(self.y, rhs.y),
+            math::rem_euclid(self.z, rhs.z),
+        )
+    }
+
     /// Returns `self` normalized to length 1.0.
     ///
     /// For valid results, `self` must _not_ be of length zero, nor very close to zero.
     ///
-    /// See also [`Self::try_normalize`] and [`Self::normalize_or_zero`].
+    /// See also [`Self::try_normalize()`] and [`Self::normalize_or_zero()`].
     ///
     /// Panics
     ///
     /// Will panic if `self` is zero length when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn normalize(self) -> Self {
         unsafe {
             let length = _mm_sqrt_ps(dot3_into_m128(self.0, self.0));
@@ -429,9 +501,9 @@
     /// In particular, if the input is zero (or very close to zero), or non-finite,
     /// the result of this operation will be `None`.
     ///
-    /// See also [`Self::normalize_or_zero`].
-    #[must_use]
+    /// See also [`Self::normalize_or_zero()`].
     #[inline]
+    #[must_use]
     pub fn try_normalize(self) -> Option<Self> {
         let rcp = self.length_recip();
         if rcp.is_finite() && rcp > 0.0 {
@@ -446,9 +518,9 @@
     /// In particular, if the input is zero (or very close to zero), or non-finite,
     /// the result of this operation will be zero.
     ///
-    /// See also [`Self::try_normalize`].
-    #[must_use]
+    /// See also [`Self::try_normalize()`].
     #[inline]
+    #[must_use]
     pub fn normalize_or_zero(self) -> Self {
         let rcp = self.length_recip();
         if rcp.is_finite() && rcp > 0.0 {
@@ -462,9 +534,10 @@
     ///
     /// Uses a precision threshold of `1e-6`.
     #[inline]
+    #[must_use]
     pub fn is_normalized(self) -> bool {
         // TODO: do something with epsilon
-        (self.length_squared() - 1.0).abs() <= 1e-4
+        math::abs(self.length_squared() - 1.0) <= 1e-4
     }
 
     /// Returns the vector projection of `self` onto `rhs`.
@@ -474,8 +547,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` is zero length when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn project_onto(self, rhs: Self) -> Self {
         let other_len_sq_rcp = rhs.dot(rhs).recip();
         glam_assert!(other_len_sq_rcp.is_finite());
@@ -492,8 +565,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` has a length of zero when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn reject_from(self, rhs: Self) -> Self {
         self - self.project_onto(rhs)
     }
@@ -505,8 +578,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` is not normalized when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn project_onto_normalized(self, rhs: Self) -> Self {
         glam_assert!(rhs.is_normalized());
         rhs * self.dot(rhs)
@@ -522,8 +595,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` is not normalized when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn reject_from_normalized(self, rhs: Self) -> Self {
         self - self.project_onto_normalized(rhs)
     }
@@ -531,6 +604,7 @@
     /// Returns a vector containing the nearest integer to a number for each element of `self`.
     /// Round half-way cases away from 0.0.
     #[inline]
+    #[must_use]
     pub fn round(self) -> Self {
         Self(unsafe { m128_round(self.0) })
     }
@@ -538,6 +612,7 @@
     /// Returns a vector containing the largest integer less than or equal to a number for each
     /// element of `self`.
     #[inline]
+    #[must_use]
     pub fn floor(self) -> Self {
         Self(unsafe { m128_floor(self.0) })
     }
@@ -545,15 +620,25 @@
     /// Returns a vector containing the smallest integer greater than or equal to a number for
     /// each element of `self`.
     #[inline]
+    #[must_use]
     pub fn ceil(self) -> Self {
         Self(unsafe { m128_ceil(self.0) })
     }
 
+    /// Returns a vector containing the integer part each element of `self`. This means numbers are
+    /// always truncated towards zero.
+    #[inline]
+    #[must_use]
+    pub fn trunc(self) -> Self {
+        Self(unsafe { m128_trunc(self.0) })
+    }
+
     /// Returns a vector containing the fractional part of the vector, e.g. `self -
     /// self.floor()`.
     ///
     /// Note that this is fast but not precise for large numbers.
     #[inline]
+    #[must_use]
     pub fn fract(self) -> Self {
         self - self.floor()
     }
@@ -561,18 +646,25 @@
     /// Returns a vector containing `e^self` (the exponential function) for each element of
     /// `self`.
     #[inline]
+    #[must_use]
     pub fn exp(self) -> Self {
-        Self::new(self.x.exp(), self.y.exp(), self.z.exp())
+        Self::new(math::exp(self.x), math::exp(self.y), math::exp(self.z))
     }
 
     /// Returns a vector containing each element of `self` raised to the power of `n`.
     #[inline]
+    #[must_use]
     pub fn powf(self, n: f32) -> Self {
-        Self::new(self.x.powf(n), self.y.powf(n), self.z.powf(n))
+        Self::new(
+            math::powf(self.x, n),
+            math::powf(self.y, n),
+            math::powf(self.z, n),
+        )
     }
 
     /// Returns a vector containing the reciprocal `1.0/n` of each element of `self`.
     #[inline]
+    #[must_use]
     pub fn recip(self) -> Self {
         Self(unsafe { _mm_div_ps(Self::ONE.0, self.0) })
     }
@@ -584,6 +676,7 @@
     /// extrapolated.
     #[doc(alias = "mix")]
     #[inline]
+    #[must_use]
     pub fn lerp(self, rhs: Self, s: f32) -> Self {
         self + ((rhs - self) * s)
     }
@@ -598,6 +691,7 @@
     /// For more see
     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
     #[inline]
+    #[must_use]
     pub fn abs_diff_eq(self, rhs: Self, max_abs_diff: f32) -> bool {
         self.sub(rhs).abs().cmple(Self::splat(max_abs_diff)).all()
     }
@@ -608,33 +702,38 @@
     ///
     /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn clamp_length(self, min: f32, max: f32) -> Self {
         glam_assert!(min <= max);
         let length_sq = self.length_squared();
         if length_sq < min * min {
-            self * (length_sq.sqrt().recip() * min)
+            min * (self / math::sqrt(length_sq))
         } else if length_sq > max * max {
-            self * (length_sq.sqrt().recip() * max)
+            max * (self / math::sqrt(length_sq))
         } else {
             self
         }
     }
 
     /// Returns a vector with a length no more than `max`
+    #[inline]
+    #[must_use]
     pub fn clamp_length_max(self, max: f32) -> Self {
         let length_sq = self.length_squared();
         if length_sq > max * max {
-            self * (length_sq.sqrt().recip() * max)
+            max * (self / math::sqrt(length_sq))
         } else {
             self
         }
     }
 
     /// Returns a vector with a length no less than `min`
+    #[inline]
+    #[must_use]
     pub fn clamp_length_min(self, min: f32) -> Self {
         let length_sq = self.length_squared();
         if length_sq < min * min {
-            self * (length_sq.sqrt().recip() * min)
+            min * (self / math::sqrt(length_sq))
         } else {
             self
         }
@@ -648,6 +747,7 @@
     /// and will be heavily dependant on designing algorithms with specific target hardware in
     /// mind.
     #[inline]
+    #[must_use]
     pub fn mul_add(self, a: Self, b: Self) -> Self {
         #[cfg(target_feature = "fma")]
         unsafe {
@@ -655,72 +755,71 @@
         }
         #[cfg(not(target_feature = "fma"))]
         Self::new(
-            self.x.mul_add(a.x, b.x),
-            self.y.mul_add(a.y, b.y),
-            self.z.mul_add(a.z, b.z),
+            math::mul_add(self.x, a.x, b.x),
+            math::mul_add(self.y, a.y, b.y),
+            math::mul_add(self.z, a.z, b.z),
         )
     }
 
     /// Returns the angle (in radians) between two vectors.
     ///
-    /// The input vectors do not need to be unit length however they must be non-zero.
+    /// The inputs do not need to be unit vectors however they must be non-zero.
     #[inline]
+    #[must_use]
     pub fn angle_between(self, rhs: Self) -> f32 {
-        use crate::FloatEx;
-        self.dot(rhs)
-            .div(self.length_squared().mul(rhs.length_squared()).sqrt())
-            .acos_approx()
+        math::acos_approx(
+            self.dot(rhs)
+                .div(math::sqrt(self.length_squared().mul(rhs.length_squared()))),
+        )
     }
 
     /// Returns some vector that is orthogonal to the given one.
     ///
     /// The input vector must be finite and non-zero.
     ///
-    /// The output vector is not necessarily unit-length.
-    /// For that use [`Self::any_orthonormal_vector`] instead.
+    /// The output vector is not necessarily unit length. For that use
+    /// [`Self::any_orthonormal_vector()`] instead.
     #[inline]
+    #[must_use]
     pub fn any_orthogonal_vector(&self) -> Self {
         // This can probably be optimized
-        if self.x.abs() > self.y.abs() {
+        if math::abs(self.x) > math::abs(self.y) {
             Self::new(-self.z, 0.0, self.x) // self.cross(Self::Y)
         } else {
             Self::new(0.0, self.z, -self.y) // self.cross(Self::X)
         }
     }
 
-    /// Returns any unit-length vector that is orthogonal to the given one.
-    /// The input vector must be finite and non-zero.
+    /// Returns any unit vector that is orthogonal to the given one.
+    ///
+    /// The input vector must be unit length.
     ///
     /// # Panics
     ///
     /// Will panic if `self` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn any_orthonormal_vector(&self) -> Self {
         glam_assert!(self.is_normalized());
         // From https://graphics.pixar.com/library/OrthonormalB/paper.pdf
-        #[cfg(feature = "std")]
-        let sign = (1.0_f32).copysign(self.z);
-        #[cfg(not(feature = "std"))]
-        let sign = self.z.signum();
+        let sign = math::signum(self.z);
         let a = -1.0 / (sign + self.z);
         let b = self.x * self.y * a;
         Self::new(b, sign + self.y * self.y * a, -self.y)
     }
 
-    /// Given a unit-length vector return two other vectors that together form an orthonormal
-    /// basis.  That is, all three vectors are orthogonal to each other and are normalized.
+    /// Given a unit vector return two other vectors that together form an orthonormal
+    /// basis. That is, all three vectors are orthogonal to each other and are normalized.
     ///
     /// # Panics
     ///
     /// Will panic if `self` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn any_orthonormal_pair(&self) -> (Self, Self) {
         glam_assert!(self.is_normalized());
         // From https://graphics.pixar.com/library/OrthonormalB/paper.pdf
-        #[cfg(feature = "std")]
-        let sign = (1.0_f32).copysign(self.z);
-        #[cfg(not(feature = "std"))]
-        let sign = self.z.signum();
+        let sign = math::signum(self.z);
         let a = -1.0 / (sign + self.z);
         let b = self.x * self.y * a;
         (
@@ -731,21 +830,52 @@
 
     /// Casts all elements of `self` to `f64`.
     #[inline]
+    #[must_use]
     pub fn as_dvec3(&self) -> crate::DVec3 {
         crate::DVec3::new(self.x as f64, self.y as f64, self.z as f64)
     }
 
+    /// Casts all elements of `self` to `i16`.
+    #[inline]
+    #[must_use]
+    pub fn as_i16vec3(&self) -> crate::I16Vec3 {
+        crate::I16Vec3::new(self.x as i16, self.y as i16, self.z as i16)
+    }
+
+    /// Casts all elements of `self` to `u16`.
+    #[inline]
+    #[must_use]
+    pub fn as_u16vec3(&self) -> crate::U16Vec3 {
+        crate::U16Vec3::new(self.x as u16, self.y as u16, self.z as u16)
+    }
+
     /// Casts all elements of `self` to `i32`.
     #[inline]
+    #[must_use]
     pub fn as_ivec3(&self) -> crate::IVec3 {
         crate::IVec3::new(self.x as i32, self.y as i32, self.z as i32)
     }
 
     /// Casts all elements of `self` to `u32`.
     #[inline]
+    #[must_use]
     pub fn as_uvec3(&self) -> crate::UVec3 {
         crate::UVec3::new(self.x as u32, self.y as u32, self.z as u32)
     }
+
+    /// Casts all elements of `self` to `i64`.
+    #[inline]
+    #[must_use]
+    pub fn as_i64vec3(&self) -> crate::I64Vec3 {
+        crate::I64Vec3::new(self.x as i64, self.y as i64, self.z as i64)
+    }
+
+    /// Casts all elements of `self` to `u64`.
+    #[inline]
+    #[must_use]
+    pub fn as_u64vec3(&self) -> crate::U64Vec3 {
+        crate::U64Vec3::new(self.x as u64, self.y as u64, self.z as u64)
+    }
 }
 
 impl Default for Vec3A {
@@ -1124,7 +1254,7 @@
 }
 
 impl From<Vec4> for Vec3A {
-    /// Creates a `Vec3A` from the `x`, `y` and `z` elements of `self` discarding `w`.
+    /// Creates a [`Vec3A`] from the `x`, `y` and `z` elements of `self` discarding `w`.
     ///
     /// On architectures where SIMD is supported such as SSE2 on `x86_64` this conversion is a noop.
     #[inline]
diff --git a/src/f32/sse2/vec4.rs b/src/f32/sse2/vec4.rs
index f1a1311..3792aae 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::{sse2::*, BVec4A, Vec2, Vec3, Vec3A};
+use crate::{f32::math, sse2::*, BVec4A, Vec2, Vec3, Vec3A};
 
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
@@ -12,10 +12,7 @@
 #[cfg(target_arch = "x86_64")]
 use core::arch::x86_64::*;
 
-#[cfg(feature = "libm")]
-#[allow(unused_imports)]
-use num_traits::Float;
-
+#[repr(C)]
 union UnionCast {
     a: [f32; 4],
     v: Vec4,
@@ -23,13 +20,16 @@
 
 /// Creates a 4-dimensional vector.
 #[inline(always)]
+#[must_use]
 pub const fn vec4(x: f32, y: f32, z: f32, w: f32) -> Vec4 {
     Vec4::new(x, y, z, w)
 }
 
-/// A 4-dimensional vector with SIMD support.
+/// A 4-dimensional vector.
 ///
-/// This type uses 16 byte aligned SIMD vector type for storage.
+/// SIMD vector types are used for storage on supported platforms.
+///
+/// This type is 16 byte aligned.
 #[derive(Clone, Copy)]
 #[repr(transparent)]
 pub struct Vec4(pub(crate) __m128);
@@ -44,31 +44,43 @@
     /// All negative ones.
     pub const NEG_ONE: Self = Self::splat(-1.0);
 
-    /// All NAN.
+    /// All `f32::MIN`.
+    pub const MIN: Self = Self::splat(f32::MIN);
+
+    /// All `f32::MAX`.
+    pub const MAX: Self = Self::splat(f32::MAX);
+
+    /// All `f32::NAN`.
     pub const NAN: Self = Self::splat(f32::NAN);
 
-    /// A unit-length vector pointing along the positive X axis.
+    /// All `f32::INFINITY`.
+    pub const INFINITY: Self = Self::splat(f32::INFINITY);
+
+    /// All `f32::NEG_INFINITY`.
+    pub const NEG_INFINITY: Self = Self::splat(f32::NEG_INFINITY);
+
+    /// A unit vector pointing along the positive X axis.
     pub const X: Self = Self::new(1.0, 0.0, 0.0, 0.0);
 
-    /// A unit-length vector pointing along the positive Y axis.
+    /// A unit vector pointing along the positive Y axis.
     pub const Y: Self = Self::new(0.0, 1.0, 0.0, 0.0);
 
-    /// A unit-length vector pointing along the positive Z axis.
+    /// A unit vector pointing along the positive Z axis.
     pub const Z: Self = Self::new(0.0, 0.0, 1.0, 0.0);
 
-    /// A unit-length vector pointing along the positive W axis.
+    /// A unit vector pointing along the positive W axis.
     pub const W: Self = Self::new(0.0, 0.0, 0.0, 1.0);
 
-    /// A unit-length vector pointing along the negative X axis.
+    /// A unit vector pointing along the negative X axis.
     pub const NEG_X: Self = Self::new(-1.0, 0.0, 0.0, 0.0);
 
-    /// A unit-length vector pointing along the negative Y axis.
+    /// A unit vector pointing along the negative Y axis.
     pub const NEG_Y: Self = Self::new(0.0, -1.0, 0.0, 0.0);
 
-    /// A unit-length vector pointing along the negative Z axis.
+    /// A unit vector pointing along the negative Z axis.
     pub const NEG_Z: Self = Self::new(0.0, 0.0, -1.0, 0.0);
 
-    /// A unit-length vector pointing along the negative W axis.
+    /// A unit vector pointing along the negative W axis.
     pub const NEG_W: Self = Self::new(0.0, 0.0, 0.0, -1.0);
 
     /// The unit axes.
@@ -76,12 +88,14 @@
 
     /// Creates a new vector.
     #[inline(always)]
+    #[must_use]
     pub const fn new(x: f32, y: f32, z: f32, w: f32) -> Self {
         unsafe { UnionCast { a: [x, y, z, w] }.v }
     }
 
     /// Creates a vector with all elements set to `v`.
     #[inline]
+    #[must_use]
     pub const fn splat(v: f32) -> Self {
         unsafe { UnionCast { a: [v; 4] }.v }
     }
@@ -92,6 +106,7 @@
     /// A true element in the mask uses the corresponding element from `if_true`, and false
     /// uses the element from `if_false`.
     #[inline]
+    #[must_use]
     pub fn select(mask: BVec4A, if_true: Self, if_false: Self) -> Self {
         Self(unsafe {
             _mm_or_ps(
@@ -103,12 +118,14 @@
 
     /// Creates a new vector from an array.
     #[inline]
+    #[must_use]
     pub const fn from_array(a: [f32; 4]) -> Self {
         Self::new(a[0], a[1], a[2], a[3])
     }
 
     /// `[x, y, z, w]`
     #[inline]
+    #[must_use]
     pub const fn to_array(&self) -> [f32; 4] {
         unsafe { *(self as *const Vec4 as *const [f32; 4]) }
     }
@@ -119,6 +136,7 @@
     ///
     /// Panics if `slice` is less than 4 elements long.
     #[inline]
+    #[must_use]
     pub const fn from_slice(slice: &[f32]) -> Self {
         Self::new(slice[0], slice[1], slice[2], slice[3])
     }
@@ -136,12 +154,13 @@
         }
     }
 
-    /// Creates a 2D vector from the `x`, `y` and `z` elements of `self`, discarding `w`.
+    /// Creates a 3D vector from the `x`, `y` and `z` elements of `self`, discarding `w`.
     ///
-    /// Truncation to `Vec3` may also be performed by using `self.xyz()` or `Vec3::from()`.
+    /// Truncation to [`Vec3`] may also be performed by using [`self.xyz()`][crate::swizzles::Vec4Swizzles::xyz()].
     ///
-    /// To truncate to `Vec3A` use `Vec3A::from()`.
+    /// To truncate to [`Vec3A`] use [`Vec3A::from()`].
     #[inline]
+    #[must_use]
     pub fn truncate(self) -> Vec3 {
         use crate::swizzles::Vec4Swizzles;
         self.xyz()
@@ -149,12 +168,14 @@
 
     /// Computes the dot product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn dot(self, rhs: Self) -> f32 {
         unsafe { dot4(self.0, rhs.0) }
     }
 
     /// Returns a vector where every component is the dot product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn dot_into_vec(self, rhs: Self) -> Self {
         Self(unsafe { dot4_into_m128(self.0, rhs.0) })
     }
@@ -163,6 +184,7 @@
     ///
     /// In other words this computes `[self.x.min(rhs.x), self.y.min(rhs.y), ..]`.
     #[inline]
+    #[must_use]
     pub fn min(self, rhs: Self) -> Self {
         Self(unsafe { _mm_min_ps(self.0, rhs.0) })
     }
@@ -171,6 +193,7 @@
     ///
     /// In other words this computes `[self.x.max(rhs.x), self.y.max(rhs.y), ..]`.
     #[inline]
+    #[must_use]
     pub fn max(self, rhs: Self) -> Self {
         Self(unsafe { _mm_max_ps(self.0, rhs.0) })
     }
@@ -183,6 +206,7 @@
     ///
     /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn clamp(self, min: Self, max: Self) -> Self {
         glam_assert!(min.cmple(max).all(), "clamp: expected min <= max");
         self.max(min).min(max)
@@ -192,6 +216,7 @@
     ///
     /// In other words this computes `min(x, y, ..)`.
     #[inline]
+    #[must_use]
     pub fn min_element(self) -> f32 {
         unsafe {
             let v = self.0;
@@ -205,6 +230,7 @@
     ///
     /// In other words this computes `max(x, y, ..)`.
     #[inline]
+    #[must_use]
     pub fn max_element(self) -> f32 {
         unsafe {
             let v = self.0;
@@ -220,6 +246,7 @@
     /// In other words, this computes `[self.x == rhs.x, self.y == rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpeq(self, rhs: Self) -> BVec4A {
         BVec4A(unsafe { _mm_cmpeq_ps(self.0, rhs.0) })
     }
@@ -230,6 +257,7 @@
     /// In other words this computes `[self.x != rhs.x, self.y != rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpne(self, rhs: Self) -> BVec4A {
         BVec4A(unsafe { _mm_cmpneq_ps(self.0, rhs.0) })
     }
@@ -240,6 +268,7 @@
     /// In other words this computes `[self.x >= rhs.x, self.y >= rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpge(self, rhs: Self) -> BVec4A {
         BVec4A(unsafe { _mm_cmpge_ps(self.0, rhs.0) })
     }
@@ -250,6 +279,7 @@
     /// In other words this computes `[self.x > rhs.x, self.y > rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpgt(self, rhs: Self) -> BVec4A {
         BVec4A(unsafe { _mm_cmpgt_ps(self.0, rhs.0) })
     }
@@ -260,6 +290,7 @@
     /// In other words this computes `[self.x <= rhs.x, self.y <= rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmple(self, rhs: Self) -> BVec4A {
         BVec4A(unsafe { _mm_cmple_ps(self.0, rhs.0) })
     }
@@ -270,12 +301,14 @@
     /// In other words this computes `[self.x < rhs.x, self.y < rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmplt(self, rhs: Self) -> BVec4A {
         BVec4A(unsafe { _mm_cmplt_ps(self.0, rhs.0) })
     }
 
     /// Returns a vector containing the absolute value of each element of `self`.
     #[inline]
+    #[must_use]
     pub fn abs(self) -> Self {
         Self(unsafe { crate::sse2::m128_abs(self.0) })
     }
@@ -286,6 +319,7 @@
     /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
     /// - `NAN` if the number is `NAN`
     #[inline]
+    #[must_use]
     pub fn signum(self) -> Self {
         unsafe {
             let result = Self(_mm_or_ps(_mm_and_ps(self.0, Self::NEG_ONE.0), Self::ONE.0));
@@ -296,6 +330,7 @@
 
     /// Returns a vector with signs of `rhs` and the magnitudes of `self`.
     #[inline]
+    #[must_use]
     pub fn copysign(self, rhs: Self) -> Self {
         unsafe {
             let mask = Self::splat(-0.0);
@@ -311,6 +346,7 @@
     /// A negative element results in a `1` bit and a positive element in a `0` bit.  Element `x` goes
     /// into the first lowest bit, element `y` into the second, etc.
     #[inline]
+    #[must_use]
     pub fn is_negative_bitmask(self) -> u32 {
         unsafe { _mm_movemask_ps(self.0) as u32 }
     }
@@ -318,12 +354,14 @@
     /// Returns `true` if, and only if, all elements are finite.  If any element is either
     /// `NaN`, positive or negative infinity, this will return `false`.
     #[inline]
+    #[must_use]
     pub fn is_finite(self) -> bool {
         self.x.is_finite() && self.y.is_finite() && self.z.is_finite() && self.w.is_finite()
     }
 
     /// Returns `true` if any elements are `NaN`.
     #[inline]
+    #[must_use]
     pub fn is_nan(self) -> bool {
         self.is_nan_mask().any()
     }
@@ -332,6 +370,7 @@
     ///
     /// In other words, this computes `[x.is_nan(), y.is_nan(), z.is_nan(), w.is_nan()]`.
     #[inline]
+    #[must_use]
     pub fn is_nan_mask(self) -> BVec4A {
         BVec4A(unsafe { _mm_cmpunord_ps(self.0, self.0) })
     }
@@ -339,6 +378,7 @@
     /// Computes the length of `self`.
     #[doc(alias = "magnitude")]
     #[inline]
+    #[must_use]
     pub fn length(self) -> f32 {
         unsafe {
             let dot = dot4_in_x(self.0, self.0);
@@ -351,6 +391,7 @@
     /// This is faster than `length()` as it avoids a square root operation.
     #[doc(alias = "magnitude2")]
     #[inline]
+    #[must_use]
     pub fn length_squared(self) -> f32 {
         self.dot(self)
     }
@@ -359,6 +400,7 @@
     ///
     /// For valid results, `self` must _not_ be of length zero.
     #[inline]
+    #[must_use]
     pub fn length_recip(self) -> f32 {
         unsafe {
             let dot = dot4_in_x(self.0, self.0);
@@ -368,27 +410,55 @@
 
     /// Computes the Euclidean distance between two points in space.
     #[inline]
+    #[must_use]
     pub fn distance(self, rhs: Self) -> f32 {
         (self - rhs).length()
     }
 
     /// Compute the squared euclidean distance between two points in space.
     #[inline]
+    #[must_use]
     pub fn distance_squared(self, rhs: Self) -> f32 {
         (self - rhs).length_squared()
     }
 
+    /// Returns the element-wise quotient of [Euclidean division] of `self` by `rhs`.
+    #[inline]
+    #[must_use]
+    pub fn div_euclid(self, rhs: Self) -> Self {
+        Self::new(
+            math::div_euclid(self.x, rhs.x),
+            math::div_euclid(self.y, rhs.y),
+            math::div_euclid(self.z, rhs.z),
+            math::div_euclid(self.w, rhs.w),
+        )
+    }
+
+    /// Returns the element-wise remainder of [Euclidean division] of `self` by `rhs`.
+    ///
+    /// [Euclidean division]: f32::rem_euclid
+    #[inline]
+    #[must_use]
+    pub fn rem_euclid(self, rhs: Self) -> Self {
+        Self::new(
+            math::rem_euclid(self.x, rhs.x),
+            math::rem_euclid(self.y, rhs.y),
+            math::rem_euclid(self.z, rhs.z),
+            math::rem_euclid(self.w, rhs.w),
+        )
+    }
+
     /// Returns `self` normalized to length 1.0.
     ///
     /// For valid results, `self` must _not_ be of length zero, nor very close to zero.
     ///
-    /// See also [`Self::try_normalize`] and [`Self::normalize_or_zero`].
+    /// See also [`Self::try_normalize()`] and [`Self::normalize_or_zero()`].
     ///
     /// Panics
     ///
     /// Will panic if `self` is zero length when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn normalize(self) -> Self {
         unsafe {
             let length = _mm_sqrt_ps(dot4_into_m128(self.0, self.0));
@@ -404,9 +474,9 @@
     /// In particular, if the input is zero (or very close to zero), or non-finite,
     /// the result of this operation will be `None`.
     ///
-    /// See also [`Self::normalize_or_zero`].
-    #[must_use]
+    /// See also [`Self::normalize_or_zero()`].
     #[inline]
+    #[must_use]
     pub fn try_normalize(self) -> Option<Self> {
         let rcp = self.length_recip();
         if rcp.is_finite() && rcp > 0.0 {
@@ -421,9 +491,9 @@
     /// In particular, if the input is zero (or very close to zero), or non-finite,
     /// the result of this operation will be zero.
     ///
-    /// See also [`Self::try_normalize`].
-    #[must_use]
+    /// See also [`Self::try_normalize()`].
     #[inline]
+    #[must_use]
     pub fn normalize_or_zero(self) -> Self {
         let rcp = self.length_recip();
         if rcp.is_finite() && rcp > 0.0 {
@@ -437,9 +507,10 @@
     ///
     /// Uses a precision threshold of `1e-6`.
     #[inline]
+    #[must_use]
     pub fn is_normalized(self) -> bool {
         // TODO: do something with epsilon
-        (self.length_squared() - 1.0).abs() <= 1e-4
+        math::abs(self.length_squared() - 1.0) <= 1e-4
     }
 
     /// Returns the vector projection of `self` onto `rhs`.
@@ -449,8 +520,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` is zero length when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn project_onto(self, rhs: Self) -> Self {
         let other_len_sq_rcp = rhs.dot(rhs).recip();
         glam_assert!(other_len_sq_rcp.is_finite());
@@ -467,8 +538,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` has a length of zero when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn reject_from(self, rhs: Self) -> Self {
         self - self.project_onto(rhs)
     }
@@ -480,8 +551,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` is not normalized when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn project_onto_normalized(self, rhs: Self) -> Self {
         glam_assert!(rhs.is_normalized());
         rhs * self.dot(rhs)
@@ -497,8 +568,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` is not normalized when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn reject_from_normalized(self, rhs: Self) -> Self {
         self - self.project_onto_normalized(rhs)
     }
@@ -506,6 +577,7 @@
     /// Returns a vector containing the nearest integer to a number for each element of `self`.
     /// Round half-way cases away from 0.0.
     #[inline]
+    #[must_use]
     pub fn round(self) -> Self {
         Self(unsafe { m128_round(self.0) })
     }
@@ -513,6 +585,7 @@
     /// Returns a vector containing the largest integer less than or equal to a number for each
     /// element of `self`.
     #[inline]
+    #[must_use]
     pub fn floor(self) -> Self {
         Self(unsafe { m128_floor(self.0) })
     }
@@ -520,15 +593,25 @@
     /// Returns a vector containing the smallest integer greater than or equal to a number for
     /// each element of `self`.
     #[inline]
+    #[must_use]
     pub fn ceil(self) -> Self {
         Self(unsafe { m128_ceil(self.0) })
     }
 
+    /// Returns a vector containing the integer part each element of `self`. This means numbers are
+    /// always truncated towards zero.
+    #[inline]
+    #[must_use]
+    pub fn trunc(self) -> Self {
+        Self(unsafe { m128_trunc(self.0) })
+    }
+
     /// Returns a vector containing the fractional part of the vector, e.g. `self -
     /// self.floor()`.
     ///
     /// Note that this is fast but not precise for large numbers.
     #[inline]
+    #[must_use]
     pub fn fract(self) -> Self {
         self - self.floor()
     }
@@ -536,23 +619,31 @@
     /// Returns a vector containing `e^self` (the exponential function) for each element of
     /// `self`.
     #[inline]
+    #[must_use]
     pub fn exp(self) -> Self {
-        Self::new(self.x.exp(), self.y.exp(), self.z.exp(), self.w.exp())
+        Self::new(
+            math::exp(self.x),
+            math::exp(self.y),
+            math::exp(self.z),
+            math::exp(self.w),
+        )
     }
 
     /// Returns a vector containing each element of `self` raised to the power of `n`.
     #[inline]
+    #[must_use]
     pub fn powf(self, n: f32) -> Self {
         Self::new(
-            self.x.powf(n),
-            self.y.powf(n),
-            self.z.powf(n),
-            self.w.powf(n),
+            math::powf(self.x, n),
+            math::powf(self.y, n),
+            math::powf(self.z, n),
+            math::powf(self.w, n),
         )
     }
 
     /// Returns a vector containing the reciprocal `1.0/n` of each element of `self`.
     #[inline]
+    #[must_use]
     pub fn recip(self) -> Self {
         Self(unsafe { _mm_div_ps(Self::ONE.0, self.0) })
     }
@@ -564,6 +655,7 @@
     /// extrapolated.
     #[doc(alias = "mix")]
     #[inline]
+    #[must_use]
     pub fn lerp(self, rhs: Self, s: f32) -> Self {
         self + ((rhs - self) * s)
     }
@@ -578,6 +670,7 @@
     /// For more see
     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
     #[inline]
+    #[must_use]
     pub fn abs_diff_eq(self, rhs: Self, max_abs_diff: f32) -> bool {
         self.sub(rhs).abs().cmple(Self::splat(max_abs_diff)).all()
     }
@@ -588,33 +681,38 @@
     ///
     /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn clamp_length(self, min: f32, max: f32) -> Self {
         glam_assert!(min <= max);
         let length_sq = self.length_squared();
         if length_sq < min * min {
-            self * (length_sq.sqrt().recip() * min)
+            min * (self / math::sqrt(length_sq))
         } else if length_sq > max * max {
-            self * (length_sq.sqrt().recip() * max)
+            max * (self / math::sqrt(length_sq))
         } else {
             self
         }
     }
 
     /// Returns a vector with a length no more than `max`
+    #[inline]
+    #[must_use]
     pub fn clamp_length_max(self, max: f32) -> Self {
         let length_sq = self.length_squared();
         if length_sq > max * max {
-            self * (length_sq.sqrt().recip() * max)
+            max * (self / math::sqrt(length_sq))
         } else {
             self
         }
     }
 
     /// Returns a vector with a length no less than `min`
+    #[inline]
+    #[must_use]
     pub fn clamp_length_min(self, min: f32) -> Self {
         let length_sq = self.length_squared();
         if length_sq < min * min {
-            self * (length_sq.sqrt().recip() * min)
+            min * (self / math::sqrt(length_sq))
         } else {
             self
         }
@@ -628,6 +726,7 @@
     /// and will be heavily dependant on designing algorithms with specific target hardware in
     /// mind.
     #[inline]
+    #[must_use]
     pub fn mul_add(self, a: Self, b: Self) -> Self {
         #[cfg(target_feature = "fma")]
         unsafe {
@@ -635,30 +734,61 @@
         }
         #[cfg(not(target_feature = "fma"))]
         Self::new(
-            self.x.mul_add(a.x, b.x),
-            self.y.mul_add(a.y, b.y),
-            self.z.mul_add(a.z, b.z),
-            self.w.mul_add(a.w, b.w),
+            math::mul_add(self.x, a.x, b.x),
+            math::mul_add(self.y, a.y, b.y),
+            math::mul_add(self.z, a.z, b.z),
+            math::mul_add(self.w, a.w, b.w),
         )
     }
 
     /// Casts all elements of `self` to `f64`.
     #[inline]
+    #[must_use]
     pub fn as_dvec4(&self) -> crate::DVec4 {
         crate::DVec4::new(self.x as f64, self.y as f64, self.z as f64, self.w as f64)
     }
 
+    /// Casts all elements of `self` to `i16`.
+    #[inline]
+    #[must_use]
+    pub fn as_i16vec4(&self) -> crate::I16Vec4 {
+        crate::I16Vec4::new(self.x as i16, self.y as i16, self.z as i16, self.w as i16)
+    }
+
+    /// Casts all elements of `self` to `u16`.
+    #[inline]
+    #[must_use]
+    pub fn as_u16vec4(&self) -> crate::U16Vec4 {
+        crate::U16Vec4::new(self.x as u16, self.y as u16, self.z as u16, self.w as u16)
+    }
+
     /// Casts all elements of `self` to `i32`.
     #[inline]
+    #[must_use]
     pub fn as_ivec4(&self) -> crate::IVec4 {
         crate::IVec4::new(self.x as i32, self.y as i32, self.z as i32, self.w as i32)
     }
 
     /// Casts all elements of `self` to `u32`.
     #[inline]
+    #[must_use]
     pub fn as_uvec4(&self) -> crate::UVec4 {
         crate::UVec4::new(self.x as u32, self.y as u32, self.z as u32, self.w as u32)
     }
+
+    /// Casts all elements of `self` to `i64`.
+    #[inline]
+    #[must_use]
+    pub fn as_i64vec4(&self) -> crate::I64Vec4 {
+        crate::I64Vec4::new(self.x as i64, self.y as i64, self.z as i64, self.w as i64)
+    }
+
+    /// Casts all elements of `self` to `u64`.
+    #[inline]
+    #[must_use]
+    pub fn as_u64vec4(&self) -> crate::U64Vec4 {
+        crate::U64Vec4::new(self.x as u64, self.y as u64, self.z as u64, self.w as u64)
+    }
 }
 
 impl Default for Vec4 {
diff --git a/src/f32/vec2.rs b/src/f32/vec2.rs
index fc92447..85f7fbd 100644
--- a/src/f32/vec2.rs
+++ b/src/f32/vec2.rs
@@ -1,18 +1,15 @@
 // Generated from vec.rs.tera template. Edit the template, not the generated file.
 
-use crate::{BVec2, Vec3};
+use crate::{f32::math, BVec2, Vec3};
 
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
 use core::iter::{Product, Sum};
 use core::{f32, ops::*};
 
-#[cfg(feature = "libm")]
-#[allow(unused_imports)]
-use num_traits::Float;
-
 /// Creates a 2-dimensional vector.
 #[inline(always)]
+#[must_use]
 pub const fn vec2(x: f32, y: f32) -> Vec2 {
     Vec2::new(x, y)
 }
@@ -37,19 +34,31 @@
     /// All negative ones.
     pub const NEG_ONE: Self = Self::splat(-1.0);
 
-    /// All NAN.
+    /// All `f32::MIN`.
+    pub const MIN: Self = Self::splat(f32::MIN);
+
+    /// All `f32::MAX`.
+    pub const MAX: Self = Self::splat(f32::MAX);
+
+    /// All `f32::NAN`.
     pub const NAN: Self = Self::splat(f32::NAN);
 
-    /// A unit-length vector pointing along the positive X axis.
+    /// All `f32::INFINITY`.
+    pub const INFINITY: Self = Self::splat(f32::INFINITY);
+
+    /// All `f32::NEG_INFINITY`.
+    pub const NEG_INFINITY: Self = Self::splat(f32::NEG_INFINITY);
+
+    /// A unit vector pointing along the positive X axis.
     pub const X: Self = Self::new(1.0, 0.0);
 
-    /// A unit-length vector pointing along the positive Y axis.
+    /// A unit vector pointing along the positive Y axis.
     pub const Y: Self = Self::new(0.0, 1.0);
 
-    /// A unit-length vector pointing along the negative X axis.
+    /// A unit vector pointing along the negative X axis.
     pub const NEG_X: Self = Self::new(-1.0, 0.0);
 
-    /// A unit-length vector pointing along the negative Y axis.
+    /// A unit vector pointing along the negative Y axis.
     pub const NEG_Y: Self = Self::new(0.0, -1.0);
 
     /// The unit axes.
@@ -57,12 +66,14 @@
 
     /// Creates a new vector.
     #[inline(always)]
+    #[must_use]
     pub const fn new(x: f32, y: f32) -> Self {
         Self { x, y }
     }
 
     /// Creates a vector with all elements set to `v`.
     #[inline]
+    #[must_use]
     pub const fn splat(v: f32) -> Self {
         Self { x: v, y: v }
     }
@@ -73,21 +84,24 @@
     /// A true element in the mask uses the corresponding element from `if_true`, and false
     /// uses the element from `if_false`.
     #[inline]
+    #[must_use]
     pub fn select(mask: BVec2, if_true: Self, if_false: Self) -> Self {
         Self {
-            x: if mask.x { if_true.x } else { if_false.x },
-            y: if mask.y { if_true.y } else { if_false.y },
+            x: if mask.test(0) { if_true.x } else { if_false.x },
+            y: if mask.test(1) { if_true.y } else { if_false.y },
         }
     }
 
     /// Creates a new vector from an array.
     #[inline]
+    #[must_use]
     pub const fn from_array(a: [f32; 2]) -> Self {
         Self::new(a[0], a[1])
     }
 
     /// `[x, y]`
     #[inline]
+    #[must_use]
     pub const fn to_array(&self) -> [f32; 2] {
         [self.x, self.y]
     }
@@ -98,6 +112,7 @@
     ///
     /// Panics if `slice` is less than 2 elements long.
     #[inline]
+    #[must_use]
     pub const fn from_slice(slice: &[f32]) -> Self {
         Self::new(slice[0], slice[1])
     }
@@ -115,18 +130,21 @@
 
     /// Creates a 3D vector from `self` and the given `z` value.
     #[inline]
+    #[must_use]
     pub const fn extend(self, z: f32) -> Vec3 {
         Vec3::new(self.x, self.y, z)
     }
 
     /// Computes the dot product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn dot(self, rhs: Self) -> f32 {
         (self.x * rhs.x) + (self.y * rhs.y)
     }
 
     /// Returns a vector where every component is the dot product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn dot_into_vec(self, rhs: Self) -> Self {
         Self::splat(self.dot(rhs))
     }
@@ -135,6 +153,7 @@
     ///
     /// In other words this computes `[self.x.min(rhs.x), self.y.min(rhs.y), ..]`.
     #[inline]
+    #[must_use]
     pub fn min(self, rhs: Self) -> Self {
         Self {
             x: self.x.min(rhs.x),
@@ -146,6 +165,7 @@
     ///
     /// In other words this computes `[self.x.max(rhs.x), self.y.max(rhs.y), ..]`.
     #[inline]
+    #[must_use]
     pub fn max(self, rhs: Self) -> Self {
         Self {
             x: self.x.max(rhs.x),
@@ -161,6 +181,7 @@
     ///
     /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn clamp(self, min: Self, max: Self) -> Self {
         glam_assert!(min.cmple(max).all(), "clamp: expected min <= max");
         self.max(min).min(max)
@@ -170,6 +191,7 @@
     ///
     /// In other words this computes `min(x, y, ..)`.
     #[inline]
+    #[must_use]
     pub fn min_element(self) -> f32 {
         self.x.min(self.y)
     }
@@ -178,6 +200,7 @@
     ///
     /// In other words this computes `max(x, y, ..)`.
     #[inline]
+    #[must_use]
     pub fn max_element(self) -> f32 {
         self.x.max(self.y)
     }
@@ -188,6 +211,7 @@
     /// In other words, this computes `[self.x == rhs.x, self.y == rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpeq(self, rhs: Self) -> BVec2 {
         BVec2::new(self.x.eq(&rhs.x), self.y.eq(&rhs.y))
     }
@@ -198,6 +222,7 @@
     /// In other words this computes `[self.x != rhs.x, self.y != rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpne(self, rhs: Self) -> BVec2 {
         BVec2::new(self.x.ne(&rhs.x), self.y.ne(&rhs.y))
     }
@@ -208,6 +233,7 @@
     /// In other words this computes `[self.x >= rhs.x, self.y >= rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpge(self, rhs: Self) -> BVec2 {
         BVec2::new(self.x.ge(&rhs.x), self.y.ge(&rhs.y))
     }
@@ -218,6 +244,7 @@
     /// In other words this computes `[self.x > rhs.x, self.y > rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpgt(self, rhs: Self) -> BVec2 {
         BVec2::new(self.x.gt(&rhs.x), self.y.gt(&rhs.y))
     }
@@ -228,6 +255,7 @@
     /// In other words this computes `[self.x <= rhs.x, self.y <= rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmple(self, rhs: Self) -> BVec2 {
         BVec2::new(self.x.le(&rhs.x), self.y.le(&rhs.y))
     }
@@ -238,16 +266,18 @@
     /// In other words this computes `[self.x < rhs.x, self.y < rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmplt(self, rhs: Self) -> BVec2 {
         BVec2::new(self.x.lt(&rhs.x), self.y.lt(&rhs.y))
     }
 
     /// Returns a vector containing the absolute value of each element of `self`.
     #[inline]
+    #[must_use]
     pub fn abs(self) -> Self {
         Self {
-            x: self.x.abs(),
-            y: self.y.abs(),
+            x: math::abs(self.x),
+            y: math::abs(self.y),
         }
     }
 
@@ -257,19 +287,21 @@
     /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
     /// - `NAN` if the number is `NAN`
     #[inline]
+    #[must_use]
     pub fn signum(self) -> Self {
         Self {
-            x: self.x.signum(),
-            y: self.y.signum(),
+            x: math::signum(self.x),
+            y: math::signum(self.y),
         }
     }
 
     /// Returns a vector with signs of `rhs` and the magnitudes of `self`.
     #[inline]
+    #[must_use]
     pub fn copysign(self, rhs: Self) -> Self {
         Self {
-            x: self.x.copysign(rhs.x),
-            y: self.y.copysign(rhs.y),
+            x: math::copysign(self.x, rhs.x),
+            y: math::copysign(self.y, rhs.y),
         }
     }
 
@@ -278,6 +310,7 @@
     /// A negative element results in a `1` bit and a positive element in a `0` bit.  Element `x` goes
     /// into the first lowest bit, element `y` into the second, etc.
     #[inline]
+    #[must_use]
     pub fn is_negative_bitmask(self) -> u32 {
         (self.x.is_sign_negative() as u32) | (self.y.is_sign_negative() as u32) << 1
     }
@@ -285,12 +318,14 @@
     /// Returns `true` if, and only if, all elements are finite.  If any element is either
     /// `NaN`, positive or negative infinity, this will return `false`.
     #[inline]
+    #[must_use]
     pub fn is_finite(self) -> bool {
         self.x.is_finite() && self.y.is_finite()
     }
 
     /// Returns `true` if any elements are `NaN`.
     #[inline]
+    #[must_use]
     pub fn is_nan(self) -> bool {
         self.x.is_nan() || self.y.is_nan()
     }
@@ -299,6 +334,7 @@
     ///
     /// In other words, this computes `[x.is_nan(), y.is_nan(), z.is_nan(), w.is_nan()]`.
     #[inline]
+    #[must_use]
     pub fn is_nan_mask(self) -> BVec2 {
         BVec2::new(self.x.is_nan(), self.y.is_nan())
     }
@@ -306,8 +342,9 @@
     /// Computes the length of `self`.
     #[doc(alias = "magnitude")]
     #[inline]
+    #[must_use]
     pub fn length(self) -> f32 {
-        self.dot(self).sqrt()
+        math::sqrt(self.dot(self))
     }
 
     /// Computes the squared length of `self`.
@@ -315,6 +352,7 @@
     /// This is faster than `length()` as it avoids a square root operation.
     #[doc(alias = "magnitude2")]
     #[inline]
+    #[must_use]
     pub fn length_squared(self) -> f32 {
         self.dot(self)
     }
@@ -323,33 +361,58 @@
     ///
     /// For valid results, `self` must _not_ be of length zero.
     #[inline]
+    #[must_use]
     pub fn length_recip(self) -> f32 {
         self.length().recip()
     }
 
     /// Computes the Euclidean distance between two points in space.
     #[inline]
+    #[must_use]
     pub fn distance(self, rhs: Self) -> f32 {
         (self - rhs).length()
     }
 
     /// Compute the squared euclidean distance between two points in space.
     #[inline]
+    #[must_use]
     pub fn distance_squared(self, rhs: Self) -> f32 {
         (self - rhs).length_squared()
     }
 
+    /// Returns the element-wise quotient of [Euclidean division] of `self` by `rhs`.
+    #[inline]
+    #[must_use]
+    pub fn div_euclid(self, rhs: Self) -> Self {
+        Self::new(
+            math::div_euclid(self.x, rhs.x),
+            math::div_euclid(self.y, rhs.y),
+        )
+    }
+
+    /// Returns the element-wise remainder of [Euclidean division] of `self` by `rhs`.
+    ///
+    /// [Euclidean division]: f32::rem_euclid
+    #[inline]
+    #[must_use]
+    pub fn rem_euclid(self, rhs: Self) -> Self {
+        Self::new(
+            math::rem_euclid(self.x, rhs.x),
+            math::rem_euclid(self.y, rhs.y),
+        )
+    }
+
     /// Returns `self` normalized to length 1.0.
     ///
     /// For valid results, `self` must _not_ be of length zero, nor very close to zero.
     ///
-    /// See also [`Self::try_normalize`] and [`Self::normalize_or_zero`].
+    /// See also [`Self::try_normalize()`] and [`Self::normalize_or_zero()`].
     ///
     /// Panics
     ///
     /// Will panic if `self` is zero length when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn normalize(self) -> Self {
         #[allow(clippy::let_and_return)]
         let normalized = self.mul(self.length_recip());
@@ -362,9 +425,9 @@
     /// In particular, if the input is zero (or very close to zero), or non-finite,
     /// the result of this operation will be `None`.
     ///
-    /// See also [`Self::normalize_or_zero`].
-    #[must_use]
+    /// See also [`Self::normalize_or_zero()`].
     #[inline]
+    #[must_use]
     pub fn try_normalize(self) -> Option<Self> {
         let rcp = self.length_recip();
         if rcp.is_finite() && rcp > 0.0 {
@@ -379,9 +442,9 @@
     /// In particular, if the input is zero (or very close to zero), or non-finite,
     /// the result of this operation will be zero.
     ///
-    /// See also [`Self::try_normalize`].
-    #[must_use]
+    /// See also [`Self::try_normalize()`].
     #[inline]
+    #[must_use]
     pub fn normalize_or_zero(self) -> Self {
         let rcp = self.length_recip();
         if rcp.is_finite() && rcp > 0.0 {
@@ -395,9 +458,10 @@
     ///
     /// Uses a precision threshold of `1e-6`.
     #[inline]
+    #[must_use]
     pub fn is_normalized(self) -> bool {
         // TODO: do something with epsilon
-        (self.length_squared() - 1.0).abs() <= 1e-4
+        math::abs(self.length_squared() - 1.0) <= 1e-4
     }
 
     /// Returns the vector projection of `self` onto `rhs`.
@@ -407,8 +471,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` is zero length when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn project_onto(self, rhs: Self) -> Self {
         let other_len_sq_rcp = rhs.dot(rhs).recip();
         glam_assert!(other_len_sq_rcp.is_finite());
@@ -425,8 +489,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` has a length of zero when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn reject_from(self, rhs: Self) -> Self {
         self - self.project_onto(rhs)
     }
@@ -438,8 +502,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` is not normalized when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn project_onto_normalized(self, rhs: Self) -> Self {
         glam_assert!(rhs.is_normalized());
         rhs * self.dot(rhs)
@@ -455,8 +519,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` is not normalized when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn reject_from_normalized(self, rhs: Self) -> Self {
         self - self.project_onto_normalized(rhs)
     }
@@ -464,30 +528,44 @@
     /// Returns a vector containing the nearest integer to a number for each element of `self`.
     /// Round half-way cases away from 0.0.
     #[inline]
+    #[must_use]
     pub fn round(self) -> Self {
         Self {
-            x: self.x.round(),
-            y: self.y.round(),
+            x: math::round(self.x),
+            y: math::round(self.y),
         }
     }
 
     /// Returns a vector containing the largest integer less than or equal to a number for each
     /// element of `self`.
     #[inline]
+    #[must_use]
     pub fn floor(self) -> Self {
         Self {
-            x: self.x.floor(),
-            y: self.y.floor(),
+            x: math::floor(self.x),
+            y: math::floor(self.y),
         }
     }
 
     /// Returns a vector containing the smallest integer greater than or equal to a number for
     /// each element of `self`.
     #[inline]
+    #[must_use]
     pub fn ceil(self) -> Self {
         Self {
-            x: self.x.ceil(),
-            y: self.y.ceil(),
+            x: math::ceil(self.x),
+            y: math::ceil(self.y),
+        }
+    }
+
+    /// Returns a vector containing the integer part each element of `self`. This means numbers are
+    /// always truncated towards zero.
+    #[inline]
+    #[must_use]
+    pub fn trunc(self) -> Self {
+        Self {
+            x: math::trunc(self.x),
+            y: math::trunc(self.y),
         }
     }
 
@@ -496,6 +574,7 @@
     ///
     /// Note that this is fast but not precise for large numbers.
     #[inline]
+    #[must_use]
     pub fn fract(self) -> Self {
         self - self.floor()
     }
@@ -503,22 +582,25 @@
     /// Returns a vector containing `e^self` (the exponential function) for each element of
     /// `self`.
     #[inline]
+    #[must_use]
     pub fn exp(self) -> Self {
-        Self::new(self.x.exp(), self.y.exp())
+        Self::new(math::exp(self.x), math::exp(self.y))
     }
 
     /// Returns a vector containing each element of `self` raised to the power of `n`.
     #[inline]
+    #[must_use]
     pub fn powf(self, n: f32) -> Self {
-        Self::new(self.x.powf(n), self.y.powf(n))
+        Self::new(math::powf(self.x, n), math::powf(self.y, n))
     }
 
     /// Returns a vector containing the reciprocal `1.0/n` of each element of `self`.
     #[inline]
+    #[must_use]
     pub fn recip(self) -> Self {
         Self {
-            x: self.x.recip(),
-            y: self.y.recip(),
+            x: 1.0 / self.x,
+            y: 1.0 / self.y,
         }
     }
 
@@ -529,6 +611,7 @@
     /// extrapolated.
     #[doc(alias = "mix")]
     #[inline]
+    #[must_use]
     pub fn lerp(self, rhs: Self, s: f32) -> Self {
         self + ((rhs - self) * s)
     }
@@ -543,6 +626,7 @@
     /// For more see
     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
     #[inline]
+    #[must_use]
     pub fn abs_diff_eq(self, rhs: Self, max_abs_diff: f32) -> bool {
         self.sub(rhs).abs().cmple(Self::splat(max_abs_diff)).all()
     }
@@ -553,33 +637,38 @@
     ///
     /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn clamp_length(self, min: f32, max: f32) -> Self {
         glam_assert!(min <= max);
         let length_sq = self.length_squared();
         if length_sq < min * min {
-            self * (length_sq.sqrt().recip() * min)
+            min * (self / math::sqrt(length_sq))
         } else if length_sq > max * max {
-            self * (length_sq.sqrt().recip() * max)
+            max * (self / math::sqrt(length_sq))
         } else {
             self
         }
     }
 
     /// Returns a vector with a length no more than `max`
+    #[inline]
+    #[must_use]
     pub fn clamp_length_max(self, max: f32) -> Self {
         let length_sq = self.length_squared();
         if length_sq > max * max {
-            self * (length_sq.sqrt().recip() * max)
+            max * (self / math::sqrt(length_sq))
         } else {
             self
         }
     }
 
     /// Returns a vector with a length no less than `min`
+    #[inline]
+    #[must_use]
     pub fn clamp_length_min(self, min: f32) -> Self {
         let length_sq = self.length_squared();
         if length_sq < min * min {
-            self * (length_sq.sqrt().recip() * min)
+            min * (self / math::sqrt(length_sq))
         } else {
             self
         }
@@ -593,33 +682,50 @@
     /// and will be heavily dependant on designing algorithms with specific target hardware in
     /// mind.
     #[inline]
+    #[must_use]
     pub fn mul_add(self, a: Self, b: Self) -> Self {
-        Self::new(self.x.mul_add(a.x, b.x), self.y.mul_add(a.y, b.y))
+        Self::new(
+            math::mul_add(self.x, a.x, b.x),
+            math::mul_add(self.y, a.y, b.y),
+        )
     }
 
     /// Creates a 2D vector containing `[angle.cos(), angle.sin()]`. This can be used in
-    /// conjunction with the `rotate` method, e.g. `Vec2::from_angle(PI).rotate(Vec2::Y)` will
-    /// create the vector [-1, 0] and rotate `Vec2::Y` around it returning `-Vec2::Y`.
+    /// conjunction with the [`rotate()`][Self::rotate()] method, e.g.
+    /// `Vec2::from_angle(PI).rotate(Vec2::Y)` will create the vector `[-1, 0]`
+    /// and rotate [`Vec2::Y`] around it returning `-Vec2::Y`.
     #[inline]
+    #[must_use]
     pub fn from_angle(angle: f32) -> Self {
-        let (sin, cos) = angle.sin_cos();
+        let (sin, cos) = math::sin_cos(angle);
         Self { x: cos, y: sin }
     }
 
-    /// Returns the angle (in radians) between `self` and `rhs`.
+    /// Returns the angle (in radians) of this vector in the range `[-π, +π]`.
     ///
-    /// The input vectors do not need to be unit length however they must be non-zero.
+    /// The input does not need to be a unit vector however it must be non-zero.
     #[inline]
-    pub fn angle_between(self, rhs: Self) -> f32 {
-        use crate::FloatEx;
-        let angle =
-            (self.dot(rhs) / (self.length_squared() * rhs.length_squared()).sqrt()).acos_approx();
+    #[must_use]
+    pub fn to_angle(self) -> f32 {
+        math::atan2(self.y, self.x)
+    }
 
-        angle * self.perp_dot(rhs).signum()
+    /// Returns the angle (in radians) between `self` and `rhs` in the range `[-π, +π]`.
+    ///
+    /// The inputs do not need to be unit vectors however they must be non-zero.
+    #[inline]
+    #[must_use]
+    pub fn angle_between(self, rhs: Self) -> f32 {
+        let angle = math::acos_approx(
+            self.dot(rhs) / math::sqrt(self.length_squared() * rhs.length_squared()),
+        );
+
+        angle * math::signum(self.perp_dot(rhs))
     }
 
     /// Returns a vector that is equal to `self` rotated by 90 degrees.
     #[inline]
+    #[must_use]
     pub fn perp(self) -> Self {
         Self {
             x: -self.y,
@@ -633,6 +739,7 @@
     #[doc(alias = "cross")]
     #[doc(alias = "determinant")]
     #[inline]
+    #[must_use]
     pub fn perp_dot(self, rhs: Self) -> f32 {
         (self.x * rhs.y) - (self.y * rhs.x)
     }
@@ -640,8 +747,8 @@
     /// Returns `rhs` rotated by the angle of `self`. If `self` is normalized,
     /// then this just rotation. This is what you usually want. Otherwise,
     /// it will be like a rotation with a multiplication by `self`'s length.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn rotate(self, rhs: Self) -> Self {
         Self {
             x: self.x * rhs.x - self.y * rhs.y,
@@ -651,21 +758,52 @@
 
     /// Casts all elements of `self` to `f64`.
     #[inline]
+    #[must_use]
     pub fn as_dvec2(&self) -> crate::DVec2 {
         crate::DVec2::new(self.x as f64, self.y as f64)
     }
 
+    /// Casts all elements of `self` to `i16`.
+    #[inline]
+    #[must_use]
+    pub fn as_i16vec2(&self) -> crate::I16Vec2 {
+        crate::I16Vec2::new(self.x as i16, self.y as i16)
+    }
+
+    /// Casts all elements of `self` to `u16`.
+    #[inline]
+    #[must_use]
+    pub fn as_u16vec2(&self) -> crate::U16Vec2 {
+        crate::U16Vec2::new(self.x as u16, self.y as u16)
+    }
+
     /// Casts all elements of `self` to `i32`.
     #[inline]
+    #[must_use]
     pub fn as_ivec2(&self) -> crate::IVec2 {
         crate::IVec2::new(self.x as i32, self.y as i32)
     }
 
     /// Casts all elements of `self` to `u32`.
     #[inline]
+    #[must_use]
     pub fn as_uvec2(&self) -> crate::UVec2 {
         crate::UVec2::new(self.x as u32, self.y as u32)
     }
+
+    /// Casts all elements of `self` to `i64`.
+    #[inline]
+    #[must_use]
+    pub fn as_i64vec2(&self) -> crate::I64Vec2 {
+        crate::I64Vec2::new(self.x as i64, self.y as i64)
+    }
+
+    /// Casts all elements of `self` to `u64`.
+    #[inline]
+    #[must_use]
+    pub fn as_u64vec2(&self) -> crate::U64Vec2 {
+        crate::U64Vec2::new(self.x as u64, self.y as u64)
+    }
 }
 
 impl Default for Vec2 {
diff --git a/src/f32/vec3.rs b/src/f32/vec3.rs
index 2838a63..8c3af6d 100644
--- a/src/f32/vec3.rs
+++ b/src/f32/vec3.rs
@@ -1,18 +1,15 @@
 // Generated from vec.rs.tera template. Edit the template, not the generated file.
 
-use crate::{BVec3, Vec2, Vec4};
+use crate::{f32::math, BVec3, Vec2, Vec4};
 
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
 use core::iter::{Product, Sum};
 use core::{f32, ops::*};
 
-#[cfg(feature = "libm")]
-#[allow(unused_imports)]
-use num_traits::Float;
-
 /// Creates a 3-dimensional vector.
 #[inline(always)]
+#[must_use]
 pub const fn vec3(x: f32, y: f32, z: f32) -> Vec3 {
     Vec3::new(x, y, z)
 }
@@ -37,25 +34,37 @@
     /// All negative ones.
     pub const NEG_ONE: Self = Self::splat(-1.0);
 
-    /// All NAN.
+    /// All `f32::MIN`.
+    pub const MIN: Self = Self::splat(f32::MIN);
+
+    /// All `f32::MAX`.
+    pub const MAX: Self = Self::splat(f32::MAX);
+
+    /// All `f32::NAN`.
     pub const NAN: Self = Self::splat(f32::NAN);
 
-    /// A unit-length vector pointing along the positive X axis.
+    /// All `f32::INFINITY`.
+    pub const INFINITY: Self = Self::splat(f32::INFINITY);
+
+    /// All `f32::NEG_INFINITY`.
+    pub const NEG_INFINITY: Self = Self::splat(f32::NEG_INFINITY);
+
+    /// A unit vector pointing along the positive X axis.
     pub const X: Self = Self::new(1.0, 0.0, 0.0);
 
-    /// A unit-length vector pointing along the positive Y axis.
+    /// A unit vector pointing along the positive Y axis.
     pub const Y: Self = Self::new(0.0, 1.0, 0.0);
 
-    /// A unit-length vector pointing along the positive Z axis.
+    /// A unit vector pointing along the positive Z axis.
     pub const Z: Self = Self::new(0.0, 0.0, 1.0);
 
-    /// A unit-length vector pointing along the negative X axis.
+    /// A unit vector pointing along the negative X axis.
     pub const NEG_X: Self = Self::new(-1.0, 0.0, 0.0);
 
-    /// A unit-length vector pointing along the negative Y axis.
+    /// A unit vector pointing along the negative Y axis.
     pub const NEG_Y: Self = Self::new(0.0, -1.0, 0.0);
 
-    /// A unit-length vector pointing along the negative Z axis.
+    /// A unit vector pointing along the negative Z axis.
     pub const NEG_Z: Self = Self::new(0.0, 0.0, -1.0);
 
     /// The unit axes.
@@ -63,12 +72,14 @@
 
     /// Creates a new vector.
     #[inline(always)]
+    #[must_use]
     pub const fn new(x: f32, y: f32, z: f32) -> Self {
         Self { x, y, z }
     }
 
     /// Creates a vector with all elements set to `v`.
     #[inline]
+    #[must_use]
     pub const fn splat(v: f32) -> Self {
         Self { x: v, y: v, z: v }
     }
@@ -79,22 +90,25 @@
     /// A true element in the mask uses the corresponding element from `if_true`, and false
     /// uses the element from `if_false`.
     #[inline]
+    #[must_use]
     pub fn select(mask: BVec3, if_true: Self, if_false: Self) -> Self {
         Self {
-            x: if mask.x { if_true.x } else { if_false.x },
-            y: if mask.y { if_true.y } else { if_false.y },
-            z: if mask.z { if_true.z } else { if_false.z },
+            x: if mask.test(0) { if_true.x } else { if_false.x },
+            y: if mask.test(1) { if_true.y } else { if_false.y },
+            z: if mask.test(2) { if_true.z } else { if_false.z },
         }
     }
 
     /// Creates a new vector from an array.
     #[inline]
+    #[must_use]
     pub const fn from_array(a: [f32; 3]) -> Self {
         Self::new(a[0], a[1], a[2])
     }
 
     /// `[x, y, z]`
     #[inline]
+    #[must_use]
     pub const fn to_array(&self) -> [f32; 3] {
         [self.x, self.y, self.z]
     }
@@ -105,6 +119,7 @@
     ///
     /// Panics if `slice` is less than 3 elements long.
     #[inline]
+    #[must_use]
     pub const fn from_slice(slice: &[f32]) -> Self {
         Self::new(slice[0], slice[1], slice[2])
     }
@@ -124,6 +139,7 @@
     /// Internal method for creating a 3D vector from a 4D vector, discarding `w`.
     #[allow(dead_code)]
     #[inline]
+    #[must_use]
     pub(crate) fn from_vec4(v: Vec4) -> Self {
         Self {
             x: v.x,
@@ -134,14 +150,16 @@
 
     /// Creates a 4D vector from `self` and the given `w` value.
     #[inline]
+    #[must_use]
     pub fn extend(self, w: f32) -> Vec4 {
         Vec4::new(self.x, self.y, self.z, w)
     }
 
     /// Creates a 2D vector from the `x` and `y` elements of `self`, discarding `z`.
     ///
-    /// Truncation may also be performed by using `self.xy()` or `Vec2::from()`.
+    /// Truncation may also be performed by using [`self.xy()`][crate::swizzles::Vec3Swizzles::xy()].
     #[inline]
+    #[must_use]
     pub fn truncate(self) -> Vec2 {
         use crate::swizzles::Vec3Swizzles;
         self.xy()
@@ -149,18 +167,21 @@
 
     /// Computes the dot product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn dot(self, rhs: Self) -> f32 {
         (self.x * rhs.x) + (self.y * rhs.y) + (self.z * rhs.z)
     }
 
     /// Returns a vector where every component is the dot product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn dot_into_vec(self, rhs: Self) -> Self {
         Self::splat(self.dot(rhs))
     }
 
     /// Computes the cross product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn cross(self, rhs: Self) -> Self {
         Self {
             x: self.y * rhs.z - rhs.y * self.z,
@@ -173,6 +194,7 @@
     ///
     /// In other words this computes `[self.x.min(rhs.x), self.y.min(rhs.y), ..]`.
     #[inline]
+    #[must_use]
     pub fn min(self, rhs: Self) -> Self {
         Self {
             x: self.x.min(rhs.x),
@@ -185,6 +207,7 @@
     ///
     /// In other words this computes `[self.x.max(rhs.x), self.y.max(rhs.y), ..]`.
     #[inline]
+    #[must_use]
     pub fn max(self, rhs: Self) -> Self {
         Self {
             x: self.x.max(rhs.x),
@@ -201,6 +224,7 @@
     ///
     /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn clamp(self, min: Self, max: Self) -> Self {
         glam_assert!(min.cmple(max).all(), "clamp: expected min <= max");
         self.max(min).min(max)
@@ -210,6 +234,7 @@
     ///
     /// In other words this computes `min(x, y, ..)`.
     #[inline]
+    #[must_use]
     pub fn min_element(self) -> f32 {
         self.x.min(self.y.min(self.z))
     }
@@ -218,6 +243,7 @@
     ///
     /// In other words this computes `max(x, y, ..)`.
     #[inline]
+    #[must_use]
     pub fn max_element(self) -> f32 {
         self.x.max(self.y.max(self.z))
     }
@@ -228,6 +254,7 @@
     /// In other words, this computes `[self.x == rhs.x, self.y == rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpeq(self, rhs: Self) -> BVec3 {
         BVec3::new(self.x.eq(&rhs.x), self.y.eq(&rhs.y), self.z.eq(&rhs.z))
     }
@@ -238,6 +265,7 @@
     /// In other words this computes `[self.x != rhs.x, self.y != rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpne(self, rhs: Self) -> BVec3 {
         BVec3::new(self.x.ne(&rhs.x), self.y.ne(&rhs.y), self.z.ne(&rhs.z))
     }
@@ -248,6 +276,7 @@
     /// In other words this computes `[self.x >= rhs.x, self.y >= rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpge(self, rhs: Self) -> BVec3 {
         BVec3::new(self.x.ge(&rhs.x), self.y.ge(&rhs.y), self.z.ge(&rhs.z))
     }
@@ -258,6 +287,7 @@
     /// In other words this computes `[self.x > rhs.x, self.y > rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpgt(self, rhs: Self) -> BVec3 {
         BVec3::new(self.x.gt(&rhs.x), self.y.gt(&rhs.y), self.z.gt(&rhs.z))
     }
@@ -268,6 +298,7 @@
     /// In other words this computes `[self.x <= rhs.x, self.y <= rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmple(self, rhs: Self) -> BVec3 {
         BVec3::new(self.x.le(&rhs.x), self.y.le(&rhs.y), self.z.le(&rhs.z))
     }
@@ -278,17 +309,19 @@
     /// In other words this computes `[self.x < rhs.x, self.y < rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmplt(self, rhs: Self) -> BVec3 {
         BVec3::new(self.x.lt(&rhs.x), self.y.lt(&rhs.y), self.z.lt(&rhs.z))
     }
 
     /// Returns a vector containing the absolute value of each element of `self`.
     #[inline]
+    #[must_use]
     pub fn abs(self) -> Self {
         Self {
-            x: self.x.abs(),
-            y: self.y.abs(),
-            z: self.z.abs(),
+            x: math::abs(self.x),
+            y: math::abs(self.y),
+            z: math::abs(self.z),
         }
     }
 
@@ -298,21 +331,23 @@
     /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
     /// - `NAN` if the number is `NAN`
     #[inline]
+    #[must_use]
     pub fn signum(self) -> Self {
         Self {
-            x: self.x.signum(),
-            y: self.y.signum(),
-            z: self.z.signum(),
+            x: math::signum(self.x),
+            y: math::signum(self.y),
+            z: math::signum(self.z),
         }
     }
 
     /// Returns a vector with signs of `rhs` and the magnitudes of `self`.
     #[inline]
+    #[must_use]
     pub fn copysign(self, rhs: Self) -> Self {
         Self {
-            x: self.x.copysign(rhs.x),
-            y: self.y.copysign(rhs.y),
-            z: self.z.copysign(rhs.z),
+            x: math::copysign(self.x, rhs.x),
+            y: math::copysign(self.y, rhs.y),
+            z: math::copysign(self.z, rhs.z),
         }
     }
 
@@ -321,6 +356,7 @@
     /// A negative element results in a `1` bit and a positive element in a `0` bit.  Element `x` goes
     /// into the first lowest bit, element `y` into the second, etc.
     #[inline]
+    #[must_use]
     pub fn is_negative_bitmask(self) -> u32 {
         (self.x.is_sign_negative() as u32)
             | (self.y.is_sign_negative() as u32) << 1
@@ -330,12 +366,14 @@
     /// Returns `true` if, and only if, all elements are finite.  If any element is either
     /// `NaN`, positive or negative infinity, this will return `false`.
     #[inline]
+    #[must_use]
     pub fn is_finite(self) -> bool {
         self.x.is_finite() && self.y.is_finite() && self.z.is_finite()
     }
 
     /// Returns `true` if any elements are `NaN`.
     #[inline]
+    #[must_use]
     pub fn is_nan(self) -> bool {
         self.x.is_nan() || self.y.is_nan() || self.z.is_nan()
     }
@@ -344,6 +382,7 @@
     ///
     /// In other words, this computes `[x.is_nan(), y.is_nan(), z.is_nan(), w.is_nan()]`.
     #[inline]
+    #[must_use]
     pub fn is_nan_mask(self) -> BVec3 {
         BVec3::new(self.x.is_nan(), self.y.is_nan(), self.z.is_nan())
     }
@@ -351,8 +390,9 @@
     /// Computes the length of `self`.
     #[doc(alias = "magnitude")]
     #[inline]
+    #[must_use]
     pub fn length(self) -> f32 {
-        self.dot(self).sqrt()
+        math::sqrt(self.dot(self))
     }
 
     /// Computes the squared length of `self`.
@@ -360,6 +400,7 @@
     /// This is faster than `length()` as it avoids a square root operation.
     #[doc(alias = "magnitude2")]
     #[inline]
+    #[must_use]
     pub fn length_squared(self) -> f32 {
         self.dot(self)
     }
@@ -368,33 +409,60 @@
     ///
     /// For valid results, `self` must _not_ be of length zero.
     #[inline]
+    #[must_use]
     pub fn length_recip(self) -> f32 {
         self.length().recip()
     }
 
     /// Computes the Euclidean distance between two points in space.
     #[inline]
+    #[must_use]
     pub fn distance(self, rhs: Self) -> f32 {
         (self - rhs).length()
     }
 
     /// Compute the squared euclidean distance between two points in space.
     #[inline]
+    #[must_use]
     pub fn distance_squared(self, rhs: Self) -> f32 {
         (self - rhs).length_squared()
     }
 
+    /// Returns the element-wise quotient of [Euclidean division] of `self` by `rhs`.
+    #[inline]
+    #[must_use]
+    pub fn div_euclid(self, rhs: Self) -> Self {
+        Self::new(
+            math::div_euclid(self.x, rhs.x),
+            math::div_euclid(self.y, rhs.y),
+            math::div_euclid(self.z, rhs.z),
+        )
+    }
+
+    /// Returns the element-wise remainder of [Euclidean division] of `self` by `rhs`.
+    ///
+    /// [Euclidean division]: f32::rem_euclid
+    #[inline]
+    #[must_use]
+    pub fn rem_euclid(self, rhs: Self) -> Self {
+        Self::new(
+            math::rem_euclid(self.x, rhs.x),
+            math::rem_euclid(self.y, rhs.y),
+            math::rem_euclid(self.z, rhs.z),
+        )
+    }
+
     /// Returns `self` normalized to length 1.0.
     ///
     /// For valid results, `self` must _not_ be of length zero, nor very close to zero.
     ///
-    /// See also [`Self::try_normalize`] and [`Self::normalize_or_zero`].
+    /// See also [`Self::try_normalize()`] and [`Self::normalize_or_zero()`].
     ///
     /// Panics
     ///
     /// Will panic if `self` is zero length when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn normalize(self) -> Self {
         #[allow(clippy::let_and_return)]
         let normalized = self.mul(self.length_recip());
@@ -407,9 +475,9 @@
     /// In particular, if the input is zero (or very close to zero), or non-finite,
     /// the result of this operation will be `None`.
     ///
-    /// See also [`Self::normalize_or_zero`].
-    #[must_use]
+    /// See also [`Self::normalize_or_zero()`].
     #[inline]
+    #[must_use]
     pub fn try_normalize(self) -> Option<Self> {
         let rcp = self.length_recip();
         if rcp.is_finite() && rcp > 0.0 {
@@ -424,9 +492,9 @@
     /// In particular, if the input is zero (or very close to zero), or non-finite,
     /// the result of this operation will be zero.
     ///
-    /// See also [`Self::try_normalize`].
-    #[must_use]
+    /// See also [`Self::try_normalize()`].
     #[inline]
+    #[must_use]
     pub fn normalize_or_zero(self) -> Self {
         let rcp = self.length_recip();
         if rcp.is_finite() && rcp > 0.0 {
@@ -440,9 +508,10 @@
     ///
     /// Uses a precision threshold of `1e-6`.
     #[inline]
+    #[must_use]
     pub fn is_normalized(self) -> bool {
         // TODO: do something with epsilon
-        (self.length_squared() - 1.0).abs() <= 1e-4
+        math::abs(self.length_squared() - 1.0) <= 1e-4
     }
 
     /// Returns the vector projection of `self` onto `rhs`.
@@ -452,8 +521,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` is zero length when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn project_onto(self, rhs: Self) -> Self {
         let other_len_sq_rcp = rhs.dot(rhs).recip();
         glam_assert!(other_len_sq_rcp.is_finite());
@@ -470,8 +539,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` has a length of zero when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn reject_from(self, rhs: Self) -> Self {
         self - self.project_onto(rhs)
     }
@@ -483,8 +552,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` is not normalized when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn project_onto_normalized(self, rhs: Self) -> Self {
         glam_assert!(rhs.is_normalized());
         rhs * self.dot(rhs)
@@ -500,8 +569,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` is not normalized when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn reject_from_normalized(self, rhs: Self) -> Self {
         self - self.project_onto_normalized(rhs)
     }
@@ -509,33 +578,48 @@
     /// Returns a vector containing the nearest integer to a number for each element of `self`.
     /// Round half-way cases away from 0.0.
     #[inline]
+    #[must_use]
     pub fn round(self) -> Self {
         Self {
-            x: self.x.round(),
-            y: self.y.round(),
-            z: self.z.round(),
+            x: math::round(self.x),
+            y: math::round(self.y),
+            z: math::round(self.z),
         }
     }
 
     /// Returns a vector containing the largest integer less than or equal to a number for each
     /// element of `self`.
     #[inline]
+    #[must_use]
     pub fn floor(self) -> Self {
         Self {
-            x: self.x.floor(),
-            y: self.y.floor(),
-            z: self.z.floor(),
+            x: math::floor(self.x),
+            y: math::floor(self.y),
+            z: math::floor(self.z),
         }
     }
 
     /// Returns a vector containing the smallest integer greater than or equal to a number for
     /// each element of `self`.
     #[inline]
+    #[must_use]
     pub fn ceil(self) -> Self {
         Self {
-            x: self.x.ceil(),
-            y: self.y.ceil(),
-            z: self.z.ceil(),
+            x: math::ceil(self.x),
+            y: math::ceil(self.y),
+            z: math::ceil(self.z),
+        }
+    }
+
+    /// Returns a vector containing the integer part each element of `self`. This means numbers are
+    /// always truncated towards zero.
+    #[inline]
+    #[must_use]
+    pub fn trunc(self) -> Self {
+        Self {
+            x: math::trunc(self.x),
+            y: math::trunc(self.y),
+            z: math::trunc(self.z),
         }
     }
 
@@ -544,6 +628,7 @@
     ///
     /// Note that this is fast but not precise for large numbers.
     #[inline]
+    #[must_use]
     pub fn fract(self) -> Self {
         self - self.floor()
     }
@@ -551,23 +636,30 @@
     /// Returns a vector containing `e^self` (the exponential function) for each element of
     /// `self`.
     #[inline]
+    #[must_use]
     pub fn exp(self) -> Self {
-        Self::new(self.x.exp(), self.y.exp(), self.z.exp())
+        Self::new(math::exp(self.x), math::exp(self.y), math::exp(self.z))
     }
 
     /// Returns a vector containing each element of `self` raised to the power of `n`.
     #[inline]
+    #[must_use]
     pub fn powf(self, n: f32) -> Self {
-        Self::new(self.x.powf(n), self.y.powf(n), self.z.powf(n))
+        Self::new(
+            math::powf(self.x, n),
+            math::powf(self.y, n),
+            math::powf(self.z, n),
+        )
     }
 
     /// Returns a vector containing the reciprocal `1.0/n` of each element of `self`.
     #[inline]
+    #[must_use]
     pub fn recip(self) -> Self {
         Self {
-            x: self.x.recip(),
-            y: self.y.recip(),
-            z: self.z.recip(),
+            x: 1.0 / self.x,
+            y: 1.0 / self.y,
+            z: 1.0 / self.z,
         }
     }
 
@@ -578,6 +670,7 @@
     /// extrapolated.
     #[doc(alias = "mix")]
     #[inline]
+    #[must_use]
     pub fn lerp(self, rhs: Self, s: f32) -> Self {
         self + ((rhs - self) * s)
     }
@@ -592,6 +685,7 @@
     /// For more see
     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
     #[inline]
+    #[must_use]
     pub fn abs_diff_eq(self, rhs: Self, max_abs_diff: f32) -> bool {
         self.sub(rhs).abs().cmple(Self::splat(max_abs_diff)).all()
     }
@@ -602,33 +696,38 @@
     ///
     /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn clamp_length(self, min: f32, max: f32) -> Self {
         glam_assert!(min <= max);
         let length_sq = self.length_squared();
         if length_sq < min * min {
-            self * (length_sq.sqrt().recip() * min)
+            min * (self / math::sqrt(length_sq))
         } else if length_sq > max * max {
-            self * (length_sq.sqrt().recip() * max)
+            max * (self / math::sqrt(length_sq))
         } else {
             self
         }
     }
 
     /// Returns a vector with a length no more than `max`
+    #[inline]
+    #[must_use]
     pub fn clamp_length_max(self, max: f32) -> Self {
         let length_sq = self.length_squared();
         if length_sq > max * max {
-            self * (length_sq.sqrt().recip() * max)
+            max * (self / math::sqrt(length_sq))
         } else {
             self
         }
     }
 
     /// Returns a vector with a length no less than `min`
+    #[inline]
+    #[must_use]
     pub fn clamp_length_min(self, min: f32) -> Self {
         let length_sq = self.length_squared();
         if length_sq < min * min {
-            self * (length_sq.sqrt().recip() * min)
+            min * (self / math::sqrt(length_sq))
         } else {
             self
         }
@@ -642,74 +741,74 @@
     /// and will be heavily dependant on designing algorithms with specific target hardware in
     /// mind.
     #[inline]
+    #[must_use]
     pub fn mul_add(self, a: Self, b: Self) -> Self {
         Self::new(
-            self.x.mul_add(a.x, b.x),
-            self.y.mul_add(a.y, b.y),
-            self.z.mul_add(a.z, b.z),
+            math::mul_add(self.x, a.x, b.x),
+            math::mul_add(self.y, a.y, b.y),
+            math::mul_add(self.z, a.z, b.z),
         )
     }
 
     /// Returns the angle (in radians) between two vectors.
     ///
-    /// The input vectors do not need to be unit length however they must be non-zero.
+    /// The inputs do not need to be unit vectors however they must be non-zero.
     #[inline]
+    #[must_use]
     pub fn angle_between(self, rhs: Self) -> f32 {
-        use crate::FloatEx;
-        self.dot(rhs)
-            .div(self.length_squared().mul(rhs.length_squared()).sqrt())
-            .acos_approx()
+        math::acos_approx(
+            self.dot(rhs)
+                .div(math::sqrt(self.length_squared().mul(rhs.length_squared()))),
+        )
     }
 
     /// Returns some vector that is orthogonal to the given one.
     ///
     /// The input vector must be finite and non-zero.
     ///
-    /// The output vector is not necessarily unit-length.
-    /// For that use [`Self::any_orthonormal_vector`] instead.
+    /// The output vector is not necessarily unit length. For that use
+    /// [`Self::any_orthonormal_vector()`] instead.
     #[inline]
+    #[must_use]
     pub fn any_orthogonal_vector(&self) -> Self {
         // This can probably be optimized
-        if self.x.abs() > self.y.abs() {
+        if math::abs(self.x) > math::abs(self.y) {
             Self::new(-self.z, 0.0, self.x) // self.cross(Self::Y)
         } else {
             Self::new(0.0, self.z, -self.y) // self.cross(Self::X)
         }
     }
 
-    /// Returns any unit-length vector that is orthogonal to the given one.
-    /// The input vector must be finite and non-zero.
+    /// Returns any unit vector that is orthogonal to the given one.
+    ///
+    /// The input vector must be unit length.
     ///
     /// # Panics
     ///
     /// Will panic if `self` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn any_orthonormal_vector(&self) -> Self {
         glam_assert!(self.is_normalized());
         // From https://graphics.pixar.com/library/OrthonormalB/paper.pdf
-        #[cfg(feature = "std")]
-        let sign = (1.0_f32).copysign(self.z);
-        #[cfg(not(feature = "std"))]
-        let sign = self.z.signum();
+        let sign = math::signum(self.z);
         let a = -1.0 / (sign + self.z);
         let b = self.x * self.y * a;
         Self::new(b, sign + self.y * self.y * a, -self.y)
     }
 
-    /// Given a unit-length vector return two other vectors that together form an orthonormal
-    /// basis.  That is, all three vectors are orthogonal to each other and are normalized.
+    /// Given a unit vector return two other vectors that together form an orthonormal
+    /// basis. That is, all three vectors are orthogonal to each other and are normalized.
     ///
     /// # Panics
     ///
     /// Will panic if `self` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn any_orthonormal_pair(&self) -> (Self, Self) {
         glam_assert!(self.is_normalized());
         // From https://graphics.pixar.com/library/OrthonormalB/paper.pdf
-        #[cfg(feature = "std")]
-        let sign = (1.0_f32).copysign(self.z);
-        #[cfg(not(feature = "std"))]
-        let sign = self.z.signum();
+        let sign = math::signum(self.z);
         let a = -1.0 / (sign + self.z);
         let b = self.x * self.y * a;
         (
@@ -720,21 +819,52 @@
 
     /// Casts all elements of `self` to `f64`.
     #[inline]
+    #[must_use]
     pub fn as_dvec3(&self) -> crate::DVec3 {
         crate::DVec3::new(self.x as f64, self.y as f64, self.z as f64)
     }
 
+    /// Casts all elements of `self` to `i16`.
+    #[inline]
+    #[must_use]
+    pub fn as_i16vec3(&self) -> crate::I16Vec3 {
+        crate::I16Vec3::new(self.x as i16, self.y as i16, self.z as i16)
+    }
+
+    /// Casts all elements of `self` to `u16`.
+    #[inline]
+    #[must_use]
+    pub fn as_u16vec3(&self) -> crate::U16Vec3 {
+        crate::U16Vec3::new(self.x as u16, self.y as u16, self.z as u16)
+    }
+
     /// Casts all elements of `self` to `i32`.
     #[inline]
+    #[must_use]
     pub fn as_ivec3(&self) -> crate::IVec3 {
         crate::IVec3::new(self.x as i32, self.y as i32, self.z as i32)
     }
 
     /// Casts all elements of `self` to `u32`.
     #[inline]
+    #[must_use]
     pub fn as_uvec3(&self) -> crate::UVec3 {
         crate::UVec3::new(self.x as u32, self.y as u32, self.z as u32)
     }
+
+    /// Casts all elements of `self` to `i64`.
+    #[inline]
+    #[must_use]
+    pub fn as_i64vec3(&self) -> crate::I64Vec3 {
+        crate::I64Vec3::new(self.x as i64, self.y as i64, self.z as i64)
+    }
+
+    /// Casts all elements of `self` to `u64`.
+    #[inline]
+    #[must_use]
+    pub fn as_u64vec3(&self) -> crate::U64Vec3 {
+        crate::U64Vec3::new(self.x as u64, self.y as u64, self.z as u64)
+    }
 }
 
 impl Default for Vec3 {
diff --git a/src/f32/wasm32/mat2.rs b/src/f32/wasm32/mat2.rs
index b96ef73..f2a4cc3 100644
--- a/src/f32/wasm32/mat2.rs
+++ b/src/f32/wasm32/mat2.rs
@@ -1,6 +1,6 @@
 // Generated from mat.rs.tera template. Edit the template, not the generated file.
 
-use crate::{swizzles::*, DMat2, Mat3, Mat3A, Vec2};
+use crate::{f32::math, swizzles::*, DMat2, Mat3, Mat3A, Vec2};
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
 use core::iter::{Product, Sum};
@@ -8,17 +8,18 @@
 
 use core::arch::wasm32::*;
 
-#[cfg(feature = "libm")]
-#[allow(unused_imports)]
-use num_traits::Float;
-
-/// Creates a 2x2 matrix from column vectors.
+/// Creates a 2x2 matrix from two column vectors.
 #[inline(always)]
+#[must_use]
 pub const fn mat2(x_axis: Vec2, y_axis: Vec2) -> Mat2 {
     Mat2::from_cols(x_axis, y_axis)
 }
 
 /// A 2x2 column major matrix.
+///
+/// SIMD vector types are used for storage on supported platforms.
+///
+/// This type is 16 byte aligned.
 #[derive(Clone, Copy)]
 #[repr(transparent)]
 pub struct Mat2(pub(crate) v128);
@@ -35,12 +36,14 @@
 
     #[allow(clippy::too_many_arguments)]
     #[inline(always)]
+    #[must_use]
     const fn new(m00: f32, m01: f32, m10: f32, m11: f32) -> Self {
         Self(f32x4(m00, m01, m10, m11))
     }
 
     /// Creates a 2x2 matrix from two column vectors.
     #[inline(always)]
+    #[must_use]
     pub const fn from_cols(x_axis: Vec2, y_axis: Vec2) -> Self {
         Self(f32x4(x_axis.x, x_axis.y, y_axis.x, y_axis.y))
     }
@@ -49,6 +52,7 @@
     /// If your data is stored in row major you will need to `transpose` the returned
     /// matrix.
     #[inline]
+    #[must_use]
     pub const fn from_cols_array(m: &[f32; 4]) -> Self {
         Self::new(m[0], m[1], m[2], m[3])
     }
@@ -56,6 +60,7 @@
     /// Creates a `[f32; 4]` array storing data in column major order.
     /// If you require data in row major order `transpose` the matrix first.
     #[inline]
+    #[must_use]
     pub const fn to_cols_array(&self) -> [f32; 4] {
         unsafe { *(self as *const Self as *const [f32; 4]) }
     }
@@ -64,6 +69,7 @@
     /// If your data is in row major order you will need to `transpose` the returned
     /// matrix.
     #[inline]
+    #[must_use]
     pub const fn from_cols_array_2d(m: &[[f32; 2]; 2]) -> Self {
         Self::from_cols(Vec2::from_array(m[0]), Vec2::from_array(m[1]))
     }
@@ -71,6 +77,7 @@
     /// Creates a `[[f32; 2]; 2]` 2D array storing data in column major order.
     /// If you require data in row major order `transpose` the matrix first.
     #[inline]
+    #[must_use]
     pub const fn to_cols_array_2d(&self) -> [[f32; 2]; 2] {
         unsafe { *(self as *const Self as *const [[f32; 2]; 2]) }
     }
@@ -78,6 +85,7 @@
     /// Creates a 2x2 matrix with its diagonal set to `diagonal` and all other entries set to 0.
     #[doc(alias = "scale")]
     #[inline]
+    #[must_use]
     pub const fn from_diagonal(diagonal: Vec2) -> Self {
         Self::new(diagonal.x, 0.0, 0.0, diagonal.y)
     }
@@ -85,26 +93,30 @@
     /// Creates a 2x2 matrix containing the combining non-uniform `scale` and rotation of
     /// `angle` (in radians).
     #[inline]
+    #[must_use]
     pub fn from_scale_angle(scale: Vec2, angle: f32) -> Self {
-        let (sin, cos) = angle.sin_cos();
+        let (sin, cos) = math::sin_cos(angle);
         Self::new(cos * scale.x, sin * scale.x, -sin * scale.y, cos * scale.y)
     }
 
     /// Creates a 2x2 matrix containing a rotation of `angle` (in radians).
     #[inline]
+    #[must_use]
     pub fn from_angle(angle: f32) -> Self {
-        let (sin, cos) = angle.sin_cos();
+        let (sin, cos) = math::sin_cos(angle);
         Self::new(cos, sin, -sin, cos)
     }
 
     /// Creates a 2x2 matrix from a 3x3 matrix, discarding the 2nd row and column.
     #[inline]
+    #[must_use]
     pub fn from_mat3(m: Mat3) -> Self {
         Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
     }
 
     /// 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())
     }
@@ -115,6 +127,7 @@
     ///
     /// Panics if `slice` is less than 4 elements long.
     #[inline]
+    #[must_use]
     pub const fn from_cols_slice(slice: &[f32]) -> Self {
         Self::new(slice[0], slice[1], slice[2], slice[3])
     }
@@ -138,6 +151,7 @@
     ///
     /// Panics if `index` is greater than 1.
     #[inline]
+    #[must_use]
     pub fn col(&self, index: usize) -> Vec2 {
         match index {
             0 => self.x_axis,
@@ -166,6 +180,7 @@
     ///
     /// Panics if `index` is greater than 1.
     #[inline]
+    #[must_use]
     pub fn row(&self, index: usize) -> Vec2 {
         match index {
             0 => Vec2::new(self.x_axis.x, self.y_axis.x),
@@ -177,25 +192,28 @@
     /// Returns `true` if, and only if, all elements are finite.
     /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
     #[inline]
+    #[must_use]
     pub fn is_finite(&self) -> bool {
         self.x_axis.is_finite() && self.y_axis.is_finite()
     }
 
     /// Returns `true` if any elements are `NaN`.
     #[inline]
+    #[must_use]
     pub fn is_nan(&self) -> bool {
         self.x_axis.is_nan() || self.y_axis.is_nan()
     }
 
     /// Returns the transpose of `self`.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn transpose(&self) -> Self {
         Self(i32x4_shuffle::<0, 2, 5, 7>(self.0, self.0))
     }
 
     /// Returns the determinant of `self`.
     #[inline]
+    #[must_use]
     pub fn determinant(&self) -> f32 {
         let abcd = self.0;
         let dcba = i32x4_shuffle::<3, 2, 5, 4>(abcd, abcd);
@@ -211,8 +229,8 @@
     /// # Panics
     ///
     /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn inverse(&self) -> Self {
         const SIGN: v128 = crate::wasm32::v128_from_f32x4([1.0, -1.0, -1.0, 1.0]);
         let abcd = self.0;
@@ -228,6 +246,7 @@
 
     /// Transforms a 2D vector.
     #[inline]
+    #[must_use]
     pub fn mul_vec2(&self, rhs: Vec2) -> Vec2 {
         use core::mem::MaybeUninit;
         let abcd = self.0;
@@ -244,6 +263,7 @@
 
     /// Multiplies two 2x2 matrices.
     #[inline]
+    #[must_use]
     pub fn mul_mat2(&self, rhs: &Self) -> Self {
         let abcd = self.0;
         let rhs = rhs.0;
@@ -260,18 +280,21 @@
 
     /// Adds two 2x2 matrices.
     #[inline]
+    #[must_use]
     pub fn add_mat2(&self, rhs: &Self) -> Self {
         Self(f32x4_add(self.0, rhs.0))
     }
 
     /// Subtracts two 2x2 matrices.
     #[inline]
+    #[must_use]
     pub fn sub_mat2(&self, rhs: &Self) -> Self {
         Self(f32x4_sub(self.0, rhs.0))
     }
 
     /// Multiplies a 2x2 matrix by a scalar.
     #[inline]
+    #[must_use]
     pub fn mul_scalar(&self, rhs: f32) -> Self {
         Self(f32x4_mul(self.0, f32x4_splat(rhs)))
     }
@@ -286,6 +309,7 @@
     /// For more see
     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
     #[inline]
+    #[must_use]
     pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
         self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
             && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
diff --git a/src/f32/wasm32/mat3a.rs b/src/f32/wasm32/mat3a.rs
index 573ea1f..96c039b 100644
--- a/src/f32/wasm32/mat3a.rs
+++ b/src/f32/wasm32/mat3a.rs
@@ -1,6 +1,6 @@
 // Generated from mat.rs.tera template. Edit the template, not the generated file.
 
-use crate::{swizzles::*, DMat3, EulerRot, Mat2, Mat3, Mat4, Quat, Vec2, Vec3, Vec3A};
+use crate::{f32::math, swizzles::*, DMat3, EulerRot, Mat2, Mat3, Mat4, Quat, Vec2, Vec3, Vec3A};
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
 use core::iter::{Product, Sum};
@@ -8,12 +8,9 @@
 
 use core::arch::wasm32::*;
 
-#[cfg(feature = "libm")]
-#[allow(unused_imports)]
-use num_traits::Float;
-
-/// Creates a 3x3 matrix from column vectors.
+/// Creates a 3x3 matrix from three column vectors.
 #[inline(always)]
+#[must_use]
 pub const fn mat3a(x_axis: Vec3A, y_axis: Vec3A, z_axis: Vec3A) -> Mat3A {
     Mat3A::from_cols(x_axis, y_axis, z_axis)
 }
@@ -62,6 +59,7 @@
 
     #[allow(clippy::too_many_arguments)]
     #[inline(always)]
+    #[must_use]
     const fn new(
         m00: f32,
         m01: f32,
@@ -80,8 +78,9 @@
         }
     }
 
-    /// Creates a 3x3 matrix from two column vectors.
+    /// Creates a 3x3 matrix from three column vectors.
     #[inline(always)]
+    #[must_use]
     pub const fn from_cols(x_axis: Vec3A, y_axis: Vec3A, z_axis: Vec3A) -> Self {
         Self {
             x_axis,
@@ -94,6 +93,7 @@
     /// If your data is stored in row major you will need to `transpose` the returned
     /// matrix.
     #[inline]
+    #[must_use]
     pub const fn from_cols_array(m: &[f32; 9]) -> Self {
         Self::new(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8])
     }
@@ -101,6 +101,7 @@
     /// Creates a `[f32; 9]` array storing data in column major order.
     /// If you require data in row major order `transpose` the matrix first.
     #[inline]
+    #[must_use]
     pub const fn to_cols_array(&self) -> [f32; 9] {
         let [x_axis_x, x_axis_y, x_axis_z] = self.x_axis.to_array();
         let [y_axis_x, y_axis_y, y_axis_z] = self.y_axis.to_array();
@@ -116,6 +117,7 @@
     /// If your data is in row major order you will need to `transpose` the returned
     /// matrix.
     #[inline]
+    #[must_use]
     pub const fn from_cols_array_2d(m: &[[f32; 3]; 3]) -> Self {
         Self::from_cols(
             Vec3A::from_array(m[0]),
@@ -127,6 +129,7 @@
     /// Creates a `[[f32; 3]; 3]` 3D array storing data in column major order.
     /// If you require data in row major order `transpose` the matrix first.
     #[inline]
+    #[must_use]
     pub const fn to_cols_array_2d(&self) -> [[f32; 3]; 3] {
         [
             self.x_axis.to_array(),
@@ -138,6 +141,7 @@
     /// Creates a 3x3 matrix with its diagonal set to `diagonal` and all other entries set to 0.
     #[doc(alias = "scale")]
     #[inline]
+    #[must_use]
     pub const fn from_diagonal(diagonal: Vec3) -> Self {
         Self::new(
             diagonal.x, 0.0, 0.0, 0.0, diagonal.y, 0.0, 0.0, 0.0, diagonal.z,
@@ -145,6 +149,8 @@
     }
 
     /// Creates a 3x3 matrix from a 4x4 matrix, discarding the 4th row and column.
+    #[inline]
+    #[must_use]
     pub fn from_mat4(m: Mat4) -> Self {
         Self::from_cols(m.x_axis.into(), m.y_axis.into(), m.z_axis.into())
     }
@@ -155,6 +161,7 @@
     ///
     /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_quat(rotation: Quat) -> Self {
         glam_assert!(rotation.is_normalized());
 
@@ -185,10 +192,11 @@
     ///
     /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
         glam_assert!(axis.is_normalized());
 
-        let (sin, cos) = angle.sin_cos();
+        let (sin, cos) = math::sin_cos(angle);
         let (xsin, ysin, zsin) = axis.mul(sin).into();
         let (x, y, z) = axis.into();
         let (x2, y2, z2) = axis.mul(axis).into();
@@ -203,9 +211,10 @@
         )
     }
 
-    #[inline]
     /// Creates a 3D rotation matrix from the given euler rotation sequence and the angles (in
     /// radians).
+    #[inline]
+    #[must_use]
     pub fn from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self {
         let quat = Quat::from_euler(order, a, b, c);
         Self::from_quat(quat)
@@ -213,8 +222,9 @@
 
     /// Creates a 3D rotation matrix from `angle` (in radians) around the x axis.
     #[inline]
+    #[must_use]
     pub fn from_rotation_x(angle: f32) -> Self {
-        let (sina, cosa) = angle.sin_cos();
+        let (sina, cosa) = math::sin_cos(angle);
         Self::from_cols(
             Vec3A::X,
             Vec3A::new(0.0, cosa, sina),
@@ -224,8 +234,9 @@
 
     /// Creates a 3D rotation matrix from `angle` (in radians) around the y axis.
     #[inline]
+    #[must_use]
     pub fn from_rotation_y(angle: f32) -> Self {
-        let (sina, cosa) = angle.sin_cos();
+        let (sina, cosa) = math::sin_cos(angle);
         Self::from_cols(
             Vec3A::new(cosa, 0.0, -sina),
             Vec3A::Y,
@@ -235,8 +246,9 @@
 
     /// Creates a 3D rotation matrix from `angle` (in radians) around the z axis.
     #[inline]
+    #[must_use]
     pub fn from_rotation_z(angle: f32) -> Self {
-        let (sina, cosa) = angle.sin_cos();
+        let (sina, cosa) = math::sin_cos(angle);
         Self::from_cols(
             Vec3A::new(cosa, sina, 0.0),
             Vec3A::new(-sina, cosa, 0.0),
@@ -249,6 +261,7 @@
     /// The resulting matrix can be used to transform 2D points and vectors. See
     /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
     #[inline]
+    #[must_use]
     pub fn from_translation(translation: Vec2) -> Self {
         Self::from_cols(
             Vec3A::X,
@@ -263,8 +276,9 @@
     /// The resulting matrix can be used to transform 2D points and vectors. See
     /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
     #[inline]
+    #[must_use]
     pub fn from_angle(angle: f32) -> Self {
-        let (sin, cos) = angle.sin_cos();
+        let (sin, cos) = math::sin_cos(angle);
         Self::from_cols(
             Vec3A::new(cos, sin, 0.0),
             Vec3A::new(-sin, cos, 0.0),
@@ -278,8 +292,9 @@
     /// The resulting matrix can be used to transform 2D points and vectors. See
     /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
     #[inline]
+    #[must_use]
     pub fn from_scale_angle_translation(scale: Vec2, angle: f32, translation: Vec2) -> Self {
-        let (sin, cos) = angle.sin_cos();
+        let (sin, cos) = math::sin_cos(angle);
         Self::from_cols(
             Vec3A::new(cos * scale.x, sin * scale.x, 0.0),
             Vec3A::new(-sin * scale.y, cos * scale.y, 0.0),
@@ -296,6 +311,7 @@
     ///
     /// Will panic if all elements of `scale` are zero when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_scale(scale: Vec2) -> Self {
         // Do not panic as long as any component is non-zero
         glam_assert!(scale.cmpne(Vec2::ZERO).any());
@@ -322,6 +338,7 @@
     ///
     /// Panics if `slice` is less than 9 elements long.
     #[inline]
+    #[must_use]
     pub const fn from_cols_slice(slice: &[f32]) -> Self {
         Self::new(
             slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
@@ -353,6 +370,7 @@
     ///
     /// Panics if `index` is greater than 2.
     #[inline]
+    #[must_use]
     pub fn col(&self, index: usize) -> Vec3A {
         match index {
             0 => self.x_axis,
@@ -383,6 +401,7 @@
     ///
     /// Panics if `index` is greater than 2.
     #[inline]
+    #[must_use]
     pub fn row(&self, index: usize) -> Vec3A {
         match index {
             0 => Vec3A::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
@@ -395,19 +414,21 @@
     /// Returns `true` if, and only if, all elements are finite.
     /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
     #[inline]
+    #[must_use]
     pub fn is_finite(&self) -> bool {
         self.x_axis.is_finite() && self.y_axis.is_finite() && self.z_axis.is_finite()
     }
 
     /// Returns `true` if any elements are `NaN`.
     #[inline]
+    #[must_use]
     pub fn is_nan(&self) -> bool {
         self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan()
     }
 
     /// Returns the transpose of `self`.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn transpose(&self) -> Self {
         let tmp0 = i32x4_shuffle::<0, 1, 4, 5>(self.x_axis.0, self.y_axis.0);
         let tmp1 = i32x4_shuffle::<2, 3, 6, 7>(self.x_axis.0, self.y_axis.0);
@@ -421,6 +442,7 @@
 
     /// Returns the determinant of `self`.
     #[inline]
+    #[must_use]
     pub fn determinant(&self) -> f32 {
         self.z_axis.dot(self.x_axis.cross(self.y_axis))
     }
@@ -432,8 +454,8 @@
     /// # Panics
     ///
     /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn inverse(&self) -> Self {
         let tmp0 = self.y_axis.cross(self.z_axis);
         let tmp1 = self.z_axis.cross(self.x_axis);
@@ -454,6 +476,7 @@
     ///
     /// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn transform_point2(&self, rhs: Vec2) -> Vec2 {
         glam_assert!(self.row(2).abs_diff_eq(Vec3A::Z, 1e-6));
         Mat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs + self.z_axis.xy()
@@ -469,6 +492,7 @@
     ///
     /// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn transform_vector2(&self, rhs: Vec2) -> Vec2 {
         glam_assert!(self.row(2).abs_diff_eq(Vec3A::Z, 1e-6));
         Mat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs
@@ -476,12 +500,14 @@
 
     /// Transforms a 3D vector.
     #[inline]
+    #[must_use]
     pub fn mul_vec3(&self, rhs: Vec3) -> Vec3 {
         self.mul_vec3a(rhs.into()).into()
     }
 
-    /// Transforms a `Vec3A`.
+    /// Transforms a [`Vec3A`].
     #[inline]
+    #[must_use]
     pub fn mul_vec3a(&self, rhs: Vec3A) -> Vec3A {
         let mut res = self.x_axis.mul(rhs.xxx());
         res = res.add(self.y_axis.mul(rhs.yyy()));
@@ -491,6 +517,7 @@
 
     /// Multiplies two 3x3 matrices.
     #[inline]
+    #[must_use]
     pub fn mul_mat3(&self, rhs: &Self) -> Self {
         Self::from_cols(
             self.mul(rhs.x_axis),
@@ -501,6 +528,7 @@
 
     /// Adds two 3x3 matrices.
     #[inline]
+    #[must_use]
     pub fn add_mat3(&self, rhs: &Self) -> Self {
         Self::from_cols(
             self.x_axis.add(rhs.x_axis),
@@ -511,6 +539,7 @@
 
     /// Subtracts two 3x3 matrices.
     #[inline]
+    #[must_use]
     pub fn sub_mat3(&self, rhs: &Self) -> Self {
         Self::from_cols(
             self.x_axis.sub(rhs.x_axis),
@@ -521,6 +550,7 @@
 
     /// Multiplies a 3x3 matrix by a scalar.
     #[inline]
+    #[must_use]
     pub fn mul_scalar(&self, rhs: f32) -> Self {
         Self::from_cols(
             self.x_axis.mul(rhs),
@@ -539,6 +569,7 @@
     /// For more see
     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
     #[inline]
+    #[must_use]
     pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
         self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
             && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
diff --git a/src/f32/wasm32/mat4.rs b/src/f32/wasm32/mat4.rs
index bdaeb29..22b67a7 100644
--- a/src/f32/wasm32/mat4.rs
+++ b/src/f32/wasm32/mat4.rs
@@ -1,6 +1,8 @@
 // Generated from mat.rs.tera template. Edit the template, not the generated file.
 
-use crate::{swizzles::*, wasm32::*, DMat4, EulerRot, Mat3, Mat3A, Quat, Vec3, Vec3A, Vec4};
+use crate::{
+    f32::math, swizzles::*, wasm32::*, DMat4, EulerRot, Mat3, Mat3A, Quat, Vec3, Vec3A, Vec4,
+};
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
 use core::iter::{Product, Sum};
@@ -8,12 +10,9 @@
 
 use core::arch::wasm32::*;
 
-#[cfg(feature = "libm")]
-#[allow(unused_imports)]
-use num_traits::Float;
-
-/// Creates a 4x4 matrix from column vectors.
+/// Creates a 4x4 matrix from four column vectors.
 #[inline(always)]
+#[must_use]
 pub const fn mat4(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Mat4 {
     Mat4::from_cols(x_axis, y_axis, z_axis, w_axis)
 }
@@ -29,7 +28,7 @@
 /// using methods such as [`Self::from_translation()`], [`Self::from_quat()`],
 /// [`Self::from_scale()`] and [`Self::from_scale_rotation_translation()`].
 ///
-/// Othographic projections can be created using the methods [`Self::orthographic_lh()`] for
+/// Orthographic projections can be created using the methods [`Self::orthographic_lh()`] for
 /// left-handed coordinate systems and [`Self::orthographic_rh()`] for right-handed
 /// systems. The resulting matrix is also an affine transformation.
 ///
@@ -68,6 +67,7 @@
 
     #[allow(clippy::too_many_arguments)]
     #[inline(always)]
+    #[must_use]
     const fn new(
         m00: f32,
         m01: f32,
@@ -94,8 +94,9 @@
         }
     }
 
-    /// Creates a 4x4 matrix from two column vectors.
+    /// Creates a 4x4 matrix from four column vectors.
     #[inline(always)]
+    #[must_use]
     pub const fn from_cols(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Self {
         Self {
             x_axis,
@@ -109,6 +110,7 @@
     /// If your data is stored in row major you will need to `transpose` the returned
     /// matrix.
     #[inline]
+    #[must_use]
     pub const fn from_cols_array(m: &[f32; 16]) -> Self {
         Self::new(
             m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9], m[10], m[11], m[12], m[13],
@@ -119,6 +121,7 @@
     /// Creates a `[f32; 16]` array storing data in column major order.
     /// If you require data in row major order `transpose` the matrix first.
     #[inline]
+    #[must_use]
     pub const fn to_cols_array(&self) -> [f32; 16] {
         let [x_axis_x, x_axis_y, x_axis_z, x_axis_w] = self.x_axis.to_array();
         let [y_axis_x, y_axis_y, y_axis_z, y_axis_w] = self.y_axis.to_array();
@@ -135,6 +138,7 @@
     /// If your data is in row major order you will need to `transpose` the returned
     /// matrix.
     #[inline]
+    #[must_use]
     pub const fn from_cols_array_2d(m: &[[f32; 4]; 4]) -> Self {
         Self::from_cols(
             Vec4::from_array(m[0]),
@@ -147,6 +151,7 @@
     /// Creates a `[[f32; 4]; 4]` 4D array storing data in column major order.
     /// If you require data in row major order `transpose` the matrix first.
     #[inline]
+    #[must_use]
     pub const fn to_cols_array_2d(&self) -> [[f32; 4]; 4] {
         [
             self.x_axis.to_array(),
@@ -159,6 +164,7 @@
     /// Creates a 4x4 matrix with its diagonal set to `diagonal` and all other entries set to 0.
     #[doc(alias = "scale")]
     #[inline]
+    #[must_use]
     pub const fn from_diagonal(diagonal: Vec4) -> Self {
         // diagonal.x, diagonal.y etc can't be done in a const-context
         let [x, y, z, w] = diagonal.to_array();
@@ -168,6 +174,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn quat_to_axes(rotation: Quat) -> (Vec4, Vec4, Vec4) {
         glam_assert!(rotation.is_normalized());
 
@@ -201,6 +208,7 @@
     ///
     /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_scale_rotation_translation(scale: Vec3, rotation: Quat, translation: Vec3) -> Self {
         let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
         Self::from_cols(
@@ -220,6 +228,7 @@
     ///
     /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_rotation_translation(rotation: Quat, translation: Vec3) -> Self {
         let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
         Self::from_cols(x_axis, y_axis, z_axis, Vec4::from((translation, 1.0)))
@@ -233,12 +242,13 @@
     /// Will panic if the determinant of `self` is zero or if the resulting scale vector
     /// contains any zero elements when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn to_scale_rotation_translation(&self) -> (Vec3, Quat, Vec3) {
         let det = self.determinant();
         glam_assert!(det != 0.0);
 
         let scale = Vec3::new(
-            self.x_axis.length() * det.signum(),
+            self.x_axis.length() * math::signum(det),
             self.y_axis.length(),
             self.z_axis.length(),
         );
@@ -267,6 +277,7 @@
     ///
     /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_quat(rotation: Quat) -> Self {
         let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
         Self::from_cols(x_axis, y_axis, z_axis, Vec4::W)
@@ -278,6 +289,7 @@
     /// The resulting matrix can be used to transform 3D points and vectors. See
     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
     #[inline]
+    #[must_use]
     pub fn from_mat3(m: Mat3) -> Self {
         Self::from_cols(
             Vec4::from((m.x_axis, 0.0)),
@@ -293,6 +305,7 @@
     /// The resulting matrix can be used to transform 3D points and vectors. See
     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
     #[inline]
+    #[must_use]
     pub fn from_mat3a(m: Mat3A) -> Self {
         Self::from_cols(
             Vec4::from((m.x_axis, 0.0)),
@@ -307,6 +320,7 @@
     /// The resulting matrix can be used to transform 3D points and vectors. See
     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
     #[inline]
+    #[must_use]
     pub fn from_translation(translation: Vec3) -> Self {
         Self::from_cols(
             Vec4::X,
@@ -326,10 +340,11 @@
     ///
     /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
         glam_assert!(axis.is_normalized());
 
-        let (sin, cos) = angle.sin_cos();
+        let (sin, cos) = math::sin_cos(angle);
         let axis_sin = axis.mul(sin);
         let axis_sq = axis.mul(axis);
         let omc = 1.0 - cos;
@@ -359,12 +374,13 @@
         )
     }
 
-    #[inline]
     /// Creates a affine transformation matrix containing a rotation from the given euler
     /// rotation sequence and angles (in radians).
     ///
     /// The resulting matrix can be used to transform 3D points and vectors. See
     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
+    #[inline]
+    #[must_use]
     pub fn from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self {
         let quat = Quat::from_euler(order, a, b, c);
         Self::from_quat(quat)
@@ -376,8 +392,9 @@
     /// The resulting matrix can be used to transform 3D points and vectors. See
     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
     #[inline]
+    #[must_use]
     pub fn from_rotation_x(angle: f32) -> Self {
-        let (sina, cosa) = angle.sin_cos();
+        let (sina, cosa) = math::sin_cos(angle);
         Self::from_cols(
             Vec4::X,
             Vec4::new(0.0, cosa, sina, 0.0),
@@ -392,8 +409,9 @@
     /// The resulting matrix can be used to transform 3D points and vectors. See
     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
     #[inline]
+    #[must_use]
     pub fn from_rotation_y(angle: f32) -> Self {
-        let (sina, cosa) = angle.sin_cos();
+        let (sina, cosa) = math::sin_cos(angle);
         Self::from_cols(
             Vec4::new(cosa, 0.0, -sina, 0.0),
             Vec4::Y,
@@ -408,8 +426,9 @@
     /// The resulting matrix can be used to transform 3D points and vectors. See
     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
     #[inline]
+    #[must_use]
     pub fn from_rotation_z(angle: f32) -> Self {
-        let (sina, cosa) = angle.sin_cos();
+        let (sina, cosa) = math::sin_cos(angle);
         Self::from_cols(
             Vec4::new(cosa, sina, 0.0, 0.0),
             Vec4::new(-sina, cosa, 0.0, 0.0),
@@ -427,6 +446,7 @@
     ///
     /// Will panic if all elements of `scale` are zero when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_scale(scale: Vec3) -> Self {
         // Do not panic as long as any component is non-zero
         glam_assert!(scale.cmpne(Vec3::ZERO).any());
@@ -445,6 +465,7 @@
     ///
     /// Panics if `slice` is less than 16 elements long.
     #[inline]
+    #[must_use]
     pub const fn from_cols_slice(slice: &[f32]) -> Self {
         Self::new(
             slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
@@ -483,6 +504,7 @@
     ///
     /// Panics if `index` is greater than 3.
     #[inline]
+    #[must_use]
     pub fn col(&self, index: usize) -> Vec4 {
         match index {
             0 => self.x_axis,
@@ -515,6 +537,7 @@
     ///
     /// Panics if `index` is greater than 3.
     #[inline]
+    #[must_use]
     pub fn row(&self, index: usize) -> Vec4 {
         match index {
             0 => Vec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
@@ -528,6 +551,7 @@
     /// Returns `true` if, and only if, all elements are finite.
     /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
     #[inline]
+    #[must_use]
     pub fn is_finite(&self) -> bool {
         self.x_axis.is_finite()
             && self.y_axis.is_finite()
@@ -537,13 +561,14 @@
 
     /// Returns `true` if any elements are `NaN`.
     #[inline]
+    #[must_use]
     pub fn is_nan(&self) -> bool {
         self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan() || self.w_axis.is_nan()
     }
 
     /// Returns the transpose of `self`.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn transpose(&self) -> Self {
         // Based on https://github.com/microsoft/DirectXMath `XMMatrixTranspose`
         let tmp0 = i32x4_shuffle::<0, 1, 4, 5>(self.x_axis.0, self.y_axis.0);
@@ -560,6 +585,7 @@
     }
 
     /// Returns the determinant of `self`.
+    #[must_use]
     pub fn determinant(&self) -> f32 {
         // Based on https://github.com/g-truc/glm `glm_mat4_determinant`
         let swp2a = i32x4_shuffle::<2, 1, 1, 0>(self.z_axis.0, self.z_axis.0);
@@ -749,6 +775,7 @@
     ///
     /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
     #[inline]
+    #[must_use]
     pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
         Self::look_to_rh(eye, -dir, up)
     }
@@ -758,6 +785,7 @@
     ///
     /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
     #[inline]
+    #[must_use]
     pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
         let f = dir.normalize();
         let s = f.cross(up).normalize();
@@ -779,6 +807,7 @@
     ///
     /// Will panic if `up` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
         glam_assert!(up.is_normalized());
         Self::look_to_lh(eye, center.sub(eye), up)
@@ -801,6 +830,7 @@
     /// This is the same as the OpenGL `gluPerspective` function.
     /// See <https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml>
     #[inline]
+    #[must_use]
     pub fn perspective_rh_gl(
         fov_y_radians: f32,
         aspect_ratio: f32,
@@ -808,7 +838,7 @@
         z_far: f32,
     ) -> Self {
         let inv_length = 1.0 / (z_near - z_far);
-        let f = 1.0 / (0.5 * fov_y_radians).tan();
+        let f = 1.0 / math::tan(0.5 * fov_y_radians);
         let a = f / aspect_ratio;
         let b = (z_near + z_far) * inv_length;
         let c = (2.0 * z_near * z_far) * inv_length;
@@ -827,9 +857,10 @@
     /// Will panic if `z_near` or `z_far` are less than or equal to zero when `glam_assert` is
     /// enabled.
     #[inline]
+    #[must_use]
     pub fn perspective_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
         glam_assert!(z_near > 0.0 && z_far > 0.0);
-        let (sin_fov, cos_fov) = (0.5 * fov_y_radians).sin_cos();
+        let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
         let h = cos_fov / sin_fov;
         let w = h / aspect_ratio;
         let r = z_far / (z_far - z_near);
@@ -848,9 +879,10 @@
     /// Will panic if `z_near` or `z_far` are less than or equal to zero when `glam_assert` is
     /// enabled.
     #[inline]
+    #[must_use]
     pub fn perspective_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
         glam_assert!(z_near > 0.0 && z_far > 0.0);
-        let (sin_fov, cos_fov) = (0.5 * fov_y_radians).sin_cos();
+        let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
         let h = cos_fov / sin_fov;
         let w = h / aspect_ratio;
         let r = z_far / (z_near - z_far);
@@ -868,9 +900,10 @@
     ///
     /// Will panic if `z_near` is less than or equal to zero when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn perspective_infinite_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
         glam_assert!(z_near > 0.0);
-        let (sin_fov, cos_fov) = (0.5 * fov_y_radians).sin_cos();
+        let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
         let h = cos_fov / sin_fov;
         let w = h / aspect_ratio;
         Self::from_cols(
@@ -887,13 +920,14 @@
     ///
     /// Will panic if `z_near` is less than or equal to zero when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn perspective_infinite_reverse_lh(
         fov_y_radians: f32,
         aspect_ratio: f32,
         z_near: f32,
     ) -> Self {
         glam_assert!(z_near > 0.0);
-        let (sin_fov, cos_fov) = (0.5 * fov_y_radians).sin_cos();
+        let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
         let h = cos_fov / sin_fov;
         let w = h / aspect_ratio;
         Self::from_cols(
@@ -907,9 +941,10 @@
     /// Creates an infinite right-handed perspective projection matrix with
     /// `[0,1]` depth range.
     #[inline]
+    #[must_use]
     pub fn perspective_infinite_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
         glam_assert!(z_near > 0.0);
-        let f = 1.0 / (0.5 * fov_y_radians).tan();
+        let f = 1.0 / math::tan(0.5 * fov_y_radians);
         Self::from_cols(
             Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
             Vec4::new(0.0, f, 0.0, 0.0),
@@ -921,13 +956,14 @@
     /// Creates an infinite reverse right-handed perspective projection matrix
     /// with `[0,1]` depth range.
     #[inline]
+    #[must_use]
     pub fn perspective_infinite_reverse_rh(
         fov_y_radians: f32,
         aspect_ratio: f32,
         z_near: f32,
     ) -> Self {
         glam_assert!(z_near > 0.0);
-        let f = 1.0 / (0.5 * fov_y_radians).tan();
+        let f = 1.0 / math::tan(0.5 * fov_y_radians);
         Self::from_cols(
             Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
             Vec4::new(0.0, f, 0.0, 0.0),
@@ -941,6 +977,7 @@
     /// See
     /// <https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glOrtho.xml>
     #[inline]
+    #[must_use]
     pub fn orthographic_rh_gl(
         left: f32,
         right: f32,
@@ -966,6 +1003,7 @@
 
     /// Creates a left-handed orthographic projection matrix with `[0,1]` depth range.
     #[inline]
+    #[must_use]
     pub fn orthographic_lh(
         left: f32,
         right: f32,
@@ -992,6 +1030,7 @@
 
     /// Creates a right-handed orthographic projection matrix with `[0,1]` depth range.
     #[inline]
+    #[must_use]
     pub fn orthographic_rh(
         left: f32,
         right: f32,
@@ -1023,6 +1062,7 @@
     ///
     /// This method assumes that `self` contains a projective transform.
     #[inline]
+    #[must_use]
     pub fn project_point3(&self, rhs: Vec3) -> Vec3 {
         let mut res = self.x_axis.mul(rhs.x);
         res = self.y_axis.mul(rhs.y).add(res);
@@ -1045,6 +1085,7 @@
     ///
     /// Will panic if the 3rd row of `self` is not `(0, 0, 0, 1)` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn transform_point3(&self, rhs: Vec3) -> Vec3 {
         glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
         let mut res = self.x_axis.mul(rhs.x);
@@ -1065,6 +1106,7 @@
     ///
     /// Will panic if the 3rd row of `self` is not `(0, 0, 0, 1)` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn transform_vector3(&self, rhs: Vec3) -> Vec3 {
         glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
         let mut res = self.x_axis.mul(rhs.x);
@@ -1073,10 +1115,11 @@
         res.xyz()
     }
 
-    /// Transforms the given `Vec3A` as 3D point.
+    /// Transforms the given [`Vec3A`] as 3D point.
     ///
-    /// This is the equivalent of multiplying the `Vec3A` as a 4D vector where `w` is `1.0`.
+    /// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `1.0`.
     #[inline]
+    #[must_use]
     pub fn transform_point3a(&self, rhs: Vec3A) -> Vec3A {
         glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
         let mut res = self.x_axis.mul(rhs.xxxx());
@@ -1086,10 +1129,11 @@
         res.into()
     }
 
-    /// Transforms the give `Vec3A` as 3D vector.
+    /// Transforms the give [`Vec3A`] as 3D vector.
     ///
-    /// This is the equivalent of multiplying the `Vec3A` as a 4D vector where `w` is `0.0`.
+    /// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `0.0`.
     #[inline]
+    #[must_use]
     pub fn transform_vector3a(&self, rhs: Vec3A) -> Vec3A {
         glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
         let mut res = self.x_axis.mul(rhs.xxxx());
@@ -1100,6 +1144,7 @@
 
     /// Transforms a 4D vector.
     #[inline]
+    #[must_use]
     pub fn mul_vec4(&self, rhs: Vec4) -> Vec4 {
         let mut res = self.x_axis.mul(rhs.xxxx());
         res = res.add(self.y_axis.mul(rhs.yyyy()));
@@ -1110,6 +1155,7 @@
 
     /// Multiplies two 4x4 matrices.
     #[inline]
+    #[must_use]
     pub fn mul_mat4(&self, rhs: &Self) -> Self {
         Self::from_cols(
             self.mul(rhs.x_axis),
@@ -1121,6 +1167,7 @@
 
     /// Adds two 4x4 matrices.
     #[inline]
+    #[must_use]
     pub fn add_mat4(&self, rhs: &Self) -> Self {
         Self::from_cols(
             self.x_axis.add(rhs.x_axis),
@@ -1132,6 +1179,7 @@
 
     /// Subtracts two 4x4 matrices.
     #[inline]
+    #[must_use]
     pub fn sub_mat4(&self, rhs: &Self) -> Self {
         Self::from_cols(
             self.x_axis.sub(rhs.x_axis),
@@ -1143,6 +1191,7 @@
 
     /// Multiplies a 4x4 matrix by a scalar.
     #[inline]
+    #[must_use]
     pub fn mul_scalar(&self, rhs: f32) -> Self {
         Self::from_cols(
             self.x_axis.mul(rhs),
@@ -1162,6 +1211,7 @@
     /// For more see
     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
     #[inline]
+    #[must_use]
     pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
         self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
             && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
diff --git a/src/f32/wasm32/quat.rs b/src/f32/wasm32/quat.rs
index 75f9c16..7247b27 100644
--- a/src/f32/wasm32/quat.rs
+++ b/src/f32/wasm32/quat.rs
@@ -2,14 +2,11 @@
 
 use crate::{
     euler::{EulerFromQuaternion, EulerRot, EulerToQuaternion},
+    f32::math,
     wasm32::*,
-    DQuat, FloatEx, Mat3, Mat3A, Mat4, Vec2, Vec3, Vec3A, Vec4,
+    DQuat, Mat3, Mat3A, Mat4, Vec2, Vec3, Vec3A, Vec4,
 };
 
-#[cfg(feature = "libm")]
-#[allow(unused_imports)]
-use num_traits::Float;
-
 use core::arch::wasm32::*;
 
 #[cfg(not(target_arch = "spirv"))]
@@ -22,6 +19,7 @@
 /// This should generally not be called manually unless you know what you are doing. Use
 /// one of the other constructors instead such as `identity` or `from_axis_angle`.
 #[inline]
+#[must_use]
 pub const fn quat(x: f32, y: f32, z: f32, w: f32) -> Quat {
     Quat::from_xyzw(x, y, z, w)
 }
@@ -32,6 +30,8 @@
 /// floating point "error creep" which can occur when successive quaternion
 /// operations are applied.
 ///
+/// SIMD vector types are used for storage on supported platforms.
+///
 /// This type is 16 byte aligned.
 #[derive(Clone, Copy)]
 #[repr(transparent)]
@@ -59,6 +59,7 @@
     /// This function does not check if the input is normalized, it is up to the user to
     /// provide normalized input or to normalized the resulting quaternion.
     #[inline(always)]
+    #[must_use]
     pub const fn from_xyzw(x: f32, y: f32, z: f32, w: f32) -> Self {
         Self(f32x4(x, y, z, w))
     }
@@ -70,6 +71,7 @@
     /// This function does not check if the input is normalized, it is up to the user to
     /// provide normalized input or to normalized the resulting quaternion.
     #[inline]
+    #[must_use]
     pub const fn from_array(a: [f32; 4]) -> Self {
         Self::from_xyzw(a[0], a[1], a[2], a[3])
     }
@@ -81,7 +83,8 @@
     /// This function does not check if the input is normalized, it is up to the user to
     /// provide normalized input or to normalized the resulting quaternion.
     #[inline]
-    pub fn from_vec4(v: Vec4) -> Self {
+    #[must_use]
+    pub const fn from_vec4(v: Vec4) -> Self {
         Self(v.0)
     }
 
@@ -96,6 +99,7 @@
     ///
     /// Panics if `slice` length is less than 4.
     #[inline]
+    #[must_use]
     pub fn from_slice(slice: &[f32]) -> Self {
         Self::from_xyzw(slice[0], slice[1], slice[2], slice[3])
     }
@@ -114,15 +118,17 @@
     }
 
     /// Create a quaternion for a normalized rotation `axis` and `angle` (in radians).
-    /// The axis must be normalized (unit-length).
+    ///
+    /// The axis must be a unit vector.
     ///
     /// # Panics
     ///
     /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
         glam_assert!(axis.is_normalized());
-        let (s, c) = (angle * 0.5).sin_cos();
+        let (s, c) = math::sin_cos(angle * 0.5);
         let v = axis * s;
         Self::from_xyzw(v.x, v.y, v.z, c)
     }
@@ -131,6 +137,7 @@
     ///
     /// `from_scaled_axis(Vec3::ZERO)` results in the identity quaternion.
     #[inline]
+    #[must_use]
     pub fn from_scaled_axis(v: Vec3) -> Self {
         let length = v.length();
         if length == 0.0 {
@@ -142,33 +149,38 @@
 
     /// Creates a quaternion from the `angle` (in radians) around the x axis.
     #[inline]
+    #[must_use]
     pub fn from_rotation_x(angle: f32) -> Self {
-        let (s, c) = (angle * 0.5).sin_cos();
+        let (s, c) = math::sin_cos(angle * 0.5);
         Self::from_xyzw(s, 0.0, 0.0, c)
     }
 
     /// Creates a quaternion from the `angle` (in radians) around the y axis.
     #[inline]
+    #[must_use]
     pub fn from_rotation_y(angle: f32) -> Self {
-        let (s, c) = (angle * 0.5).sin_cos();
+        let (s, c) = math::sin_cos(angle * 0.5);
         Self::from_xyzw(0.0, s, 0.0, c)
     }
 
     /// Creates a quaternion from the `angle` (in radians) around the z axis.
     #[inline]
+    #[must_use]
     pub fn from_rotation_z(angle: f32) -> Self {
-        let (s, c) = (angle * 0.5).sin_cos();
+        let (s, c) = math::sin_cos(angle * 0.5);
         Self::from_xyzw(0.0, 0.0, s, c)
     }
 
-    #[inline]
     /// Creates a quaternion from the given Euler rotation sequence and the angles (in radians).
+    #[inline]
+    #[must_use]
     pub fn from_euler(euler: EulerRot, a: f32, b: f32, c: f32) -> Self {
         euler.new_quat(a, b, c)
     }
 
     /// From the columns of a 3x3 rotation matrix.
     #[inline]
+    #[must_use]
     pub(crate) fn from_rotation_axes(x_axis: Vec3, y_axis: Vec3, z_axis: Vec3) -> Self {
         // Based on https://github.com/microsoft/DirectXMath `XM$quaternionRotationMatrix`
         let (m00, m01, m02) = x_axis.into();
@@ -181,7 +193,7 @@
             if dif10 <= 0.0 {
                 // x^2 >= y^2
                 let four_xsq = omm22 - dif10;
-                let inv4x = 0.5 / four_xsq.sqrt();
+                let inv4x = 0.5 / math::sqrt(four_xsq);
                 Self::from_xyzw(
                     four_xsq * inv4x,
                     (m01 + m10) * inv4x,
@@ -191,7 +203,7 @@
             } else {
                 // y^2 >= x^2
                 let four_ysq = omm22 + dif10;
-                let inv4y = 0.5 / four_ysq.sqrt();
+                let inv4y = 0.5 / math::sqrt(four_ysq);
                 Self::from_xyzw(
                     (m01 + m10) * inv4y,
                     four_ysq * inv4y,
@@ -206,7 +218,7 @@
             if sum10 <= 0.0 {
                 // z^2 >= w^2
                 let four_zsq = opm22 - sum10;
-                let inv4z = 0.5 / four_zsq.sqrt();
+                let inv4z = 0.5 / math::sqrt(four_zsq);
                 Self::from_xyzw(
                     (m02 + m20) * inv4z,
                     (m12 + m21) * inv4z,
@@ -216,7 +228,7 @@
             } else {
                 // w^2 >= z^2
                 let four_wsq = opm22 + sum10;
-                let inv4w = 0.5 / four_wsq.sqrt();
+                let inv4w = 0.5 / math::sqrt(four_wsq);
                 Self::from_xyzw(
                     (m12 - m21) * inv4w,
                     (m20 - m02) * inv4w,
@@ -229,18 +241,21 @@
 
     /// Creates a quaternion from a 3x3 rotation matrix.
     #[inline]
+    #[must_use]
     pub fn from_mat3(mat: &Mat3) -> Self {
         Self::from_rotation_axes(mat.x_axis, mat.y_axis, mat.z_axis)
     }
 
     /// Creates a quaternion from a 3x3 SIMD aligned rotation matrix.
     #[inline]
+    #[must_use]
     pub fn from_mat3a(mat: &Mat3A) -> Self {
         Self::from_rotation_axes(mat.x_axis.into(), mat.y_axis.into(), mat.z_axis.into())
     }
 
     /// Creates a quaternion from a 3x3 rotation matrix inside a homogeneous 4x4 matrix.
     #[inline]
+    #[must_use]
     pub fn from_mat4(mat: &Mat4) -> Self {
         Self::from_rotation_axes(
             mat.x_axis.truncate(),
@@ -252,7 +267,7 @@
     /// Gets the minimal rotation for transforming `from` to `to`.  The rotation is in the
     /// plane spanned by the two vectors.  Will rotate at most 180 degrees.
     ///
-    /// The input vectors must be normalized (unit-length).
+    /// The inputs must be unit vectors.
     ///
     /// `from_rotation_arc(from, to) * from ≈ to`.
     ///
@@ -262,6 +277,7 @@
     /// # Panics
     ///
     /// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
+    #[must_use]
     pub fn from_rotation_arc(from: Vec3, to: Vec3) -> Self {
         glam_assert!(from.is_normalized());
         glam_assert!(to.is_normalized());
@@ -287,7 +303,7 @@
     /// The rotation is in the plane spanned by the two vectors.  Will rotate at most 90
     /// degrees.
     ///
-    /// The input vectors must be normalized (unit-length).
+    /// The inputs must be unit vectors.
     ///
     /// `to.dot(from_rotation_arc_colinear(from, to) * from).abs() ≈ 1`.
     ///
@@ -295,6 +311,7 @@
     ///
     /// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_rotation_arc_colinear(from: Vec3, to: Vec3) -> Self {
         if from.dot(to) < 0.0 {
             Self::from_rotation_arc(from, -to)
@@ -306,7 +323,7 @@
     /// Gets the minimal rotation for transforming `from` to `to`.  The resulting rotation is
     /// around the z axis. Will rotate at most 180 degrees.
     ///
-    /// The input vectors must be normalized (unit-length).
+    /// The inputs must be unit vectors.
     ///
     /// `from_rotation_arc_2d(from, to) * from ≈ to`.
     ///
@@ -316,6 +333,7 @@
     /// # Panics
     ///
     /// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
+    #[must_use]
     pub fn from_rotation_arc_2d(from: Vec2, to: Vec2) -> Self {
         glam_assert!(from.is_normalized());
         glam_assert!(to.is_normalized());
@@ -336,31 +354,30 @@
             let z = from.x * to.y - to.x * from.y;
             let w = 1.0 + dot;
             // calculate length with x=0 and y=0 to normalize
-            let len_rcp = 1.0 / (z * z + w * w).sqrt();
+            let len_rcp = 1.0 / math::sqrt(z * z + w * w);
             Self::from_xyzw(0.0, 0.0, z * len_rcp, w * len_rcp)
         }
     }
 
-    /// Returns the rotation axis and angle (in radians) of `self`.
+    /// Returns the rotation axis (normalized) and angle (in radians) of `self`.
     #[inline]
+    #[must_use]
     pub fn to_axis_angle(self) -> (Vec3, f32) {
         const EPSILON: f32 = 1.0e-8;
-        const EPSILON_SQUARED: f32 = EPSILON * EPSILON;
-        let w = self.w;
-        let angle = w.acos_approx() * 2.0;
-        let scale_sq = f32::max(1.0 - w * w, 0.0);
-        if scale_sq >= EPSILON_SQUARED {
-            (
-                Vec3::new(self.x, self.y, self.z) * scale_sq.sqrt().recip(),
-                angle,
-            )
+        let v = Vec3::new(self.x, self.y, self.z);
+        let length = v.length();
+        if length >= EPSILON {
+            let angle = 2.0 * math::atan2(length, self.w);
+            let axis = v / length;
+            (axis, angle)
         } else {
-            (Vec3::X, angle)
+            (Vec3::X, 0.0)
         }
     }
 
     /// Returns the rotation axis scaled by the rotation in radians.
     #[inline]
+    #[must_use]
     pub fn to_scaled_axis(self) -> Vec3 {
         let (axis, angle) = self.to_axis_angle();
         axis * angle
@@ -368,26 +385,29 @@
 
     /// Returns the rotation angles for the given euler rotation sequence.
     #[inline]
+    #[must_use]
     pub fn to_euler(self, euler: EulerRot) -> (f32, f32, f32) {
         euler.convert_quat(self)
     }
 
     /// `[x, y, z, w]`
     #[inline]
+    #[must_use]
     pub fn to_array(&self) -> [f32; 4] {
         [self.x, self.y, self.z, self.w]
     }
 
     /// Returns the vector part of the quaternion.
     #[inline]
+    #[must_use]
     pub fn xyz(self) -> Vec3 {
         Vec3::new(self.x, self.y, self.z)
     }
 
     /// Returns the quaternion conjugate of `self`. For a unit quaternion the
     /// conjugate is also the inverse.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn conjugate(self) -> Self {
         const SIGN: v128 = v128_from_f32x4([-1.0, -1.0, -1.0, 1.0]);
         Self(f32x4_mul(self.0, SIGN))
@@ -402,8 +422,8 @@
     /// # Panics
     ///
     /// Will panic if `self` is not normalized when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn inverse(self) -> Self {
         glam_assert!(self.is_normalized());
         self.conjugate()
@@ -412,6 +432,7 @@
     /// Computes the dot product of `self` and `rhs`. The dot product is
     /// equal to the cosine of the angle between two quaternion rotations.
     #[inline]
+    #[must_use]
     pub fn dot(self, rhs: Self) -> f32 {
         Vec4::from(self).dot(Vec4::from(rhs))
     }
@@ -419,6 +440,7 @@
     /// Computes the length of `self`.
     #[doc(alias = "magnitude")]
     #[inline]
+    #[must_use]
     pub fn length(self) -> f32 {
         Vec4::from(self).length()
     }
@@ -429,6 +451,7 @@
     /// root operation.
     #[doc(alias = "magnitude2")]
     #[inline]
+    #[must_use]
     pub fn length_squared(self) -> f32 {
         Vec4::from(self).length_squared()
     }
@@ -437,6 +460,7 @@
     ///
     /// For valid results, `self` must _not_ be of length zero.
     #[inline]
+    #[must_use]
     pub fn length_recip(self) -> f32 {
         Vec4::from(self).length_recip()
     }
@@ -448,8 +472,8 @@
     /// Panics
     ///
     /// Will panic if `self` is zero length when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn normalize(self) -> Self {
         Self::from_vec4(Vec4::from(self).normalize())
     }
@@ -457,11 +481,13 @@
     /// Returns `true` if, and only if, all elements are finite.
     /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
     #[inline]
+    #[must_use]
     pub fn is_finite(self) -> bool {
         Vec4::from(self).is_finite()
     }
 
     #[inline]
+    #[must_use]
     pub fn is_nan(self) -> bool {
         Vec4::from(self).is_nan()
     }
@@ -470,11 +496,13 @@
     ///
     /// Uses a precision threshold of `1e-6`.
     #[inline]
+    #[must_use]
     pub fn is_normalized(self) -> bool {
         Vec4::from(self).is_normalized()
     }
 
     #[inline]
+    #[must_use]
     pub fn is_near_identity(self) -> bool {
         // Based on https://github.com/nfrechette/rtm `rtm::quat_near_identity`
         let threshold_angle = 0.002_847_144_6;
@@ -491,7 +519,7 @@
         // If the quat.w is close to -1.0, the angle will be near 2*PI which is close to
         // a negative 0 rotation. By forcing quat.w to be positive, we'll end up with
         // the shortest path.
-        let positive_w_angle = self.w.abs().acos_approx() * 2.0;
+        let positive_w_angle = math::acos_approx(math::abs(self.w)) * 2.0;
         positive_w_angle < threshold_angle
     }
 
@@ -504,9 +532,10 @@
     ///
     /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn angle_between(self, rhs: Self) -> f32 {
         glam_assert!(self.is_normalized() && rhs.is_normalized());
-        self.dot(rhs).abs().acos_approx() * 2.0
+        math::acos_approx(math::abs(self.dot(rhs))) * 2.0
     }
 
     /// Returns true if the absolute difference of all elements between `self` and `rhs`
@@ -519,6 +548,7 @@
     /// For more see
     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
     #[inline]
+    #[must_use]
     pub fn abs_diff_eq(self, rhs: Self, max_abs_diff: f32) -> bool {
         Vec4::from(self).abs_diff_eq(Vec4::from(rhs), max_abs_diff)
     }
@@ -532,8 +562,9 @@
     /// # Panics
     ///
     /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
-    #[inline]
     #[doc(alias = "mix")]
+    #[inline]
+    #[must_use]
     pub fn lerp(self, end: Self, s: f32) -> Self {
         glam_assert!(self.is_normalized());
         glam_assert!(end.is_normalized());
@@ -562,6 +593,7 @@
     ///
     /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn slerp(self, mut end: Self, s: f32) -> Self {
         // http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/
         glam_assert!(self.is_normalized());
@@ -585,7 +617,7 @@
             // assumes lerp returns a normalized quaternion
             self.lerp(end, s)
         } else {
-            let theta = dot.acos_approx();
+            let theta = math::acos_approx(dot);
 
             // TODO: v128_sin is broken
             // let x = 1.0 - s;
@@ -594,9 +626,9 @@
             // let w = 0.0;
             // let tmp = f32x4_mul(f32x4_splat(theta), f32x4(x, y, z, w));
             // let tmp = v128_sin(tmp);
-            let x = (theta * (1.0 - s)).sin();
-            let y = (theta * s).sin();
-            let z = theta.sin();
+            let x = math::sin(theta * (1.0 - s));
+            let y = math::sin(theta * s);
+            let z = math::sin(theta);
             let w = 0.0;
             let tmp = f32x4(x, y, z, w);
 
@@ -617,6 +649,7 @@
     ///
     /// Will panic if `self` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn mul_vec3(self, rhs: Vec3) -> Vec3 {
         glam_assert!(self.is_normalized());
 
@@ -632,6 +665,7 @@
     ///
     /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn mul_quat(self, rhs: Self) -> Self {
         glam_assert!(self.is_normalized());
         glam_assert!(rhs.is_normalized());
@@ -672,6 +706,7 @@
 
     /// Creates a quaternion from a 3x3 rotation matrix inside a 3D affine transform.
     #[inline]
+    #[must_use]
     pub fn from_affine3(a: &crate::Affine3A) -> Self {
         #[allow(clippy::useless_conversion)]
         Self::from_rotation_axes(
@@ -683,6 +718,7 @@
 
     /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
     #[inline]
+    #[must_use]
     pub fn mul_vec3a(self, rhs: Vec3A) -> Vec3A {
         const TWO: v128 = v128_from_f32x4([2.0; 4]);
         let w = i32x4_shuffle::<3, 3, 7, 7>(self.0, self.0);
@@ -698,9 +734,17 @@
     }
 
     #[inline]
-    pub fn as_f64(self) -> DQuat {
+    #[must_use]
+    pub fn as_dquat(self) -> DQuat {
         DQuat::from_xyzw(self.x as f64, self.y as f64, self.z as f64, self.w as f64)
     }
+
+    #[inline]
+    #[must_use]
+    #[deprecated(since = "0.24.2", note = "Use as_dquat() instead")]
+    pub fn as_f64(self) -> DQuat {
+        self.as_dquat()
+    }
 }
 
 #[cfg(not(target_arch = "spirv"))]
diff --git a/src/f32/wasm32/vec3a.rs b/src/f32/wasm32/vec3a.rs
index 33df7cf..70ae013 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::{wasm32::*, BVec3A, Vec2, Vec3, Vec4};
+use crate::{f32::math, wasm32::*, BVec3A, Vec2, Vec3, Vec4};
 
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
@@ -9,10 +9,7 @@
 
 use core::arch::wasm32::*;
 
-#[cfg(feature = "libm")]
-#[allow(unused_imports)]
-use num_traits::Float;
-
+#[repr(C)]
 union UnionCast {
     a: [f32; 4],
     v: Vec3A,
@@ -20,16 +17,20 @@
 
 /// Creates a 3-dimensional vector.
 #[inline(always)]
+#[must_use]
 pub const fn vec3a(x: f32, y: f32, z: f32) -> Vec3A {
     Vec3A::new(x, y, z)
 }
 
-/// A 3-dimensional vector with SIMD support.
+/// A 3-dimensional vector.
 ///
-/// This type is 16 byte aligned. A SIMD vector type is used for storage on supported platforms for
-/// better performance than the `Vec3` type.
+/// SIMD vector types are used for storage on supported platforms for better
+/// performance than the [`Vec3`] type.
 ///
-/// It is possible to convert between `Vec3` and `Vec3A` types using `From` trait implementations.
+/// It is possible to convert between [`Vec3`] and [`Vec3A`] types using [`From`]
+/// or [`Into`] trait implementations.
+///
+/// This type is 16 byte aligned.
 #[derive(Clone, Copy)]
 #[repr(transparent)]
 pub struct Vec3A(pub(crate) v128);
@@ -44,25 +45,37 @@
     /// All negative ones.
     pub const NEG_ONE: Self = Self::splat(-1.0);
 
-    /// All NAN.
+    /// All `f32::MIN`.
+    pub const MIN: Self = Self::splat(f32::MIN);
+
+    /// All `f32::MAX`.
+    pub const MAX: Self = Self::splat(f32::MAX);
+
+    /// All `f32::NAN`.
     pub const NAN: Self = Self::splat(f32::NAN);
 
-    /// A unit-length vector pointing along the positive X axis.
+    /// All `f32::INFINITY`.
+    pub const INFINITY: Self = Self::splat(f32::INFINITY);
+
+    /// All `f32::NEG_INFINITY`.
+    pub const NEG_INFINITY: Self = Self::splat(f32::NEG_INFINITY);
+
+    /// A unit vector pointing along the positive X axis.
     pub const X: Self = Self::new(1.0, 0.0, 0.0);
 
-    /// A unit-length vector pointing along the positive Y axis.
+    /// A unit vector pointing along the positive Y axis.
     pub const Y: Self = Self::new(0.0, 1.0, 0.0);
 
-    /// A unit-length vector pointing along the positive Z axis.
+    /// A unit vector pointing along the positive Z axis.
     pub const Z: Self = Self::new(0.0, 0.0, 1.0);
 
-    /// A unit-length vector pointing along the negative X axis.
+    /// A unit vector pointing along the negative X axis.
     pub const NEG_X: Self = Self::new(-1.0, 0.0, 0.0);
 
-    /// A unit-length vector pointing along the negative Y axis.
+    /// A unit vector pointing along the negative Y axis.
     pub const NEG_Y: Self = Self::new(0.0, -1.0, 0.0);
 
-    /// A unit-length vector pointing along the negative Z axis.
+    /// A unit vector pointing along the negative Z axis.
     pub const NEG_Z: Self = Self::new(0.0, 0.0, -1.0);
 
     /// The unit axes.
@@ -70,12 +83,14 @@
 
     /// Creates a new vector.
     #[inline(always)]
+    #[must_use]
     pub const fn new(x: f32, y: f32, z: f32) -> Self {
         Self(f32x4(x, y, z, z))
     }
 
     /// Creates a vector with all elements set to `v`.
     #[inline]
+    #[must_use]
     pub const fn splat(v: f32) -> Self {
         unsafe { UnionCast { a: [v; 4] }.v }
     }
@@ -86,18 +101,21 @@
     /// A true element in the mask uses the corresponding element from `if_true`, and false
     /// uses the element from `if_false`.
     #[inline]
+    #[must_use]
     pub fn select(mask: BVec3A, if_true: Self, if_false: Self) -> Self {
         Self(v128_bitselect(if_true.0, if_false.0, mask.0))
     }
 
     /// Creates a new vector from an array.
     #[inline]
+    #[must_use]
     pub const fn from_array(a: [f32; 3]) -> Self {
         Self::new(a[0], a[1], a[2])
     }
 
     /// `[x, y, z]`
     #[inline]
+    #[must_use]
     pub const fn to_array(&self) -> [f32; 3] {
         unsafe { *(self as *const Vec3A as *const [f32; 3]) }
     }
@@ -108,6 +126,7 @@
     ///
     /// Panics if `slice` is less than 3 elements long.
     #[inline]
+    #[must_use]
     pub const fn from_slice(slice: &[f32]) -> Self {
         Self::new(slice[0], slice[1], slice[2])
     }
@@ -127,20 +146,23 @@
     /// Internal method for creating a 3D vector from a 4D vector, discarding `w`.
     #[allow(dead_code)]
     #[inline]
+    #[must_use]
     pub(crate) fn from_vec4(v: Vec4) -> Self {
         Self(v.0)
     }
 
     /// Creates a 4D vector from `self` and the given `w` value.
     #[inline]
+    #[must_use]
     pub fn extend(self, w: f32) -> Vec4 {
         Vec4::new(self.x, self.y, self.z, w)
     }
 
     /// Creates a 2D vector from the `x` and `y` elements of `self`, discarding `z`.
     ///
-    /// Truncation may also be performed by using `self.xy()` or `Vec2::from()`.
+    /// Truncation may also be performed by using [`self.xy()`][crate::swizzles::Vec3Swizzles::xy()].
     #[inline]
+    #[must_use]
     pub fn truncate(self) -> Vec2 {
         use crate::swizzles::Vec3Swizzles;
         self.xy()
@@ -148,18 +170,21 @@
 
     /// Computes the dot product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn dot(self, rhs: Self) -> f32 {
         dot3(self.0, rhs.0)
     }
 
     /// Returns a vector where every component is the dot product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn dot_into_vec(self, rhs: Self) -> Self {
-        Self(unsafe { dot3_into_v128(self.0, rhs.0) })
+        Self(dot3_into_v128(self.0, rhs.0))
     }
 
     /// Computes the cross product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn cross(self, rhs: Self) -> Self {
         let lhszxy = i32x4_shuffle::<2, 0, 1, 1>(self.0, self.0);
         let rhszxy = i32x4_shuffle::<2, 0, 1, 1>(rhs.0, rhs.0);
@@ -173,6 +198,7 @@
     ///
     /// In other words this computes `[self.x.min(rhs.x), self.y.min(rhs.y), ..]`.
     #[inline]
+    #[must_use]
     pub fn min(self, rhs: Self) -> Self {
         Self(f32x4_pmin(self.0, rhs.0))
     }
@@ -181,6 +207,7 @@
     ///
     /// In other words this computes `[self.x.max(rhs.x), self.y.max(rhs.y), ..]`.
     #[inline]
+    #[must_use]
     pub fn max(self, rhs: Self) -> Self {
         Self(f32x4_pmax(self.0, rhs.0))
     }
@@ -193,6 +220,7 @@
     ///
     /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn clamp(self, min: Self, max: Self) -> Self {
         glam_assert!(min.cmple(max).all(), "clamp: expected min <= max");
         self.max(min).min(max)
@@ -202,6 +230,7 @@
     ///
     /// In other words this computes `min(x, y, ..)`.
     #[inline]
+    #[must_use]
     pub fn min_element(self) -> f32 {
         let v = self.0;
         let v = f32x4_pmin(v, i32x4_shuffle::<2, 2, 1, 1>(v, v));
@@ -213,6 +242,7 @@
     ///
     /// In other words this computes `max(x, y, ..)`.
     #[inline]
+    #[must_use]
     pub fn max_element(self) -> f32 {
         let v = self.0;
         let v = f32x4_pmax(v, i32x4_shuffle::<2, 2, 0, 0>(v, v));
@@ -226,6 +256,7 @@
     /// In other words, this computes `[self.x == rhs.x, self.y == rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpeq(self, rhs: Self) -> BVec3A {
         BVec3A(f32x4_eq(self.0, rhs.0))
     }
@@ -236,6 +267,7 @@
     /// In other words this computes `[self.x != rhs.x, self.y != rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpne(self, rhs: Self) -> BVec3A {
         BVec3A(f32x4_ne(self.0, rhs.0))
     }
@@ -246,6 +278,7 @@
     /// In other words this computes `[self.x >= rhs.x, self.y >= rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpge(self, rhs: Self) -> BVec3A {
         BVec3A(f32x4_ge(self.0, rhs.0))
     }
@@ -256,6 +289,7 @@
     /// In other words this computes `[self.x > rhs.x, self.y > rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpgt(self, rhs: Self) -> BVec3A {
         BVec3A(f32x4_gt(self.0, rhs.0))
     }
@@ -266,6 +300,7 @@
     /// In other words this computes `[self.x <= rhs.x, self.y <= rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmple(self, rhs: Self) -> BVec3A {
         BVec3A(f32x4_le(self.0, rhs.0))
     }
@@ -276,12 +311,14 @@
     /// In other words this computes `[self.x < rhs.x, self.y < rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmplt(self, rhs: Self) -> BVec3A {
         BVec3A(f32x4_lt(self.0, rhs.0))
     }
 
     /// Returns a vector containing the absolute value of each element of `self`.
     #[inline]
+    #[must_use]
     pub fn abs(self) -> Self {
         Self(f32x4_abs(self.0))
     }
@@ -292,6 +329,7 @@
     /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
     /// - `NAN` if the number is `NAN`
     #[inline]
+    #[must_use]
     pub fn signum(self) -> Self {
         unsafe {
             let result = Self(v128_or(v128_and(self.0, Self::NEG_ONE.0), Self::ONE.0));
@@ -302,6 +340,7 @@
 
     /// Returns a vector with signs of `rhs` and the magnitudes of `self`.
     #[inline]
+    #[must_use]
     pub fn copysign(self, rhs: Self) -> Self {
         unsafe {
             let mask = Self::splat(-0.0);
@@ -317,6 +356,7 @@
     /// A negative element results in a `1` bit and a positive element in a `0` bit.  Element `x` goes
     /// into the first lowest bit, element `y` into the second, etc.
     #[inline]
+    #[must_use]
     pub fn is_negative_bitmask(self) -> u32 {
         (u32x4_bitmask(self.0) & 0x7) as u32
     }
@@ -324,12 +364,14 @@
     /// Returns `true` if, and only if, all elements are finite.  If any element is either
     /// `NaN`, positive or negative infinity, this will return `false`.
     #[inline]
+    #[must_use]
     pub fn is_finite(self) -> bool {
         self.x.is_finite() && self.y.is_finite() && self.z.is_finite()
     }
 
     /// Returns `true` if any elements are `NaN`.
     #[inline]
+    #[must_use]
     pub fn is_nan(self) -> bool {
         self.is_nan_mask().any()
     }
@@ -338,6 +380,7 @@
     ///
     /// In other words, this computes `[x.is_nan(), y.is_nan(), z.is_nan(), w.is_nan()]`.
     #[inline]
+    #[must_use]
     pub fn is_nan_mask(self) -> BVec3A {
         BVec3A(f32x4_ne(self.0, self.0))
     }
@@ -345,6 +388,7 @@
     /// Computes the length of `self`.
     #[doc(alias = "magnitude")]
     #[inline]
+    #[must_use]
     pub fn length(self) -> f32 {
         let dot = dot3_in_x(self.0, self.0);
         f32x4_extract_lane::<0>(f32x4_sqrt(dot))
@@ -355,6 +399,7 @@
     /// This is faster than `length()` as it avoids a square root operation.
     #[doc(alias = "magnitude2")]
     #[inline]
+    #[must_use]
     pub fn length_squared(self) -> f32 {
         self.dot(self)
     }
@@ -363,6 +408,7 @@
     ///
     /// For valid results, `self` must _not_ be of length zero.
     #[inline]
+    #[must_use]
     pub fn length_recip(self) -> f32 {
         let dot = dot3_in_x(self.0, self.0);
         f32x4_extract_lane::<0>(f32x4_div(Self::ONE.0, f32x4_sqrt(dot)))
@@ -370,27 +416,53 @@
 
     /// Computes the Euclidean distance between two points in space.
     #[inline]
+    #[must_use]
     pub fn distance(self, rhs: Self) -> f32 {
         (self - rhs).length()
     }
 
     /// Compute the squared euclidean distance between two points in space.
     #[inline]
+    #[must_use]
     pub fn distance_squared(self, rhs: Self) -> f32 {
         (self - rhs).length_squared()
     }
 
+    /// Returns the element-wise quotient of [Euclidean division] of `self` by `rhs`.
+    #[inline]
+    #[must_use]
+    pub fn div_euclid(self, rhs: Self) -> Self {
+        Self::new(
+            math::div_euclid(self.x, rhs.x),
+            math::div_euclid(self.y, rhs.y),
+            math::div_euclid(self.z, rhs.z),
+        )
+    }
+
+    /// Returns the element-wise remainder of [Euclidean division] of `self` by `rhs`.
+    ///
+    /// [Euclidean division]: f32::rem_euclid
+    #[inline]
+    #[must_use]
+    pub fn rem_euclid(self, rhs: Self) -> Self {
+        Self::new(
+            math::rem_euclid(self.x, rhs.x),
+            math::rem_euclid(self.y, rhs.y),
+            math::rem_euclid(self.z, rhs.z),
+        )
+    }
+
     /// Returns `self` normalized to length 1.0.
     ///
     /// For valid results, `self` must _not_ be of length zero, nor very close to zero.
     ///
-    /// See also [`Self::try_normalize`] and [`Self::normalize_or_zero`].
+    /// See also [`Self::try_normalize()`] and [`Self::normalize_or_zero()`].
     ///
     /// Panics
     ///
     /// Will panic if `self` is zero length when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn normalize(self) -> Self {
         let length = f32x4_sqrt(dot3_into_v128(self.0, self.0));
         #[allow(clippy::let_and_return)]
@@ -404,9 +476,9 @@
     /// In particular, if the input is zero (or very close to zero), or non-finite,
     /// the result of this operation will be `None`.
     ///
-    /// See also [`Self::normalize_or_zero`].
-    #[must_use]
+    /// See also [`Self::normalize_or_zero()`].
     #[inline]
+    #[must_use]
     pub fn try_normalize(self) -> Option<Self> {
         let rcp = self.length_recip();
         if rcp.is_finite() && rcp > 0.0 {
@@ -421,9 +493,9 @@
     /// In particular, if the input is zero (or very close to zero), or non-finite,
     /// the result of this operation will be zero.
     ///
-    /// See also [`Self::try_normalize`].
-    #[must_use]
+    /// See also [`Self::try_normalize()`].
     #[inline]
+    #[must_use]
     pub fn normalize_or_zero(self) -> Self {
         let rcp = self.length_recip();
         if rcp.is_finite() && rcp > 0.0 {
@@ -437,9 +509,10 @@
     ///
     /// Uses a precision threshold of `1e-6`.
     #[inline]
+    #[must_use]
     pub fn is_normalized(self) -> bool {
         // TODO: do something with epsilon
-        (self.length_squared() - 1.0).abs() <= 1e-4
+        math::abs(self.length_squared() - 1.0) <= 1e-4
     }
 
     /// Returns the vector projection of `self` onto `rhs`.
@@ -449,8 +522,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` is zero length when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn project_onto(self, rhs: Self) -> Self {
         let other_len_sq_rcp = rhs.dot(rhs).recip();
         glam_assert!(other_len_sq_rcp.is_finite());
@@ -467,8 +540,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` has a length of zero when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn reject_from(self, rhs: Self) -> Self {
         self - self.project_onto(rhs)
     }
@@ -480,8 +553,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` is not normalized when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn project_onto_normalized(self, rhs: Self) -> Self {
         glam_assert!(rhs.is_normalized());
         rhs * self.dot(rhs)
@@ -497,8 +570,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` is not normalized when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn reject_from_normalized(self, rhs: Self) -> Self {
         self - self.project_onto_normalized(rhs)
     }
@@ -506,6 +579,7 @@
     /// Returns a vector containing the nearest integer to a number for each element of `self`.
     /// Round half-way cases away from 0.0.
     #[inline]
+    #[must_use]
     pub fn round(self) -> Self {
         Self(f32x4_nearest(self.0))
     }
@@ -513,6 +587,7 @@
     /// Returns a vector containing the largest integer less than or equal to a number for each
     /// element of `self`.
     #[inline]
+    #[must_use]
     pub fn floor(self) -> Self {
         Self(f32x4_floor(self.0))
     }
@@ -520,15 +595,25 @@
     /// Returns a vector containing the smallest integer greater than or equal to a number for
     /// each element of `self`.
     #[inline]
+    #[must_use]
     pub fn ceil(self) -> Self {
         Self(f32x4_ceil(self.0))
     }
 
+    /// Returns a vector containing the integer part each element of `self`. This means numbers are
+    /// always truncated towards zero.
+    #[inline]
+    #[must_use]
+    pub fn trunc(self) -> Self {
+        Self(f32x4_trunc(self.0))
+    }
+
     /// Returns a vector containing the fractional part of the vector, e.g. `self -
     /// self.floor()`.
     ///
     /// Note that this is fast but not precise for large numbers.
     #[inline]
+    #[must_use]
     pub fn fract(self) -> Self {
         self - self.floor()
     }
@@ -536,18 +621,25 @@
     /// Returns a vector containing `e^self` (the exponential function) for each element of
     /// `self`.
     #[inline]
+    #[must_use]
     pub fn exp(self) -> Self {
-        Self::new(self.x.exp(), self.y.exp(), self.z.exp())
+        Self::new(math::exp(self.x), math::exp(self.y), math::exp(self.z))
     }
 
     /// Returns a vector containing each element of `self` raised to the power of `n`.
     #[inline]
+    #[must_use]
     pub fn powf(self, n: f32) -> Self {
-        Self::new(self.x.powf(n), self.y.powf(n), self.z.powf(n))
+        Self::new(
+            math::powf(self.x, n),
+            math::powf(self.y, n),
+            math::powf(self.z, n),
+        )
     }
 
     /// Returns a vector containing the reciprocal `1.0/n` of each element of `self`.
     #[inline]
+    #[must_use]
     pub fn recip(self) -> Self {
         Self(f32x4_div(Self::ONE.0, self.0))
     }
@@ -559,6 +651,7 @@
     /// extrapolated.
     #[doc(alias = "mix")]
     #[inline]
+    #[must_use]
     pub fn lerp(self, rhs: Self, s: f32) -> Self {
         self + ((rhs - self) * s)
     }
@@ -573,6 +666,7 @@
     /// For more see
     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
     #[inline]
+    #[must_use]
     pub fn abs_diff_eq(self, rhs: Self, max_abs_diff: f32) -> bool {
         self.sub(rhs).abs().cmple(Self::splat(max_abs_diff)).all()
     }
@@ -583,33 +677,38 @@
     ///
     /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn clamp_length(self, min: f32, max: f32) -> Self {
         glam_assert!(min <= max);
         let length_sq = self.length_squared();
         if length_sq < min * min {
-            self * (length_sq.sqrt().recip() * min)
+            min * (self / math::sqrt(length_sq))
         } else if length_sq > max * max {
-            self * (length_sq.sqrt().recip() * max)
+            max * (self / math::sqrt(length_sq))
         } else {
             self
         }
     }
 
     /// Returns a vector with a length no more than `max`
+    #[inline]
+    #[must_use]
     pub fn clamp_length_max(self, max: f32) -> Self {
         let length_sq = self.length_squared();
         if length_sq > max * max {
-            self * (length_sq.sqrt().recip() * max)
+            max * (self / math::sqrt(length_sq))
         } else {
             self
         }
     }
 
     /// Returns a vector with a length no less than `min`
+    #[inline]
+    #[must_use]
     pub fn clamp_length_min(self, min: f32) -> Self {
         let length_sq = self.length_squared();
         if length_sq < min * min {
-            self * (length_sq.sqrt().recip() * min)
+            min * (self / math::sqrt(length_sq))
         } else {
             self
         }
@@ -623,74 +722,74 @@
     /// and will be heavily dependant on designing algorithms with specific target hardware in
     /// mind.
     #[inline]
+    #[must_use]
     pub fn mul_add(self, a: Self, b: Self) -> Self {
         Self::new(
-            self.x.mul_add(a.x, b.x),
-            self.y.mul_add(a.y, b.y),
-            self.z.mul_add(a.z, b.z),
+            math::mul_add(self.x, a.x, b.x),
+            math::mul_add(self.y, a.y, b.y),
+            math::mul_add(self.z, a.z, b.z),
         )
     }
 
     /// Returns the angle (in radians) between two vectors.
     ///
-    /// The input vectors do not need to be unit length however they must be non-zero.
+    /// The inputs do not need to be unit vectors however they must be non-zero.
     #[inline]
+    #[must_use]
     pub fn angle_between(self, rhs: Self) -> f32 {
-        use crate::FloatEx;
-        self.dot(rhs)
-            .div(self.length_squared().mul(rhs.length_squared()).sqrt())
-            .acos_approx()
+        math::acos_approx(
+            self.dot(rhs)
+                .div(math::sqrt(self.length_squared().mul(rhs.length_squared()))),
+        )
     }
 
     /// Returns some vector that is orthogonal to the given one.
     ///
     /// The input vector must be finite and non-zero.
     ///
-    /// The output vector is not necessarily unit-length.
-    /// For that use [`Self::any_orthonormal_vector`] instead.
+    /// The output vector is not necessarily unit length. For that use
+    /// [`Self::any_orthonormal_vector()`] instead.
     #[inline]
+    #[must_use]
     pub fn any_orthogonal_vector(&self) -> Self {
         // This can probably be optimized
-        if self.x.abs() > self.y.abs() {
+        if math::abs(self.x) > math::abs(self.y) {
             Self::new(-self.z, 0.0, self.x) // self.cross(Self::Y)
         } else {
             Self::new(0.0, self.z, -self.y) // self.cross(Self::X)
         }
     }
 
-    /// Returns any unit-length vector that is orthogonal to the given one.
-    /// The input vector must be finite and non-zero.
+    /// Returns any unit vector that is orthogonal to the given one.
+    ///
+    /// The input vector must be unit length.
     ///
     /// # Panics
     ///
     /// Will panic if `self` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn any_orthonormal_vector(&self) -> Self {
         glam_assert!(self.is_normalized());
         // From https://graphics.pixar.com/library/OrthonormalB/paper.pdf
-        #[cfg(feature = "std")]
-        let sign = (1.0_f32).copysign(self.z);
-        #[cfg(not(feature = "std"))]
-        let sign = self.z.signum();
+        let sign = math::signum(self.z);
         let a = -1.0 / (sign + self.z);
         let b = self.x * self.y * a;
         Self::new(b, sign + self.y * self.y * a, -self.y)
     }
 
-    /// Given a unit-length vector return two other vectors that together form an orthonormal
-    /// basis.  That is, all three vectors are orthogonal to each other and are normalized.
+    /// Given a unit vector return two other vectors that together form an orthonormal
+    /// basis. That is, all three vectors are orthogonal to each other and are normalized.
     ///
     /// # Panics
     ///
     /// Will panic if `self` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn any_orthonormal_pair(&self) -> (Self, Self) {
         glam_assert!(self.is_normalized());
         // From https://graphics.pixar.com/library/OrthonormalB/paper.pdf
-        #[cfg(feature = "std")]
-        let sign = (1.0_f32).copysign(self.z);
-        #[cfg(not(feature = "std"))]
-        let sign = self.z.signum();
+        let sign = math::signum(self.z);
         let a = -1.0 / (sign + self.z);
         let b = self.x * self.y * a;
         (
@@ -701,21 +800,52 @@
 
     /// Casts all elements of `self` to `f64`.
     #[inline]
+    #[must_use]
     pub fn as_dvec3(&self) -> crate::DVec3 {
         crate::DVec3::new(self.x as f64, self.y as f64, self.z as f64)
     }
 
+    /// Casts all elements of `self` to `i16`.
+    #[inline]
+    #[must_use]
+    pub fn as_i16vec3(&self) -> crate::I16Vec3 {
+        crate::I16Vec3::new(self.x as i16, self.y as i16, self.z as i16)
+    }
+
+    /// Casts all elements of `self` to `u16`.
+    #[inline]
+    #[must_use]
+    pub fn as_u16vec3(&self) -> crate::U16Vec3 {
+        crate::U16Vec3::new(self.x as u16, self.y as u16, self.z as u16)
+    }
+
     /// Casts all elements of `self` to `i32`.
     #[inline]
+    #[must_use]
     pub fn as_ivec3(&self) -> crate::IVec3 {
         crate::IVec3::new(self.x as i32, self.y as i32, self.z as i32)
     }
 
     /// Casts all elements of `self` to `u32`.
     #[inline]
+    #[must_use]
     pub fn as_uvec3(&self) -> crate::UVec3 {
         crate::UVec3::new(self.x as u32, self.y as u32, self.z as u32)
     }
+
+    /// Casts all elements of `self` to `i64`.
+    #[inline]
+    #[must_use]
+    pub fn as_i64vec3(&self) -> crate::I64Vec3 {
+        crate::I64Vec3::new(self.x as i64, self.y as i64, self.z as i64)
+    }
+
+    /// Casts all elements of `self` to `u64`.
+    #[inline]
+    #[must_use]
+    pub fn as_u64vec3(&self) -> crate::U64Vec3 {
+        crate::U64Vec3::new(self.x as u64, self.y as u64, self.z as u64)
+    }
 }
 
 impl Default for Vec3A {
@@ -1080,7 +1210,7 @@
 }
 
 impl From<Vec4> for Vec3A {
-    /// Creates a `Vec3A` from the `x`, `y` and `z` elements of `self` discarding `w`.
+    /// Creates a [`Vec3A`] from the `x`, `y` and `z` elements of `self` discarding `w`.
     ///
     /// On architectures where SIMD is supported such as SSE2 on `x86_64` this conversion is a noop.
     #[inline]
diff --git a/src/f32/wasm32/vec4.rs b/src/f32/wasm32/vec4.rs
index 10f3927..4608b34 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::{wasm32::*, BVec4A, Vec2, Vec3, Vec3A};
+use crate::{f32::math, wasm32::*, BVec4A, Vec2, Vec3, Vec3A};
 
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
@@ -9,10 +9,7 @@
 
 use core::arch::wasm32::*;
 
-#[cfg(feature = "libm")]
-#[allow(unused_imports)]
-use num_traits::Float;
-
+#[repr(C)]
 union UnionCast {
     a: [f32; 4],
     v: Vec4,
@@ -20,13 +17,16 @@
 
 /// Creates a 4-dimensional vector.
 #[inline(always)]
+#[must_use]
 pub const fn vec4(x: f32, y: f32, z: f32, w: f32) -> Vec4 {
     Vec4::new(x, y, z, w)
 }
 
-/// A 4-dimensional vector with SIMD support.
+/// A 4-dimensional vector.
 ///
-/// This type uses 16 byte aligned SIMD vector type for storage.
+/// SIMD vector types are used for storage on supported platforms.
+///
+/// This type is 16 byte aligned.
 #[derive(Clone, Copy)]
 #[repr(transparent)]
 pub struct Vec4(pub(crate) v128);
@@ -41,31 +41,43 @@
     /// All negative ones.
     pub const NEG_ONE: Self = Self::splat(-1.0);
 
-    /// All NAN.
+    /// All `f32::MIN`.
+    pub const MIN: Self = Self::splat(f32::MIN);
+
+    /// All `f32::MAX`.
+    pub const MAX: Self = Self::splat(f32::MAX);
+
+    /// All `f32::NAN`.
     pub const NAN: Self = Self::splat(f32::NAN);
 
-    /// A unit-length vector pointing along the positive X axis.
+    /// All `f32::INFINITY`.
+    pub const INFINITY: Self = Self::splat(f32::INFINITY);
+
+    /// All `f32::NEG_INFINITY`.
+    pub const NEG_INFINITY: Self = Self::splat(f32::NEG_INFINITY);
+
+    /// A unit vector pointing along the positive X axis.
     pub const X: Self = Self::new(1.0, 0.0, 0.0, 0.0);
 
-    /// A unit-length vector pointing along the positive Y axis.
+    /// A unit vector pointing along the positive Y axis.
     pub const Y: Self = Self::new(0.0, 1.0, 0.0, 0.0);
 
-    /// A unit-length vector pointing along the positive Z axis.
+    /// A unit vector pointing along the positive Z axis.
     pub const Z: Self = Self::new(0.0, 0.0, 1.0, 0.0);
 
-    /// A unit-length vector pointing along the positive W axis.
+    /// A unit vector pointing along the positive W axis.
     pub const W: Self = Self::new(0.0, 0.0, 0.0, 1.0);
 
-    /// A unit-length vector pointing along the negative X axis.
+    /// A unit vector pointing along the negative X axis.
     pub const NEG_X: Self = Self::new(-1.0, 0.0, 0.0, 0.0);
 
-    /// A unit-length vector pointing along the negative Y axis.
+    /// A unit vector pointing along the negative Y axis.
     pub const NEG_Y: Self = Self::new(0.0, -1.0, 0.0, 0.0);
 
-    /// A unit-length vector pointing along the negative Z axis.
+    /// A unit vector pointing along the negative Z axis.
     pub const NEG_Z: Self = Self::new(0.0, 0.0, -1.0, 0.0);
 
-    /// A unit-length vector pointing along the negative W axis.
+    /// A unit vector pointing along the negative W axis.
     pub const NEG_W: Self = Self::new(0.0, 0.0, 0.0, -1.0);
 
     /// The unit axes.
@@ -73,12 +85,14 @@
 
     /// Creates a new vector.
     #[inline(always)]
+    #[must_use]
     pub const fn new(x: f32, y: f32, z: f32, w: f32) -> Self {
         Self(f32x4(x, y, z, w))
     }
 
     /// Creates a vector with all elements set to `v`.
     #[inline]
+    #[must_use]
     pub const fn splat(v: f32) -> Self {
         unsafe { UnionCast { a: [v; 4] }.v }
     }
@@ -89,18 +103,21 @@
     /// A true element in the mask uses the corresponding element from `if_true`, and false
     /// uses the element from `if_false`.
     #[inline]
+    #[must_use]
     pub fn select(mask: BVec4A, if_true: Self, if_false: Self) -> Self {
         Self(v128_bitselect(if_true.0, if_false.0, mask.0))
     }
 
     /// Creates a new vector from an array.
     #[inline]
+    #[must_use]
     pub const fn from_array(a: [f32; 4]) -> Self {
         Self::new(a[0], a[1], a[2], a[3])
     }
 
     /// `[x, y, z, w]`
     #[inline]
+    #[must_use]
     pub const fn to_array(&self) -> [f32; 4] {
         unsafe { *(self as *const Vec4 as *const [f32; 4]) }
     }
@@ -111,6 +128,7 @@
     ///
     /// Panics if `slice` is less than 4 elements long.
     #[inline]
+    #[must_use]
     pub const fn from_slice(slice: &[f32]) -> Self {
         Self::new(slice[0], slice[1], slice[2], slice[3])
     }
@@ -128,12 +146,13 @@
         slice[3] = self.w;
     }
 
-    /// Creates a 2D vector from the `x`, `y` and `z` elements of `self`, discarding `w`.
+    /// Creates a 3D vector from the `x`, `y` and `z` elements of `self`, discarding `w`.
     ///
-    /// Truncation to `Vec3` may also be performed by using `self.xyz()` or `Vec3::from()`.
+    /// Truncation to [`Vec3`] may also be performed by using [`self.xyz()`][crate::swizzles::Vec4Swizzles::xyz()].
     ///
-    /// To truncate to `Vec3A` use `Vec3A::from()`.
+    /// To truncate to [`Vec3A`] use [`Vec3A::from()`].
     #[inline]
+    #[must_use]
     pub fn truncate(self) -> Vec3 {
         use crate::swizzles::Vec4Swizzles;
         self.xyz()
@@ -141,20 +160,23 @@
 
     /// Computes the dot product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn dot(self, rhs: Self) -> f32 {
         dot4(self.0, rhs.0)
     }
 
     /// Returns a vector where every component is the dot product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn dot_into_vec(self, rhs: Self) -> Self {
-        Self(unsafe { dot4_into_v128(self.0, rhs.0) })
+        Self(dot4_into_v128(self.0, rhs.0))
     }
 
     /// Returns a vector containing the minimum values for each element of `self` and `rhs`.
     ///
     /// In other words this computes `[self.x.min(rhs.x), self.y.min(rhs.y), ..]`.
     #[inline]
+    #[must_use]
     pub fn min(self, rhs: Self) -> Self {
         Self(f32x4_pmin(self.0, rhs.0))
     }
@@ -163,6 +185,7 @@
     ///
     /// In other words this computes `[self.x.max(rhs.x), self.y.max(rhs.y), ..]`.
     #[inline]
+    #[must_use]
     pub fn max(self, rhs: Self) -> Self {
         Self(f32x4_pmax(self.0, rhs.0))
     }
@@ -175,6 +198,7 @@
     ///
     /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn clamp(self, min: Self, max: Self) -> Self {
         glam_assert!(min.cmple(max).all(), "clamp: expected min <= max");
         self.max(min).min(max)
@@ -184,6 +208,7 @@
     ///
     /// In other words this computes `min(x, y, ..)`.
     #[inline]
+    #[must_use]
     pub fn min_element(self) -> f32 {
         let v = self.0;
         let v = f32x4_pmin(v, i32x4_shuffle::<2, 3, 0, 0>(v, v));
@@ -195,6 +220,7 @@
     ///
     /// In other words this computes `max(x, y, ..)`.
     #[inline]
+    #[must_use]
     pub fn max_element(self) -> f32 {
         let v = self.0;
         let v = f32x4_pmax(v, i32x4_shuffle::<2, 3, 0, 0>(v, v));
@@ -208,6 +234,7 @@
     /// In other words, this computes `[self.x == rhs.x, self.y == rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpeq(self, rhs: Self) -> BVec4A {
         BVec4A(f32x4_eq(self.0, rhs.0))
     }
@@ -218,6 +245,7 @@
     /// In other words this computes `[self.x != rhs.x, self.y != rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpne(self, rhs: Self) -> BVec4A {
         BVec4A(f32x4_ne(self.0, rhs.0))
     }
@@ -228,6 +256,7 @@
     /// In other words this computes `[self.x >= rhs.x, self.y >= rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpge(self, rhs: Self) -> BVec4A {
         BVec4A(f32x4_ge(self.0, rhs.0))
     }
@@ -238,6 +267,7 @@
     /// In other words this computes `[self.x > rhs.x, self.y > rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpgt(self, rhs: Self) -> BVec4A {
         BVec4A(f32x4_gt(self.0, rhs.0))
     }
@@ -248,6 +278,7 @@
     /// In other words this computes `[self.x <= rhs.x, self.y <= rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmple(self, rhs: Self) -> BVec4A {
         BVec4A(f32x4_le(self.0, rhs.0))
     }
@@ -258,12 +289,14 @@
     /// In other words this computes `[self.x < rhs.x, self.y < rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmplt(self, rhs: Self) -> BVec4A {
         BVec4A(f32x4_lt(self.0, rhs.0))
     }
 
     /// Returns a vector containing the absolute value of each element of `self`.
     #[inline]
+    #[must_use]
     pub fn abs(self) -> Self {
         Self(f32x4_abs(self.0))
     }
@@ -274,6 +307,7 @@
     /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
     /// - `NAN` if the number is `NAN`
     #[inline]
+    #[must_use]
     pub fn signum(self) -> Self {
         unsafe {
             let result = Self(v128_or(v128_and(self.0, Self::NEG_ONE.0), Self::ONE.0));
@@ -284,6 +318,7 @@
 
     /// Returns a vector with signs of `rhs` and the magnitudes of `self`.
     #[inline]
+    #[must_use]
     pub fn copysign(self, rhs: Self) -> Self {
         unsafe {
             let mask = Self::splat(-0.0);
@@ -299,6 +334,7 @@
     /// A negative element results in a `1` bit and a positive element in a `0` bit.  Element `x` goes
     /// into the first lowest bit, element `y` into the second, etc.
     #[inline]
+    #[must_use]
     pub fn is_negative_bitmask(self) -> u32 {
         u32x4_bitmask(self.0) as u32
     }
@@ -306,12 +342,14 @@
     /// Returns `true` if, and only if, all elements are finite.  If any element is either
     /// `NaN`, positive or negative infinity, this will return `false`.
     #[inline]
+    #[must_use]
     pub fn is_finite(self) -> bool {
         self.x.is_finite() && self.y.is_finite() && self.z.is_finite() && self.w.is_finite()
     }
 
     /// Returns `true` if any elements are `NaN`.
     #[inline]
+    #[must_use]
     pub fn is_nan(self) -> bool {
         self.is_nan_mask().any()
     }
@@ -320,6 +358,7 @@
     ///
     /// In other words, this computes `[x.is_nan(), y.is_nan(), z.is_nan(), w.is_nan()]`.
     #[inline]
+    #[must_use]
     pub fn is_nan_mask(self) -> BVec4A {
         BVec4A(f32x4_ne(self.0, self.0))
     }
@@ -327,6 +366,7 @@
     /// Computes the length of `self`.
     #[doc(alias = "magnitude")]
     #[inline]
+    #[must_use]
     pub fn length(self) -> f32 {
         let dot = dot4_in_x(self.0, self.0);
         f32x4_extract_lane::<0>(f32x4_sqrt(dot))
@@ -337,6 +377,7 @@
     /// This is faster than `length()` as it avoids a square root operation.
     #[doc(alias = "magnitude2")]
     #[inline]
+    #[must_use]
     pub fn length_squared(self) -> f32 {
         self.dot(self)
     }
@@ -345,6 +386,7 @@
     ///
     /// For valid results, `self` must _not_ be of length zero.
     #[inline]
+    #[must_use]
     pub fn length_recip(self) -> f32 {
         let dot = dot4_in_x(self.0, self.0);
         f32x4_extract_lane::<0>(f32x4_div(Self::ONE.0, f32x4_sqrt(dot)))
@@ -352,27 +394,55 @@
 
     /// Computes the Euclidean distance between two points in space.
     #[inline]
+    #[must_use]
     pub fn distance(self, rhs: Self) -> f32 {
         (self - rhs).length()
     }
 
     /// Compute the squared euclidean distance between two points in space.
     #[inline]
+    #[must_use]
     pub fn distance_squared(self, rhs: Self) -> f32 {
         (self - rhs).length_squared()
     }
 
+    /// Returns the element-wise quotient of [Euclidean division] of `self` by `rhs`.
+    #[inline]
+    #[must_use]
+    pub fn div_euclid(self, rhs: Self) -> Self {
+        Self::new(
+            math::div_euclid(self.x, rhs.x),
+            math::div_euclid(self.y, rhs.y),
+            math::div_euclid(self.z, rhs.z),
+            math::div_euclid(self.w, rhs.w),
+        )
+    }
+
+    /// Returns the element-wise remainder of [Euclidean division] of `self` by `rhs`.
+    ///
+    /// [Euclidean division]: f32::rem_euclid
+    #[inline]
+    #[must_use]
+    pub fn rem_euclid(self, rhs: Self) -> Self {
+        Self::new(
+            math::rem_euclid(self.x, rhs.x),
+            math::rem_euclid(self.y, rhs.y),
+            math::rem_euclid(self.z, rhs.z),
+            math::rem_euclid(self.w, rhs.w),
+        )
+    }
+
     /// Returns `self` normalized to length 1.0.
     ///
     /// For valid results, `self` must _not_ be of length zero, nor very close to zero.
     ///
-    /// See also [`Self::try_normalize`] and [`Self::normalize_or_zero`].
+    /// See also [`Self::try_normalize()`] and [`Self::normalize_or_zero()`].
     ///
     /// Panics
     ///
     /// Will panic if `self` is zero length when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn normalize(self) -> Self {
         let length = f32x4_sqrt(dot4_into_v128(self.0, self.0));
         #[allow(clippy::let_and_return)]
@@ -386,9 +456,9 @@
     /// In particular, if the input is zero (or very close to zero), or non-finite,
     /// the result of this operation will be `None`.
     ///
-    /// See also [`Self::normalize_or_zero`].
-    #[must_use]
+    /// See also [`Self::normalize_or_zero()`].
     #[inline]
+    #[must_use]
     pub fn try_normalize(self) -> Option<Self> {
         let rcp = self.length_recip();
         if rcp.is_finite() && rcp > 0.0 {
@@ -403,9 +473,9 @@
     /// In particular, if the input is zero (or very close to zero), or non-finite,
     /// the result of this operation will be zero.
     ///
-    /// See also [`Self::try_normalize`].
-    #[must_use]
+    /// See also [`Self::try_normalize()`].
     #[inline]
+    #[must_use]
     pub fn normalize_or_zero(self) -> Self {
         let rcp = self.length_recip();
         if rcp.is_finite() && rcp > 0.0 {
@@ -419,9 +489,10 @@
     ///
     /// Uses a precision threshold of `1e-6`.
     #[inline]
+    #[must_use]
     pub fn is_normalized(self) -> bool {
         // TODO: do something with epsilon
-        (self.length_squared() - 1.0).abs() <= 1e-4
+        math::abs(self.length_squared() - 1.0) <= 1e-4
     }
 
     /// Returns the vector projection of `self` onto `rhs`.
@@ -431,8 +502,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` is zero length when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn project_onto(self, rhs: Self) -> Self {
         let other_len_sq_rcp = rhs.dot(rhs).recip();
         glam_assert!(other_len_sq_rcp.is_finite());
@@ -449,8 +520,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` has a length of zero when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn reject_from(self, rhs: Self) -> Self {
         self - self.project_onto(rhs)
     }
@@ -462,8 +533,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` is not normalized when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn project_onto_normalized(self, rhs: Self) -> Self {
         glam_assert!(rhs.is_normalized());
         rhs * self.dot(rhs)
@@ -479,8 +550,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` is not normalized when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn reject_from_normalized(self, rhs: Self) -> Self {
         self - self.project_onto_normalized(rhs)
     }
@@ -488,6 +559,7 @@
     /// Returns a vector containing the nearest integer to a number for each element of `self`.
     /// Round half-way cases away from 0.0.
     #[inline]
+    #[must_use]
     pub fn round(self) -> Self {
         Self(f32x4_nearest(self.0))
     }
@@ -495,6 +567,7 @@
     /// Returns a vector containing the largest integer less than or equal to a number for each
     /// element of `self`.
     #[inline]
+    #[must_use]
     pub fn floor(self) -> Self {
         Self(f32x4_floor(self.0))
     }
@@ -502,15 +575,25 @@
     /// Returns a vector containing the smallest integer greater than or equal to a number for
     /// each element of `self`.
     #[inline]
+    #[must_use]
     pub fn ceil(self) -> Self {
         Self(f32x4_ceil(self.0))
     }
 
+    /// Returns a vector containing the integer part each element of `self`. This means numbers are
+    /// always truncated towards zero.
+    #[inline]
+    #[must_use]
+    pub fn trunc(self) -> Self {
+        Self(f32x4_trunc(self.0))
+    }
+
     /// Returns a vector containing the fractional part of the vector, e.g. `self -
     /// self.floor()`.
     ///
     /// Note that this is fast but not precise for large numbers.
     #[inline]
+    #[must_use]
     pub fn fract(self) -> Self {
         self - self.floor()
     }
@@ -518,23 +601,31 @@
     /// Returns a vector containing `e^self` (the exponential function) for each element of
     /// `self`.
     #[inline]
+    #[must_use]
     pub fn exp(self) -> Self {
-        Self::new(self.x.exp(), self.y.exp(), self.z.exp(), self.w.exp())
+        Self::new(
+            math::exp(self.x),
+            math::exp(self.y),
+            math::exp(self.z),
+            math::exp(self.w),
+        )
     }
 
     /// Returns a vector containing each element of `self` raised to the power of `n`.
     #[inline]
+    #[must_use]
     pub fn powf(self, n: f32) -> Self {
         Self::new(
-            self.x.powf(n),
-            self.y.powf(n),
-            self.z.powf(n),
-            self.w.powf(n),
+            math::powf(self.x, n),
+            math::powf(self.y, n),
+            math::powf(self.z, n),
+            math::powf(self.w, n),
         )
     }
 
     /// Returns a vector containing the reciprocal `1.0/n` of each element of `self`.
     #[inline]
+    #[must_use]
     pub fn recip(self) -> Self {
         Self(f32x4_div(Self::ONE.0, self.0))
     }
@@ -546,6 +637,7 @@
     /// extrapolated.
     #[doc(alias = "mix")]
     #[inline]
+    #[must_use]
     pub fn lerp(self, rhs: Self, s: f32) -> Self {
         self + ((rhs - self) * s)
     }
@@ -560,6 +652,7 @@
     /// For more see
     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
     #[inline]
+    #[must_use]
     pub fn abs_diff_eq(self, rhs: Self, max_abs_diff: f32) -> bool {
         self.sub(rhs).abs().cmple(Self::splat(max_abs_diff)).all()
     }
@@ -570,33 +663,38 @@
     ///
     /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn clamp_length(self, min: f32, max: f32) -> Self {
         glam_assert!(min <= max);
         let length_sq = self.length_squared();
         if length_sq < min * min {
-            self * (length_sq.sqrt().recip() * min)
+            min * (self / math::sqrt(length_sq))
         } else if length_sq > max * max {
-            self * (length_sq.sqrt().recip() * max)
+            max * (self / math::sqrt(length_sq))
         } else {
             self
         }
     }
 
     /// Returns a vector with a length no more than `max`
+    #[inline]
+    #[must_use]
     pub fn clamp_length_max(self, max: f32) -> Self {
         let length_sq = self.length_squared();
         if length_sq > max * max {
-            self * (length_sq.sqrt().recip() * max)
+            max * (self / math::sqrt(length_sq))
         } else {
             self
         }
     }
 
     /// Returns a vector with a length no less than `min`
+    #[inline]
+    #[must_use]
     pub fn clamp_length_min(self, min: f32) -> Self {
         let length_sq = self.length_squared();
         if length_sq < min * min {
-            self * (length_sq.sqrt().recip() * min)
+            min * (self / math::sqrt(length_sq))
         } else {
             self
         }
@@ -610,32 +708,64 @@
     /// and will be heavily dependant on designing algorithms with specific target hardware in
     /// mind.
     #[inline]
+    #[must_use]
     pub fn mul_add(self, a: Self, b: Self) -> Self {
         Self::new(
-            self.x.mul_add(a.x, b.x),
-            self.y.mul_add(a.y, b.y),
-            self.z.mul_add(a.z, b.z),
-            self.w.mul_add(a.w, b.w),
+            math::mul_add(self.x, a.x, b.x),
+            math::mul_add(self.y, a.y, b.y),
+            math::mul_add(self.z, a.z, b.z),
+            math::mul_add(self.w, a.w, b.w),
         )
     }
 
     /// Casts all elements of `self` to `f64`.
     #[inline]
+    #[must_use]
     pub fn as_dvec4(&self) -> crate::DVec4 {
         crate::DVec4::new(self.x as f64, self.y as f64, self.z as f64, self.w as f64)
     }
 
+    /// Casts all elements of `self` to `i16`.
+    #[inline]
+    #[must_use]
+    pub fn as_i16vec4(&self) -> crate::I16Vec4 {
+        crate::I16Vec4::new(self.x as i16, self.y as i16, self.z as i16, self.w as i16)
+    }
+
+    /// Casts all elements of `self` to `u16`.
+    #[inline]
+    #[must_use]
+    pub fn as_u16vec4(&self) -> crate::U16Vec4 {
+        crate::U16Vec4::new(self.x as u16, self.y as u16, self.z as u16, self.w as u16)
+    }
+
     /// Casts all elements of `self` to `i32`.
     #[inline]
+    #[must_use]
     pub fn as_ivec4(&self) -> crate::IVec4 {
         crate::IVec4::new(self.x as i32, self.y as i32, self.z as i32, self.w as i32)
     }
 
     /// Casts all elements of `self` to `u32`.
     #[inline]
+    #[must_use]
     pub fn as_uvec4(&self) -> crate::UVec4 {
         crate::UVec4::new(self.x as u32, self.y as u32, self.z as u32, self.w as u32)
     }
+
+    /// Casts all elements of `self` to `i64`.
+    #[inline]
+    #[must_use]
+    pub fn as_i64vec4(&self) -> crate::I64Vec4 {
+        crate::I64Vec4::new(self.x as i64, self.y as i64, self.z as i64, self.w as i64)
+    }
+
+    /// Casts all elements of `self` to `u64`.
+    #[inline]
+    #[must_use]
+    pub fn as_u64vec4(&self) -> crate::U64Vec4 {
+        crate::U64Vec4::new(self.x as u64, self.y as u64, self.z as u64, self.w as u64)
+    }
 }
 
 impl Default for Vec4 {
diff --git a/src/f64.rs b/src/f64.rs
index 307cd1a..3839d3e 100644
--- a/src/f64.rs
+++ b/src/f64.rs
@@ -7,6 +7,8 @@
 mod dvec2;
 mod dvec3;
 mod dvec4;
+mod float;
+pub(crate) mod math;
 
 pub use daffine2::DAffine2;
 pub use daffine3::DAffine3;
diff --git a/src/f64/daffine2.rs b/src/f64/daffine2.rs
index 4e1d76a..cf9fe5f 100644
--- a/src/f64/daffine2.rs
+++ b/src/f64/daffine2.rs
@@ -1,7 +1,7 @@
 // Generated from affine.rs.tera template. Edit the template, not the generated file.
 
 use crate::{DMat2, DMat3, DVec2};
-use core::ops::{Deref, DerefMut, Mul};
+use core::ops::{Deref, DerefMut, Mul, MulAssign};
 
 /// A 2D affine transform, which can represent translation, rotation, scaling and shear.
 #[derive(Copy, Clone)]
@@ -37,6 +37,7 @@
 
     /// Creates an affine transform from three column vectors.
     #[inline(always)]
+    #[must_use]
     pub const fn from_cols(x_axis: DVec2, y_axis: DVec2, z_axis: DVec2) -> Self {
         Self {
             matrix2: DMat2::from_cols(x_axis, y_axis),
@@ -46,6 +47,7 @@
 
     /// Creates an affine transform from a `[f64; 6]` array stored in column major order.
     #[inline]
+    #[must_use]
     pub fn from_cols_array(m: &[f64; 6]) -> Self {
         Self {
             matrix2: DMat2::from_cols_slice(&m[0..4]),
@@ -55,6 +57,7 @@
 
     /// Creates a `[f64; 6]` array storing data in column major order.
     #[inline]
+    #[must_use]
     pub fn to_cols_array(&self) -> [f64; 6] {
         let x = &self.matrix2.x_axis;
         let y = &self.matrix2.y_axis;
@@ -67,6 +70,7 @@
     /// If your data is in row major order you will need to `transpose` the returned
     /// matrix.
     #[inline]
+    #[must_use]
     pub fn from_cols_array_2d(m: &[[f64; 2]; 3]) -> Self {
         Self {
             matrix2: DMat2::from_cols(m[0].into(), m[1].into()),
@@ -78,6 +82,7 @@
     /// column major order.
     /// If you require data in row major order `transpose` the matrix first.
     #[inline]
+    #[must_use]
     pub fn to_cols_array_2d(&self) -> [[f64; 2]; 3] {
         [
             self.matrix2.x_axis.into(),
@@ -92,6 +97,7 @@
     ///
     /// Panics if `slice` is less than 6 elements long.
     #[inline]
+    #[must_use]
     pub fn from_cols_slice(slice: &[f64]) -> Self {
         Self {
             matrix2: DMat2::from_cols_slice(&slice[0..4]),
@@ -113,6 +119,7 @@
     /// Creates an affine transform that changes scale.
     /// Note that if any scale is zero the transform will be non-invertible.
     #[inline]
+    #[must_use]
     pub fn from_scale(scale: DVec2) -> Self {
         Self {
             matrix2: DMat2::from_diagonal(scale),
@@ -122,6 +129,7 @@
 
     /// Creates an affine transform from the given rotation `angle`.
     #[inline]
+    #[must_use]
     pub fn from_angle(angle: f64) -> Self {
         Self {
             matrix2: DMat2::from_angle(angle),
@@ -131,6 +139,7 @@
 
     /// Creates an affine transformation from the given 2D `translation`.
     #[inline]
+    #[must_use]
     pub fn from_translation(translation: DVec2) -> Self {
         Self {
             matrix2: DMat2::IDENTITY,
@@ -140,6 +149,7 @@
 
     /// Creates an affine transform from a 2x2 matrix (expressing scale, shear and rotation)
     #[inline]
+    #[must_use]
     pub fn from_mat2(matrix2: DMat2) -> Self {
         Self {
             matrix2,
@@ -153,6 +163,7 @@
     /// Equivalent to
     /// `DAffine2::from_translation(translation) * DAffine2::from_mat2(mat2)`
     #[inline]
+    #[must_use]
     pub fn from_mat2_translation(matrix2: DMat2, translation: DVec2) -> Self {
         Self {
             matrix2,
@@ -166,6 +177,7 @@
     /// Equivalent to `DAffine2::from_translation(translation) *
     /// DAffine2::from_angle(angle) * DAffine2::from_scale(scale)`
     #[inline]
+    #[must_use]
     pub fn from_scale_angle_translation(scale: DVec2, angle: f64, translation: DVec2) -> Self {
         let rotation = DMat2::from_angle(angle);
         Self {
@@ -179,6 +191,7 @@
     ///
     /// Equivalent to `DAffine2::from_translation(translation) * DAffine2::from_angle(angle)`
     #[inline]
+    #[must_use]
     pub fn from_angle_translation(angle: f64, translation: DVec2) -> Self {
         Self {
             matrix2: DMat2::from_angle(angle),
@@ -188,6 +201,7 @@
 
     /// The given `DMat3` must be an affine transform,
     #[inline]
+    #[must_use]
     pub fn from_mat3(m: DMat3) -> Self {
         use crate::swizzles::Vec3Swizzles;
         Self {
@@ -196,8 +210,37 @@
         }
     }
 
+    /// Extracts `scale`, `angle` and `translation` from `self`.
+    ///
+    /// The transform is expected to be non-degenerate and without shearing, or the output
+    /// will be invalid.
+    ///
+    /// # Panics
+    ///
+    /// Will panic if the determinant `self.matrix2` is zero or if the resulting scale
+    /// vector contains any zero elements when `glam_assert` is enabled.
+    #[inline]
+    #[must_use]
+    pub fn to_scale_angle_translation(self) -> (DVec2, f64, DVec2) {
+        use crate::f64::math;
+        let det = self.matrix2.determinant();
+        glam_assert!(det != 0.0);
+
+        let scale = DVec2::new(
+            self.matrix2.x_axis.length() * math::signum(det),
+            self.matrix2.y_axis.length(),
+        );
+
+        glam_assert!(scale.cmpne(DVec2::ZERO).all());
+
+        let angle = math::atan2(-self.matrix2.y_axis.x, self.matrix2.y_axis.y);
+
+        (scale, angle, self.translation)
+    }
+
     /// Transforms the given 2D point, applying shear, scale, rotation and translation.
     #[inline]
+    #[must_use]
     pub fn transform_point2(&self, rhs: DVec2) -> DVec2 {
         self.matrix2 * rhs + self.translation
     }
@@ -205,7 +248,7 @@
     /// Transforms the given 2D vector, applying shear, scale and rotation (but NOT
     /// translation).
     ///
-    /// To also apply translation, use [`Self::transform_point2`] instead.
+    /// To also apply translation, use [`Self::transform_point2()`] instead.
     #[inline]
     pub fn transform_vector2(&self, rhs: DVec2) -> DVec2 {
         self.matrix2 * rhs
@@ -216,12 +259,14 @@
     /// If any element is either `NaN`, positive or negative infinity, this will return
     /// `false`.
     #[inline]
+    #[must_use]
     pub fn is_finite(&self) -> bool {
         self.matrix2.is_finite() && self.translation.is_finite()
     }
 
     /// Returns `true` if any elements are `NaN`.
     #[inline]
+    #[must_use]
     pub fn is_nan(&self) -> bool {
         self.matrix2.is_nan() || self.translation.is_nan()
     }
@@ -236,6 +281,7 @@
     /// For more see
     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
     #[inline]
+    #[must_use]
     pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
         self.matrix2.abs_diff_eq(rhs.matrix2, max_abs_diff)
             && self.translation.abs_diff_eq(rhs.translation, max_abs_diff)
@@ -244,8 +290,8 @@
     /// Return the inverse of this transform.
     ///
     /// Note that if the transform is not invertible the result will be invalid.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn inverse(&self) -> Self {
         let matrix2 = self.matrix2.inverse();
         // transform negative translation by the matrix inverse:
@@ -329,6 +375,13 @@
     }
 }
 
+impl MulAssign for DAffine2 {
+    #[inline]
+    fn mul_assign(&mut self, rhs: DAffine2) {
+        *self = self.mul(rhs);
+    }
+}
+
 impl From<DAffine2> for DMat3 {
     #[inline]
     fn from(m: DAffine2) -> DMat3 {
diff --git a/src/f64/daffine3.rs b/src/f64/daffine3.rs
index a5f4535..6a261bf 100644
--- a/src/f64/daffine3.rs
+++ b/src/f64/daffine3.rs
@@ -1,7 +1,7 @@
 // Generated from affine.rs.tera template. Edit the template, not the generated file.
 
 use crate::{DMat3, DMat4, DQuat, DVec3};
-use core::ops::{Deref, DerefMut, Mul};
+use core::ops::{Deref, DerefMut, Mul, MulAssign};
 
 /// A 3D affine transform, which can represent translation, rotation, scaling and shear.
 #[derive(Copy, Clone)]
@@ -37,6 +37,7 @@
 
     /// Creates an affine transform from three column vectors.
     #[inline(always)]
+    #[must_use]
     pub const fn from_cols(x_axis: DVec3, y_axis: DVec3, z_axis: DVec3, w_axis: DVec3) -> Self {
         Self {
             matrix3: DMat3::from_cols(x_axis, y_axis, z_axis),
@@ -46,6 +47,7 @@
 
     /// Creates an affine transform from a `[f64; 12]` array stored in column major order.
     #[inline]
+    #[must_use]
     pub fn from_cols_array(m: &[f64; 12]) -> Self {
         Self {
             matrix3: DMat3::from_cols_slice(&m[0..9]),
@@ -55,6 +57,7 @@
 
     /// Creates a `[f64; 12]` array storing data in column major order.
     #[inline]
+    #[must_use]
     pub fn to_cols_array(&self) -> [f64; 12] {
         let x = &self.matrix3.x_axis;
         let y = &self.matrix3.y_axis;
@@ -68,6 +71,7 @@
     /// If your data is in row major order you will need to `transpose` the returned
     /// matrix.
     #[inline]
+    #[must_use]
     pub fn from_cols_array_2d(m: &[[f64; 3]; 4]) -> Self {
         Self {
             matrix3: DMat3::from_cols(m[0].into(), m[1].into(), m[2].into()),
@@ -79,6 +83,7 @@
     /// column major order.
     /// If you require data in row major order `transpose` the matrix first.
     #[inline]
+    #[must_use]
     pub fn to_cols_array_2d(&self) -> [[f64; 3]; 4] {
         [
             self.matrix3.x_axis.into(),
@@ -94,6 +99,7 @@
     ///
     /// Panics if `slice` is less than 12 elements long.
     #[inline]
+    #[must_use]
     pub fn from_cols_slice(slice: &[f64]) -> Self {
         Self {
             matrix3: DMat3::from_cols_slice(&slice[0..9]),
@@ -115,6 +121,7 @@
     /// Creates an affine transform that changes scale.
     /// Note that if any scale is zero the transform will be non-invertible.
     #[inline]
+    #[must_use]
     pub fn from_scale(scale: DVec3) -> Self {
         Self {
             matrix3: DMat3::from_diagonal(scale),
@@ -123,6 +130,7 @@
     }
     /// Creates an affine transform from the given `rotation` quaternion.
     #[inline]
+    #[must_use]
     pub fn from_quat(rotation: DQuat) -> Self {
         Self {
             matrix3: DMat3::from_quat(rotation),
@@ -133,6 +141,7 @@
     /// Creates an affine transform containing a 3D rotation around a normalized
     /// rotation `axis` of `angle` (in radians).
     #[inline]
+    #[must_use]
     pub fn from_axis_angle(axis: DVec3, angle: f64) -> Self {
         Self {
             matrix3: DMat3::from_axis_angle(axis, angle),
@@ -143,6 +152,7 @@
     /// Creates an affine transform containing a 3D rotation around the x axis of
     /// `angle` (in radians).
     #[inline]
+    #[must_use]
     pub fn from_rotation_x(angle: f64) -> Self {
         Self {
             matrix3: DMat3::from_rotation_x(angle),
@@ -153,6 +163,7 @@
     /// Creates an affine transform containing a 3D rotation around the y axis of
     /// `angle` (in radians).
     #[inline]
+    #[must_use]
     pub fn from_rotation_y(angle: f64) -> Self {
         Self {
             matrix3: DMat3::from_rotation_y(angle),
@@ -163,6 +174,7 @@
     /// Creates an affine transform containing a 3D rotation around the z axis of
     /// `angle` (in radians).
     #[inline]
+    #[must_use]
     pub fn from_rotation_z(angle: f64) -> Self {
         Self {
             matrix3: DMat3::from_rotation_z(angle),
@@ -172,6 +184,7 @@
 
     /// Creates an affine transformation from the given 3D `translation`.
     #[inline]
+    #[must_use]
     pub fn from_translation(translation: DVec3) -> Self {
         #[allow(clippy::useless_conversion)]
         Self {
@@ -183,6 +196,7 @@
     /// Creates an affine transform from a 3x3 matrix (expressing scale, shear and
     /// rotation)
     #[inline]
+    #[must_use]
     pub fn from_mat3(mat3: DMat3) -> Self {
         #[allow(clippy::useless_conversion)]
         Self {
@@ -196,6 +210,7 @@
     ///
     /// Equivalent to `DAffine3::from_translation(translation) * DAffine3::from_mat3(mat3)`
     #[inline]
+    #[must_use]
     pub fn from_mat3_translation(mat3: DMat3, translation: DVec3) -> Self {
         #[allow(clippy::useless_conversion)]
         Self {
@@ -210,6 +225,7 @@
     /// Equivalent to `DAffine3::from_translation(translation) *
     /// DAffine3::from_quat(rotation) * DAffine3::from_scale(scale)`
     #[inline]
+    #[must_use]
     pub fn from_scale_rotation_translation(
         scale: DVec3,
         rotation: DQuat,
@@ -231,6 +247,7 @@
     ///
     /// Equivalent to `DAffine3::from_translation(translation) * DAffine3::from_quat(rotation)`
     #[inline]
+    #[must_use]
     pub fn from_rotation_translation(rotation: DQuat, translation: DVec3) -> Self {
         #[allow(clippy::useless_conversion)]
         Self {
@@ -242,6 +259,7 @@
     /// The given `DMat4` must be an affine transform,
     /// i.e. contain no perspective transform.
     #[inline]
+    #[must_use]
     pub fn from_mat4(m: DMat4) -> Self {
         Self {
             matrix3: DMat3::from_cols(
@@ -263,16 +281,14 @@
     /// Will panic if the determinant `self.matrix3` is zero or if the resulting scale
     /// vector contains any zero elements when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn to_scale_rotation_translation(&self) -> (DVec3, DQuat, DVec3) {
-        #[cfg(feature = "libm")]
-        #[allow(unused_imports)]
-        use num_traits::Float;
-
+        use crate::f64::math;
         let det = self.matrix3.determinant();
         glam_assert!(det != 0.0);
 
         let scale = DVec3::new(
-            self.matrix3.x_axis.length() * det.signum(),
+            self.matrix3.x_axis.length() * math::signum(det),
             self.matrix3.y_axis.length(),
             self.matrix3.z_axis.length(),
         );
@@ -297,6 +313,7 @@
     ///
     /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
     #[inline]
+    #[must_use]
     pub fn look_to_lh(eye: DVec3, dir: DVec3, up: DVec3) -> Self {
         Self::look_to_rh(eye, -dir, up)
     }
@@ -306,6 +323,7 @@
     ///
     /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
     #[inline]
+    #[must_use]
     pub fn look_to_rh(eye: DVec3, dir: DVec3, up: DVec3) -> Self {
         let f = dir.normalize();
         let s = f.cross(up).normalize();
@@ -329,6 +347,7 @@
     ///
     /// Will panic if `up` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn look_at_lh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
         glam_assert!(up.is_normalized());
         Self::look_to_lh(eye, center - eye, up)
@@ -342,6 +361,7 @@
     ///
     /// Will panic if `up` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn look_at_rh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
         glam_assert!(up.is_normalized());
         Self::look_to_rh(eye, center - eye, up)
@@ -361,8 +381,9 @@
     /// Transforms the given 3D vector, applying shear, scale and rotation (but NOT
     /// translation).
     ///
-    /// To also apply translation, use [`Self::transform_point3`] instead.
+    /// To also apply translation, use [`Self::transform_point3()`] instead.
     #[inline]
+    #[must_use]
     pub fn transform_vector3(&self, rhs: DVec3) -> DVec3 {
         #[allow(clippy::useless_conversion)]
         ((self.matrix3.x_axis * rhs.x)
@@ -376,12 +397,14 @@
     /// If any element is either `NaN`, positive or negative infinity, this will return
     /// `false`.
     #[inline]
+    #[must_use]
     pub fn is_finite(&self) -> bool {
         self.matrix3.is_finite() && self.translation.is_finite()
     }
 
     /// Returns `true` if any elements are `NaN`.
     #[inline]
+    #[must_use]
     pub fn is_nan(&self) -> bool {
         self.matrix3.is_nan() || self.translation.is_nan()
     }
@@ -396,6 +419,7 @@
     /// For more see
     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
     #[inline]
+    #[must_use]
     pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
         self.matrix3.abs_diff_eq(rhs.matrix3, max_abs_diff)
             && self.translation.abs_diff_eq(rhs.translation, max_abs_diff)
@@ -404,8 +428,8 @@
     /// Return the inverse of this transform.
     ///
     /// Note that if the transform is not invertible the result will be invalid.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn inverse(&self) -> Self {
         let matrix3 = self.matrix3.inverse();
         // transform negative translation by the matrix inverse:
@@ -489,6 +513,13 @@
     }
 }
 
+impl MulAssign for DAffine3 {
+    #[inline]
+    fn mul_assign(&mut self, rhs: DAffine3) {
+        *self = self.mul(rhs);
+    }
+}
+
 impl From<DAffine3> for DMat4 {
     #[inline]
     fn from(m: DAffine3) -> DMat4 {
diff --git a/src/f64/dmat2.rs b/src/f64/dmat2.rs
index bd52c8c..dbc61c5 100644
--- a/src/f64/dmat2.rs
+++ b/src/f64/dmat2.rs
@@ -1,17 +1,14 @@
 // Generated from mat.rs.tera template. Edit the template, not the generated file.
 
-use crate::{swizzles::*, DMat3, DVec2, Mat2};
+use crate::{f64::math, swizzles::*, DMat3, DVec2, Mat2};
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
 use core::iter::{Product, Sum};
 use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
 
-#[cfg(feature = "libm")]
-#[allow(unused_imports)]
-use num_traits::Float;
-
-/// Creates a 2x2 matrix from column vectors.
+/// Creates a 2x2 matrix from two column vectors.
 #[inline(always)]
+#[must_use]
 pub const fn dmat2(x_axis: DVec2, y_axis: DVec2) -> DMat2 {
     DMat2::from_cols(x_axis, y_axis)
 }
@@ -37,6 +34,7 @@
 
     #[allow(clippy::too_many_arguments)]
     #[inline(always)]
+    #[must_use]
     const fn new(m00: f64, m01: f64, m10: f64, m11: f64) -> Self {
         Self {
             x_axis: DVec2::new(m00, m01),
@@ -46,6 +44,7 @@
 
     /// Creates a 2x2 matrix from two column vectors.
     #[inline(always)]
+    #[must_use]
     pub const fn from_cols(x_axis: DVec2, y_axis: DVec2) -> Self {
         Self { x_axis, y_axis }
     }
@@ -54,6 +53,7 @@
     /// If your data is stored in row major you will need to `transpose` the returned
     /// matrix.
     #[inline]
+    #[must_use]
     pub const fn from_cols_array(m: &[f64; 4]) -> Self {
         Self::new(m[0], m[1], m[2], m[3])
     }
@@ -61,6 +61,7 @@
     /// Creates a `[f64; 4]` array storing data in column major order.
     /// If you require data in row major order `transpose` the matrix first.
     #[inline]
+    #[must_use]
     pub const fn to_cols_array(&self) -> [f64; 4] {
         [self.x_axis.x, self.x_axis.y, self.y_axis.x, self.y_axis.y]
     }
@@ -69,6 +70,7 @@
     /// If your data is in row major order you will need to `transpose` the returned
     /// matrix.
     #[inline]
+    #[must_use]
     pub const fn from_cols_array_2d(m: &[[f64; 2]; 2]) -> Self {
         Self::from_cols(DVec2::from_array(m[0]), DVec2::from_array(m[1]))
     }
@@ -76,6 +78,7 @@
     /// Creates a `[[f64; 2]; 2]` 2D array storing data in column major order.
     /// If you require data in row major order `transpose` the matrix first.
     #[inline]
+    #[must_use]
     pub const fn to_cols_array_2d(&self) -> [[f64; 2]; 2] {
         [self.x_axis.to_array(), self.y_axis.to_array()]
     }
@@ -83,6 +86,7 @@
     /// Creates a 2x2 matrix with its diagonal set to `diagonal` and all other entries set to 0.
     #[doc(alias = "scale")]
     #[inline]
+    #[must_use]
     pub const fn from_diagonal(diagonal: DVec2) -> Self {
         Self::new(diagonal.x, 0.0, 0.0, diagonal.y)
     }
@@ -90,20 +94,23 @@
     /// Creates a 2x2 matrix containing the combining non-uniform `scale` and rotation of
     /// `angle` (in radians).
     #[inline]
+    #[must_use]
     pub fn from_scale_angle(scale: DVec2, angle: f64) -> Self {
-        let (sin, cos) = angle.sin_cos();
+        let (sin, cos) = math::sin_cos(angle);
         Self::new(cos * scale.x, sin * scale.x, -sin * scale.y, cos * scale.y)
     }
 
     /// Creates a 2x2 matrix containing a rotation of `angle` (in radians).
     #[inline]
+    #[must_use]
     pub fn from_angle(angle: f64) -> Self {
-        let (sin, cos) = angle.sin_cos();
+        let (sin, cos) = math::sin_cos(angle);
         Self::new(cos, sin, -sin, cos)
     }
 
     /// Creates a 2x2 matrix from a 3x3 matrix, discarding the 2nd row and column.
     #[inline]
+    #[must_use]
     pub fn from_mat3(m: DMat3) -> Self {
         Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
     }
@@ -114,6 +121,7 @@
     ///
     /// Panics if `slice` is less than 4 elements long.
     #[inline]
+    #[must_use]
     pub const fn from_cols_slice(slice: &[f64]) -> Self {
         Self::new(slice[0], slice[1], slice[2], slice[3])
     }
@@ -137,6 +145,7 @@
     ///
     /// Panics if `index` is greater than 1.
     #[inline]
+    #[must_use]
     pub fn col(&self, index: usize) -> DVec2 {
         match index {
             0 => self.x_axis,
@@ -165,6 +174,7 @@
     ///
     /// Panics if `index` is greater than 1.
     #[inline]
+    #[must_use]
     pub fn row(&self, index: usize) -> DVec2 {
         match index {
             0 => DVec2::new(self.x_axis.x, self.y_axis.x),
@@ -176,19 +186,21 @@
     /// Returns `true` if, and only if, all elements are finite.
     /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
     #[inline]
+    #[must_use]
     pub fn is_finite(&self) -> bool {
         self.x_axis.is_finite() && self.y_axis.is_finite()
     }
 
     /// Returns `true` if any elements are `NaN`.
     #[inline]
+    #[must_use]
     pub fn is_nan(&self) -> bool {
         self.x_axis.is_nan() || self.y_axis.is_nan()
     }
 
     /// Returns the transpose of `self`.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn transpose(&self) -> Self {
         Self {
             x_axis: DVec2::new(self.x_axis.x, self.y_axis.x),
@@ -198,6 +210,7 @@
 
     /// Returns the determinant of `self`.
     #[inline]
+    #[must_use]
     pub fn determinant(&self) -> f64 {
         self.x_axis.x * self.y_axis.y - self.x_axis.y * self.y_axis.x
     }
@@ -209,8 +222,8 @@
     /// # Panics
     ///
     /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn inverse(&self) -> Self {
         let inv_det = {
             let det = self.determinant();
@@ -227,6 +240,7 @@
 
     /// Transforms a 2D vector.
     #[inline]
+    #[must_use]
     pub fn mul_vec2(&self, rhs: DVec2) -> DVec2 {
         #[allow(clippy::suspicious_operation_groupings)]
         DVec2::new(
@@ -237,24 +251,28 @@
 
     /// Multiplies two 2x2 matrices.
     #[inline]
+    #[must_use]
     pub fn mul_mat2(&self, rhs: &Self) -> Self {
         Self::from_cols(self.mul(rhs.x_axis), self.mul(rhs.y_axis))
     }
 
     /// Adds two 2x2 matrices.
     #[inline]
+    #[must_use]
     pub fn add_mat2(&self, rhs: &Self) -> Self {
         Self::from_cols(self.x_axis.add(rhs.x_axis), self.y_axis.add(rhs.y_axis))
     }
 
     /// Subtracts two 2x2 matrices.
     #[inline]
+    #[must_use]
     pub fn sub_mat2(&self, rhs: &Self) -> Self {
         Self::from_cols(self.x_axis.sub(rhs.x_axis), self.y_axis.sub(rhs.y_axis))
     }
 
     /// Multiplies a 2x2 matrix by a scalar.
     #[inline]
+    #[must_use]
     pub fn mul_scalar(&self, rhs: f64) -> Self {
         Self::from_cols(self.x_axis.mul(rhs), self.y_axis.mul(rhs))
     }
@@ -269,6 +287,7 @@
     /// For more see
     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
     #[inline]
+    #[must_use]
     pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
         self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
             && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
diff --git a/src/f64/dmat3.rs b/src/f64/dmat3.rs
index 600223c..c271886 100644
--- a/src/f64/dmat3.rs
+++ b/src/f64/dmat3.rs
@@ -1,17 +1,14 @@
 // Generated from mat.rs.tera template. Edit the template, not the generated file.
 
-use crate::{swizzles::*, DMat2, DMat4, DQuat, DVec2, DVec3, EulerRot, Mat3};
+use crate::{f64::math, swizzles::*, DMat2, DMat4, DQuat, DVec2, DVec3, EulerRot, Mat3};
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
 use core::iter::{Product, Sum};
 use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
 
-#[cfg(feature = "libm")]
-#[allow(unused_imports)]
-use num_traits::Float;
-
-/// Creates a 3x3 matrix from column vectors.
+/// Creates a 3x3 matrix from three column vectors.
 #[inline(always)]
+#[must_use]
 pub const fn dmat3(x_axis: DVec3, y_axis: DVec3, z_axis: DVec3) -> DMat3 {
     DMat3::from_cols(x_axis, y_axis, z_axis)
 }
@@ -60,6 +57,7 @@
 
     #[allow(clippy::too_many_arguments)]
     #[inline(always)]
+    #[must_use]
     const fn new(
         m00: f64,
         m01: f64,
@@ -78,8 +76,9 @@
         }
     }
 
-    /// Creates a 3x3 matrix from two column vectors.
+    /// Creates a 3x3 matrix from three column vectors.
     #[inline(always)]
+    #[must_use]
     pub const fn from_cols(x_axis: DVec3, y_axis: DVec3, z_axis: DVec3) -> Self {
         Self {
             x_axis,
@@ -92,6 +91,7 @@
     /// If your data is stored in row major you will need to `transpose` the returned
     /// matrix.
     #[inline]
+    #[must_use]
     pub const fn from_cols_array(m: &[f64; 9]) -> Self {
         Self::new(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8])
     }
@@ -99,6 +99,7 @@
     /// Creates a `[f64; 9]` array storing data in column major order.
     /// If you require data in row major order `transpose` the matrix first.
     #[inline]
+    #[must_use]
     pub const fn to_cols_array(&self) -> [f64; 9] {
         [
             self.x_axis.x,
@@ -117,6 +118,7 @@
     /// If your data is in row major order you will need to `transpose` the returned
     /// matrix.
     #[inline]
+    #[must_use]
     pub const fn from_cols_array_2d(m: &[[f64; 3]; 3]) -> Self {
         Self::from_cols(
             DVec3::from_array(m[0]),
@@ -128,6 +130,7 @@
     /// Creates a `[[f64; 3]; 3]` 3D array storing data in column major order.
     /// If you require data in row major order `transpose` the matrix first.
     #[inline]
+    #[must_use]
     pub const fn to_cols_array_2d(&self) -> [[f64; 3]; 3] {
         [
             self.x_axis.to_array(),
@@ -139,6 +142,7 @@
     /// Creates a 3x3 matrix with its diagonal set to `diagonal` and all other entries set to 0.
     #[doc(alias = "scale")]
     #[inline]
+    #[must_use]
     pub const fn from_diagonal(diagonal: DVec3) -> Self {
         Self::new(
             diagonal.x, 0.0, 0.0, 0.0, diagonal.y, 0.0, 0.0, 0.0, diagonal.z,
@@ -146,6 +150,8 @@
     }
 
     /// Creates a 3x3 matrix from a 4x4 matrix, discarding the 4th row and column.
+    #[inline]
+    #[must_use]
     pub fn from_mat4(m: DMat4) -> Self {
         Self::from_cols(m.x_axis.xyz(), m.y_axis.xyz(), m.z_axis.xyz())
     }
@@ -156,6 +162,7 @@
     ///
     /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_quat(rotation: DQuat) -> Self {
         glam_assert!(rotation.is_normalized());
 
@@ -186,10 +193,11 @@
     ///
     /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_axis_angle(axis: DVec3, angle: f64) -> Self {
         glam_assert!(axis.is_normalized());
 
-        let (sin, cos) = angle.sin_cos();
+        let (sin, cos) = math::sin_cos(angle);
         let (xsin, ysin, zsin) = axis.mul(sin).into();
         let (x, y, z) = axis.into();
         let (x2, y2, z2) = axis.mul(axis).into();
@@ -204,9 +212,10 @@
         )
     }
 
-    #[inline]
     /// Creates a 3D rotation matrix from the given euler rotation sequence and the angles (in
     /// radians).
+    #[inline]
+    #[must_use]
     pub fn from_euler(order: EulerRot, a: f64, b: f64, c: f64) -> Self {
         let quat = DQuat::from_euler(order, a, b, c);
         Self::from_quat(quat)
@@ -214,8 +223,9 @@
 
     /// Creates a 3D rotation matrix from `angle` (in radians) around the x axis.
     #[inline]
+    #[must_use]
     pub fn from_rotation_x(angle: f64) -> Self {
-        let (sina, cosa) = angle.sin_cos();
+        let (sina, cosa) = math::sin_cos(angle);
         Self::from_cols(
             DVec3::X,
             DVec3::new(0.0, cosa, sina),
@@ -225,8 +235,9 @@
 
     /// Creates a 3D rotation matrix from `angle` (in radians) around the y axis.
     #[inline]
+    #[must_use]
     pub fn from_rotation_y(angle: f64) -> Self {
-        let (sina, cosa) = angle.sin_cos();
+        let (sina, cosa) = math::sin_cos(angle);
         Self::from_cols(
             DVec3::new(cosa, 0.0, -sina),
             DVec3::Y,
@@ -236,8 +247,9 @@
 
     /// Creates a 3D rotation matrix from `angle` (in radians) around the z axis.
     #[inline]
+    #[must_use]
     pub fn from_rotation_z(angle: f64) -> Self {
-        let (sina, cosa) = angle.sin_cos();
+        let (sina, cosa) = math::sin_cos(angle);
         Self::from_cols(
             DVec3::new(cosa, sina, 0.0),
             DVec3::new(-sina, cosa, 0.0),
@@ -250,6 +262,7 @@
     /// The resulting matrix can be used to transform 2D points and vectors. See
     /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
     #[inline]
+    #[must_use]
     pub fn from_translation(translation: DVec2) -> Self {
         Self::from_cols(
             DVec3::X,
@@ -264,8 +277,9 @@
     /// The resulting matrix can be used to transform 2D points and vectors. See
     /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
     #[inline]
+    #[must_use]
     pub fn from_angle(angle: f64) -> Self {
-        let (sin, cos) = angle.sin_cos();
+        let (sin, cos) = math::sin_cos(angle);
         Self::from_cols(
             DVec3::new(cos, sin, 0.0),
             DVec3::new(-sin, cos, 0.0),
@@ -279,8 +293,9 @@
     /// The resulting matrix can be used to transform 2D points and vectors. See
     /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
     #[inline]
+    #[must_use]
     pub fn from_scale_angle_translation(scale: DVec2, angle: f64, translation: DVec2) -> Self {
-        let (sin, cos) = angle.sin_cos();
+        let (sin, cos) = math::sin_cos(angle);
         Self::from_cols(
             DVec3::new(cos * scale.x, sin * scale.x, 0.0),
             DVec3::new(-sin * scale.y, cos * scale.y, 0.0),
@@ -297,6 +312,7 @@
     ///
     /// Will panic if all elements of `scale` are zero when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_scale(scale: DVec2) -> Self {
         // Do not panic as long as any component is non-zero
         glam_assert!(scale.cmpne(DVec2::ZERO).any());
@@ -323,6 +339,7 @@
     ///
     /// Panics if `slice` is less than 9 elements long.
     #[inline]
+    #[must_use]
     pub const fn from_cols_slice(slice: &[f64]) -> Self {
         Self::new(
             slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
@@ -354,6 +371,7 @@
     ///
     /// Panics if `index` is greater than 2.
     #[inline]
+    #[must_use]
     pub fn col(&self, index: usize) -> DVec3 {
         match index {
             0 => self.x_axis,
@@ -384,6 +402,7 @@
     ///
     /// Panics if `index` is greater than 2.
     #[inline]
+    #[must_use]
     pub fn row(&self, index: usize) -> DVec3 {
         match index {
             0 => DVec3::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
@@ -396,19 +415,21 @@
     /// Returns `true` if, and only if, all elements are finite.
     /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
     #[inline]
+    #[must_use]
     pub fn is_finite(&self) -> bool {
         self.x_axis.is_finite() && self.y_axis.is_finite() && self.z_axis.is_finite()
     }
 
     /// Returns `true` if any elements are `NaN`.
     #[inline]
+    #[must_use]
     pub fn is_nan(&self) -> bool {
         self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan()
     }
 
     /// Returns the transpose of `self`.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn transpose(&self) -> Self {
         Self {
             x_axis: DVec3::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
@@ -419,6 +440,7 @@
 
     /// Returns the determinant of `self`.
     #[inline]
+    #[must_use]
     pub fn determinant(&self) -> f64 {
         self.z_axis.dot(self.x_axis.cross(self.y_axis))
     }
@@ -430,8 +452,8 @@
     /// # Panics
     ///
     /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn inverse(&self) -> Self {
         let tmp0 = self.y_axis.cross(self.z_axis);
         let tmp1 = self.z_axis.cross(self.x_axis);
@@ -452,6 +474,7 @@
     ///
     /// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn transform_point2(&self, rhs: DVec2) -> DVec2 {
         glam_assert!(self.row(2).abs_diff_eq(DVec3::Z, 1e-6));
         DMat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs + self.z_axis.xy()
@@ -467,6 +490,7 @@
     ///
     /// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn transform_vector2(&self, rhs: DVec2) -> DVec2 {
         glam_assert!(self.row(2).abs_diff_eq(DVec3::Z, 1e-6));
         DMat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs
@@ -474,6 +498,7 @@
 
     /// Transforms a 3D vector.
     #[inline]
+    #[must_use]
     pub fn mul_vec3(&self, rhs: DVec3) -> DVec3 {
         let mut res = self.x_axis.mul(rhs.x);
         res = res.add(self.y_axis.mul(rhs.y));
@@ -483,6 +508,7 @@
 
     /// Multiplies two 3x3 matrices.
     #[inline]
+    #[must_use]
     pub fn mul_mat3(&self, rhs: &Self) -> Self {
         Self::from_cols(
             self.mul(rhs.x_axis),
@@ -493,6 +519,7 @@
 
     /// Adds two 3x3 matrices.
     #[inline]
+    #[must_use]
     pub fn add_mat3(&self, rhs: &Self) -> Self {
         Self::from_cols(
             self.x_axis.add(rhs.x_axis),
@@ -503,6 +530,7 @@
 
     /// Subtracts two 3x3 matrices.
     #[inline]
+    #[must_use]
     pub fn sub_mat3(&self, rhs: &Self) -> Self {
         Self::from_cols(
             self.x_axis.sub(rhs.x_axis),
@@ -513,6 +541,7 @@
 
     /// Multiplies a 3x3 matrix by a scalar.
     #[inline]
+    #[must_use]
     pub fn mul_scalar(&self, rhs: f64) -> Self {
         Self::from_cols(
             self.x_axis.mul(rhs),
@@ -531,6 +560,7 @@
     /// For more see
     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
     #[inline]
+    #[must_use]
     pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
         self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
             && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
diff --git a/src/f64/dmat4.rs b/src/f64/dmat4.rs
index cc4283c..cc9147c 100644
--- a/src/f64/dmat4.rs
+++ b/src/f64/dmat4.rs
@@ -1,17 +1,14 @@
 // Generated from mat.rs.tera template. Edit the template, not the generated file.
 
-use crate::{swizzles::*, DMat3, DQuat, DVec3, DVec4, EulerRot, Mat4};
+use crate::{f64::math, swizzles::*, DMat3, DQuat, DVec3, DVec4, EulerRot, Mat4};
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
 use core::iter::{Product, Sum};
 use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
 
-#[cfg(feature = "libm")]
-#[allow(unused_imports)]
-use num_traits::Float;
-
-/// Creates a 4x4 matrix from column vectors.
+/// Creates a 4x4 matrix from four column vectors.
 #[inline(always)]
+#[must_use]
 pub const fn dmat4(x_axis: DVec4, y_axis: DVec4, z_axis: DVec4, w_axis: DVec4) -> DMat4 {
     DMat4::from_cols(x_axis, y_axis, z_axis, w_axis)
 }
@@ -27,7 +24,7 @@
 /// using methods such as [`Self::from_translation()`], [`Self::from_quat()`],
 /// [`Self::from_scale()`] and [`Self::from_scale_rotation_translation()`].
 ///
-/// Othographic projections can be created using the methods [`Self::orthographic_lh()`] for
+/// Orthographic projections can be created using the methods [`Self::orthographic_lh()`] for
 /// left-handed coordinate systems and [`Self::orthographic_rh()`] for right-handed
 /// systems. The resulting matrix is also an affine transformation.
 ///
@@ -67,6 +64,7 @@
 
     #[allow(clippy::too_many_arguments)]
     #[inline(always)]
+    #[must_use]
     const fn new(
         m00: f64,
         m01: f64,
@@ -93,8 +91,9 @@
         }
     }
 
-    /// Creates a 4x4 matrix from two column vectors.
+    /// Creates a 4x4 matrix from four column vectors.
     #[inline(always)]
+    #[must_use]
     pub const fn from_cols(x_axis: DVec4, y_axis: DVec4, z_axis: DVec4, w_axis: DVec4) -> Self {
         Self {
             x_axis,
@@ -108,6 +107,7 @@
     /// If your data is stored in row major you will need to `transpose` the returned
     /// matrix.
     #[inline]
+    #[must_use]
     pub const fn from_cols_array(m: &[f64; 16]) -> Self {
         Self::new(
             m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9], m[10], m[11], m[12], m[13],
@@ -118,6 +118,7 @@
     /// Creates a `[f64; 16]` array storing data in column major order.
     /// If you require data in row major order `transpose` the matrix first.
     #[inline]
+    #[must_use]
     pub const fn to_cols_array(&self) -> [f64; 16] {
         [
             self.x_axis.x,
@@ -143,6 +144,7 @@
     /// If your data is in row major order you will need to `transpose` the returned
     /// matrix.
     #[inline]
+    #[must_use]
     pub const fn from_cols_array_2d(m: &[[f64; 4]; 4]) -> Self {
         Self::from_cols(
             DVec4::from_array(m[0]),
@@ -155,6 +157,7 @@
     /// Creates a `[[f64; 4]; 4]` 4D array storing data in column major order.
     /// If you require data in row major order `transpose` the matrix first.
     #[inline]
+    #[must_use]
     pub const fn to_cols_array_2d(&self) -> [[f64; 4]; 4] {
         [
             self.x_axis.to_array(),
@@ -167,6 +170,7 @@
     /// Creates a 4x4 matrix with its diagonal set to `diagonal` and all other entries set to 0.
     #[doc(alias = "scale")]
     #[inline]
+    #[must_use]
     pub const fn from_diagonal(diagonal: DVec4) -> Self {
         Self::new(
             diagonal.x, 0.0, 0.0, 0.0, 0.0, diagonal.y, 0.0, 0.0, 0.0, 0.0, diagonal.z, 0.0, 0.0,
@@ -175,6 +179,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn quat_to_axes(rotation: DQuat) -> (DVec4, DVec4, DVec4) {
         glam_assert!(rotation.is_normalized());
 
@@ -208,6 +213,7 @@
     ///
     /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_scale_rotation_translation(
         scale: DVec3,
         rotation: DQuat,
@@ -231,6 +237,7 @@
     ///
     /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_rotation_translation(rotation: DQuat, translation: DVec3) -> Self {
         let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
         Self::from_cols(x_axis, y_axis, z_axis, DVec4::from((translation, 1.0)))
@@ -244,12 +251,13 @@
     /// Will panic if the determinant of `self` is zero or if the resulting scale vector
     /// contains any zero elements when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn to_scale_rotation_translation(&self) -> (DVec3, DQuat, DVec3) {
         let det = self.determinant();
         glam_assert!(det != 0.0);
 
         let scale = DVec3::new(
-            self.x_axis.length() * det.signum(),
+            self.x_axis.length() * math::signum(det),
             self.y_axis.length(),
             self.z_axis.length(),
         );
@@ -278,6 +286,7 @@
     ///
     /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_quat(rotation: DQuat) -> Self {
         let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
         Self::from_cols(x_axis, y_axis, z_axis, DVec4::W)
@@ -289,6 +298,7 @@
     /// The resulting matrix can be used to transform 3D points and vectors. See
     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
     #[inline]
+    #[must_use]
     pub fn from_mat3(m: DMat3) -> Self {
         Self::from_cols(
             DVec4::from((m.x_axis, 0.0)),
@@ -303,6 +313,7 @@
     /// The resulting matrix can be used to transform 3D points and vectors. See
     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
     #[inline]
+    #[must_use]
     pub fn from_translation(translation: DVec3) -> Self {
         Self::from_cols(
             DVec4::X,
@@ -322,10 +333,11 @@
     ///
     /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_axis_angle(axis: DVec3, angle: f64) -> Self {
         glam_assert!(axis.is_normalized());
 
-        let (sin, cos) = angle.sin_cos();
+        let (sin, cos) = math::sin_cos(angle);
         let axis_sin = axis.mul(sin);
         let axis_sq = axis.mul(axis);
         let omc = 1.0 - cos;
@@ -355,12 +367,13 @@
         )
     }
 
-    #[inline]
     /// Creates a affine transformation matrix containing a rotation from the given euler
     /// rotation sequence and angles (in radians).
     ///
     /// The resulting matrix can be used to transform 3D points and vectors. See
     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
+    #[inline]
+    #[must_use]
     pub fn from_euler(order: EulerRot, a: f64, b: f64, c: f64) -> Self {
         let quat = DQuat::from_euler(order, a, b, c);
         Self::from_quat(quat)
@@ -372,8 +385,9 @@
     /// The resulting matrix can be used to transform 3D points and vectors. See
     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
     #[inline]
+    #[must_use]
     pub fn from_rotation_x(angle: f64) -> Self {
-        let (sina, cosa) = angle.sin_cos();
+        let (sina, cosa) = math::sin_cos(angle);
         Self::from_cols(
             DVec4::X,
             DVec4::new(0.0, cosa, sina, 0.0),
@@ -388,8 +402,9 @@
     /// The resulting matrix can be used to transform 3D points and vectors. See
     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
     #[inline]
+    #[must_use]
     pub fn from_rotation_y(angle: f64) -> Self {
-        let (sina, cosa) = angle.sin_cos();
+        let (sina, cosa) = math::sin_cos(angle);
         Self::from_cols(
             DVec4::new(cosa, 0.0, -sina, 0.0),
             DVec4::Y,
@@ -404,8 +419,9 @@
     /// The resulting matrix can be used to transform 3D points and vectors. See
     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
     #[inline]
+    #[must_use]
     pub fn from_rotation_z(angle: f64) -> Self {
-        let (sina, cosa) = angle.sin_cos();
+        let (sina, cosa) = math::sin_cos(angle);
         Self::from_cols(
             DVec4::new(cosa, sina, 0.0, 0.0),
             DVec4::new(-sina, cosa, 0.0, 0.0),
@@ -423,6 +439,7 @@
     ///
     /// Will panic if all elements of `scale` are zero when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_scale(scale: DVec3) -> Self {
         // Do not panic as long as any component is non-zero
         glam_assert!(scale.cmpne(DVec3::ZERO).any());
@@ -441,6 +458,7 @@
     ///
     /// Panics if `slice` is less than 16 elements long.
     #[inline]
+    #[must_use]
     pub const fn from_cols_slice(slice: &[f64]) -> Self {
         Self::new(
             slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
@@ -479,6 +497,7 @@
     ///
     /// Panics if `index` is greater than 3.
     #[inline]
+    #[must_use]
     pub fn col(&self, index: usize) -> DVec4 {
         match index {
             0 => self.x_axis,
@@ -511,6 +530,7 @@
     ///
     /// Panics if `index` is greater than 3.
     #[inline]
+    #[must_use]
     pub fn row(&self, index: usize) -> DVec4 {
         match index {
             0 => DVec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
@@ -524,6 +544,7 @@
     /// Returns `true` if, and only if, all elements are finite.
     /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
     #[inline]
+    #[must_use]
     pub fn is_finite(&self) -> bool {
         self.x_axis.is_finite()
             && self.y_axis.is_finite()
@@ -533,13 +554,14 @@
 
     /// Returns `true` if any elements are `NaN`.
     #[inline]
+    #[must_use]
     pub fn is_nan(&self) -> bool {
         self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan() || self.w_axis.is_nan()
     }
 
     /// Returns the transpose of `self`.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn transpose(&self) -> Self {
         Self {
             x_axis: DVec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
@@ -550,6 +572,7 @@
     }
 
     /// Returns the determinant of `self`.
+    #[must_use]
     pub fn determinant(&self) -> f64 {
         let (m00, m01, m02, m03) = self.x_axis.into();
         let (m10, m11, m12, m13) = self.y_axis.into();
@@ -655,6 +678,7 @@
     ///
     /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
     #[inline]
+    #[must_use]
     pub fn look_to_lh(eye: DVec3, dir: DVec3, up: DVec3) -> Self {
         Self::look_to_rh(eye, -dir, up)
     }
@@ -664,6 +688,7 @@
     ///
     /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
     #[inline]
+    #[must_use]
     pub fn look_to_rh(eye: DVec3, dir: DVec3, up: DVec3) -> Self {
         let f = dir.normalize();
         let s = f.cross(up).normalize();
@@ -685,6 +710,7 @@
     ///
     /// Will panic if `up` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn look_at_lh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
         glam_assert!(up.is_normalized());
         Self::look_to_lh(eye, center.sub(eye), up)
@@ -707,6 +733,7 @@
     /// This is the same as the OpenGL `gluPerspective` function.
     /// See <https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml>
     #[inline]
+    #[must_use]
     pub fn perspective_rh_gl(
         fov_y_radians: f64,
         aspect_ratio: f64,
@@ -714,7 +741,7 @@
         z_far: f64,
     ) -> Self {
         let inv_length = 1.0 / (z_near - z_far);
-        let f = 1.0 / (0.5 * fov_y_radians).tan();
+        let f = 1.0 / math::tan(0.5 * fov_y_radians);
         let a = f / aspect_ratio;
         let b = (z_near + z_far) * inv_length;
         let c = (2.0 * z_near * z_far) * inv_length;
@@ -733,9 +760,10 @@
     /// Will panic if `z_near` or `z_far` are less than or equal to zero when `glam_assert` is
     /// enabled.
     #[inline]
+    #[must_use]
     pub fn perspective_lh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64, z_far: f64) -> Self {
         glam_assert!(z_near > 0.0 && z_far > 0.0);
-        let (sin_fov, cos_fov) = (0.5 * fov_y_radians).sin_cos();
+        let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
         let h = cos_fov / sin_fov;
         let w = h / aspect_ratio;
         let r = z_far / (z_far - z_near);
@@ -754,9 +782,10 @@
     /// Will panic if `z_near` or `z_far` are less than or equal to zero when `glam_assert` is
     /// enabled.
     #[inline]
+    #[must_use]
     pub fn perspective_rh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64, z_far: f64) -> Self {
         glam_assert!(z_near > 0.0 && z_far > 0.0);
-        let (sin_fov, cos_fov) = (0.5 * fov_y_radians).sin_cos();
+        let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
         let h = cos_fov / sin_fov;
         let w = h / aspect_ratio;
         let r = z_far / (z_near - z_far);
@@ -774,9 +803,10 @@
     ///
     /// Will panic if `z_near` is less than or equal to zero when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn perspective_infinite_lh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64) -> Self {
         glam_assert!(z_near > 0.0);
-        let (sin_fov, cos_fov) = (0.5 * fov_y_radians).sin_cos();
+        let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
         let h = cos_fov / sin_fov;
         let w = h / aspect_ratio;
         Self::from_cols(
@@ -793,13 +823,14 @@
     ///
     /// Will panic if `z_near` is less than or equal to zero when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn perspective_infinite_reverse_lh(
         fov_y_radians: f64,
         aspect_ratio: f64,
         z_near: f64,
     ) -> Self {
         glam_assert!(z_near > 0.0);
-        let (sin_fov, cos_fov) = (0.5 * fov_y_radians).sin_cos();
+        let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
         let h = cos_fov / sin_fov;
         let w = h / aspect_ratio;
         Self::from_cols(
@@ -813,9 +844,10 @@
     /// Creates an infinite right-handed perspective projection matrix with
     /// `[0,1]` depth range.
     #[inline]
+    #[must_use]
     pub fn perspective_infinite_rh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64) -> Self {
         glam_assert!(z_near > 0.0);
-        let f = 1.0 / (0.5 * fov_y_radians).tan();
+        let f = 1.0 / math::tan(0.5 * fov_y_radians);
         Self::from_cols(
             DVec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
             DVec4::new(0.0, f, 0.0, 0.0),
@@ -827,13 +859,14 @@
     /// Creates an infinite reverse right-handed perspective projection matrix
     /// with `[0,1]` depth range.
     #[inline]
+    #[must_use]
     pub fn perspective_infinite_reverse_rh(
         fov_y_radians: f64,
         aspect_ratio: f64,
         z_near: f64,
     ) -> Self {
         glam_assert!(z_near > 0.0);
-        let f = 1.0 / (0.5 * fov_y_radians).tan();
+        let f = 1.0 / math::tan(0.5 * fov_y_radians);
         Self::from_cols(
             DVec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
             DVec4::new(0.0, f, 0.0, 0.0),
@@ -847,6 +880,7 @@
     /// See
     /// <https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glOrtho.xml>
     #[inline]
+    #[must_use]
     pub fn orthographic_rh_gl(
         left: f64,
         right: f64,
@@ -872,6 +906,7 @@
 
     /// Creates a left-handed orthographic projection matrix with `[0,1]` depth range.
     #[inline]
+    #[must_use]
     pub fn orthographic_lh(
         left: f64,
         right: f64,
@@ -898,6 +933,7 @@
 
     /// Creates a right-handed orthographic projection matrix with `[0,1]` depth range.
     #[inline]
+    #[must_use]
     pub fn orthographic_rh(
         left: f64,
         right: f64,
@@ -929,6 +965,7 @@
     ///
     /// This method assumes that `self` contains a projective transform.
     #[inline]
+    #[must_use]
     pub fn project_point3(&self, rhs: DVec3) -> DVec3 {
         let mut res = self.x_axis.mul(rhs.x);
         res = self.y_axis.mul(rhs.y).add(res);
@@ -951,6 +988,7 @@
     ///
     /// Will panic if the 3rd row of `self` is not `(0, 0, 0, 1)` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn transform_point3(&self, rhs: DVec3) -> DVec3 {
         glam_assert!(self.row(3).abs_diff_eq(DVec4::W, 1e-6));
         let mut res = self.x_axis.mul(rhs.x);
@@ -971,6 +1009,7 @@
     ///
     /// Will panic if the 3rd row of `self` is not `(0, 0, 0, 1)` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn transform_vector3(&self, rhs: DVec3) -> DVec3 {
         glam_assert!(self.row(3).abs_diff_eq(DVec4::W, 1e-6));
         let mut res = self.x_axis.mul(rhs.x);
@@ -981,6 +1020,7 @@
 
     /// Transforms a 4D vector.
     #[inline]
+    #[must_use]
     pub fn mul_vec4(&self, rhs: DVec4) -> DVec4 {
         let mut res = self.x_axis.mul(rhs.x);
         res = res.add(self.y_axis.mul(rhs.y));
@@ -991,6 +1031,7 @@
 
     /// Multiplies two 4x4 matrices.
     #[inline]
+    #[must_use]
     pub fn mul_mat4(&self, rhs: &Self) -> Self {
         Self::from_cols(
             self.mul(rhs.x_axis),
@@ -1002,6 +1043,7 @@
 
     /// Adds two 4x4 matrices.
     #[inline]
+    #[must_use]
     pub fn add_mat4(&self, rhs: &Self) -> Self {
         Self::from_cols(
             self.x_axis.add(rhs.x_axis),
@@ -1013,6 +1055,7 @@
 
     /// Subtracts two 4x4 matrices.
     #[inline]
+    #[must_use]
     pub fn sub_mat4(&self, rhs: &Self) -> Self {
         Self::from_cols(
             self.x_axis.sub(rhs.x_axis),
@@ -1024,6 +1067,7 @@
 
     /// Multiplies a 4x4 matrix by a scalar.
     #[inline]
+    #[must_use]
     pub fn mul_scalar(&self, rhs: f64) -> Self {
         Self::from_cols(
             self.x_axis.mul(rhs),
@@ -1043,6 +1087,7 @@
     /// For more see
     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
     #[inline]
+    #[must_use]
     pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
         self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
             && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
diff --git a/src/f64/dquat.rs b/src/f64/dquat.rs
index 6f89430..eddcfa1 100644
--- a/src/f64/dquat.rs
+++ b/src/f64/dquat.rs
@@ -2,13 +2,10 @@
 
 use crate::{
     euler::{EulerFromQuaternion, EulerRot, EulerToQuaternion},
-    DMat3, DMat4, DVec2, DVec3, DVec4, FloatEx, Quat,
+    f64::math,
+    DMat3, DMat4, DVec2, DVec3, DVec4, Quat,
 };
 
-#[cfg(feature = "libm")]
-#[allow(unused_imports)]
-use num_traits::Float;
-
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
 use core::iter::{Product, Sum};
@@ -19,6 +16,7 @@
 /// This should generally not be called manually unless you know what you are doing. Use
 /// one of the other constructors instead such as `identity` or `from_axis_angle`.
 #[inline]
+#[must_use]
 pub const fn dquat(x: f64, y: f64, z: f64, w: f64) -> DQuat {
     DQuat::from_xyzw(x, y, z, w)
 }
@@ -60,6 +58,7 @@
     /// This function does not check if the input is normalized, it is up to the user to
     /// provide normalized input or to normalized the resulting quaternion.
     #[inline(always)]
+    #[must_use]
     pub const fn from_xyzw(x: f64, y: f64, z: f64, w: f64) -> Self {
         Self { x, y, z, w }
     }
@@ -71,6 +70,7 @@
     /// This function does not check if the input is normalized, it is up to the user to
     /// provide normalized input or to normalized the resulting quaternion.
     #[inline]
+    #[must_use]
     pub const fn from_array(a: [f64; 4]) -> Self {
         Self::from_xyzw(a[0], a[1], a[2], a[3])
     }
@@ -82,7 +82,8 @@
     /// This function does not check if the input is normalized, it is up to the user to
     /// provide normalized input or to normalized the resulting quaternion.
     #[inline]
-    pub fn from_vec4(v: DVec4) -> Self {
+    #[must_use]
+    pub const fn from_vec4(v: DVec4) -> Self {
         Self {
             x: v.x,
             y: v.y,
@@ -102,6 +103,7 @@
     ///
     /// Panics if `slice` length is less than 4.
     #[inline]
+    #[must_use]
     pub fn from_slice(slice: &[f64]) -> Self {
         Self::from_xyzw(slice[0], slice[1], slice[2], slice[3])
     }
@@ -120,15 +122,17 @@
     }
 
     /// Create a quaternion for a normalized rotation `axis` and `angle` (in radians).
-    /// The axis must be normalized (unit-length).
+    ///
+    /// The axis must be a unit vector.
     ///
     /// # Panics
     ///
     /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_axis_angle(axis: DVec3, angle: f64) -> Self {
         glam_assert!(axis.is_normalized());
-        let (s, c) = (angle * 0.5).sin_cos();
+        let (s, c) = math::sin_cos(angle * 0.5);
         let v = axis * s;
         Self::from_xyzw(v.x, v.y, v.z, c)
     }
@@ -137,6 +141,7 @@
     ///
     /// `from_scaled_axis(Vec3::ZERO)` results in the identity quaternion.
     #[inline]
+    #[must_use]
     pub fn from_scaled_axis(v: DVec3) -> Self {
         let length = v.length();
         if length == 0.0 {
@@ -148,33 +153,38 @@
 
     /// Creates a quaternion from the `angle` (in radians) around the x axis.
     #[inline]
+    #[must_use]
     pub fn from_rotation_x(angle: f64) -> Self {
-        let (s, c) = (angle * 0.5).sin_cos();
+        let (s, c) = math::sin_cos(angle * 0.5);
         Self::from_xyzw(s, 0.0, 0.0, c)
     }
 
     /// Creates a quaternion from the `angle` (in radians) around the y axis.
     #[inline]
+    #[must_use]
     pub fn from_rotation_y(angle: f64) -> Self {
-        let (s, c) = (angle * 0.5).sin_cos();
+        let (s, c) = math::sin_cos(angle * 0.5);
         Self::from_xyzw(0.0, s, 0.0, c)
     }
 
     /// Creates a quaternion from the `angle` (in radians) around the z axis.
     #[inline]
+    #[must_use]
     pub fn from_rotation_z(angle: f64) -> Self {
-        let (s, c) = (angle * 0.5).sin_cos();
+        let (s, c) = math::sin_cos(angle * 0.5);
         Self::from_xyzw(0.0, 0.0, s, c)
     }
 
-    #[inline]
     /// Creates a quaternion from the given Euler rotation sequence and the angles (in radians).
+    #[inline]
+    #[must_use]
     pub fn from_euler(euler: EulerRot, a: f64, b: f64, c: f64) -> Self {
         euler.new_quat(a, b, c)
     }
 
     /// From the columns of a 3x3 rotation matrix.
     #[inline]
+    #[must_use]
     pub(crate) fn from_rotation_axes(x_axis: DVec3, y_axis: DVec3, z_axis: DVec3) -> Self {
         // Based on https://github.com/microsoft/DirectXMath `XM$quaternionRotationMatrix`
         let (m00, m01, m02) = x_axis.into();
@@ -187,7 +197,7 @@
             if dif10 <= 0.0 {
                 // x^2 >= y^2
                 let four_xsq = omm22 - dif10;
-                let inv4x = 0.5 / four_xsq.sqrt();
+                let inv4x = 0.5 / math::sqrt(four_xsq);
                 Self::from_xyzw(
                     four_xsq * inv4x,
                     (m01 + m10) * inv4x,
@@ -197,7 +207,7 @@
             } else {
                 // y^2 >= x^2
                 let four_ysq = omm22 + dif10;
-                let inv4y = 0.5 / four_ysq.sqrt();
+                let inv4y = 0.5 / math::sqrt(four_ysq);
                 Self::from_xyzw(
                     (m01 + m10) * inv4y,
                     four_ysq * inv4y,
@@ -212,7 +222,7 @@
             if sum10 <= 0.0 {
                 // z^2 >= w^2
                 let four_zsq = opm22 - sum10;
-                let inv4z = 0.5 / four_zsq.sqrt();
+                let inv4z = 0.5 / math::sqrt(four_zsq);
                 Self::from_xyzw(
                     (m02 + m20) * inv4z,
                     (m12 + m21) * inv4z,
@@ -222,7 +232,7 @@
             } else {
                 // w^2 >= z^2
                 let four_wsq = opm22 + sum10;
-                let inv4w = 0.5 / four_wsq.sqrt();
+                let inv4w = 0.5 / math::sqrt(four_wsq);
                 Self::from_xyzw(
                     (m12 - m21) * inv4w,
                     (m20 - m02) * inv4w,
@@ -235,12 +245,14 @@
 
     /// Creates a quaternion from a 3x3 rotation matrix.
     #[inline]
+    #[must_use]
     pub fn from_mat3(mat: &DMat3) -> Self {
         Self::from_rotation_axes(mat.x_axis, mat.y_axis, mat.z_axis)
     }
 
     /// Creates a quaternion from a 3x3 rotation matrix inside a homogeneous 4x4 matrix.
     #[inline]
+    #[must_use]
     pub fn from_mat4(mat: &DMat4) -> Self {
         Self::from_rotation_axes(
             mat.x_axis.truncate(),
@@ -252,7 +264,7 @@
     /// Gets the minimal rotation for transforming `from` to `to`.  The rotation is in the
     /// plane spanned by the two vectors.  Will rotate at most 180 degrees.
     ///
-    /// The input vectors must be normalized (unit-length).
+    /// The inputs must be unit vectors.
     ///
     /// `from_rotation_arc(from, to) * from ≈ to`.
     ///
@@ -262,6 +274,7 @@
     /// # Panics
     ///
     /// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
+    #[must_use]
     pub fn from_rotation_arc(from: DVec3, to: DVec3) -> Self {
         glam_assert!(from.is_normalized());
         glam_assert!(to.is_normalized());
@@ -287,7 +300,7 @@
     /// The rotation is in the plane spanned by the two vectors.  Will rotate at most 90
     /// degrees.
     ///
-    /// The input vectors must be normalized (unit-length).
+    /// The inputs must be unit vectors.
     ///
     /// `to.dot(from_rotation_arc_colinear(from, to) * from).abs() ≈ 1`.
     ///
@@ -295,6 +308,7 @@
     ///
     /// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn from_rotation_arc_colinear(from: DVec3, to: DVec3) -> Self {
         if from.dot(to) < 0.0 {
             Self::from_rotation_arc(from, -to)
@@ -306,7 +320,7 @@
     /// Gets the minimal rotation for transforming `from` to `to`.  The resulting rotation is
     /// around the z axis. Will rotate at most 180 degrees.
     ///
-    /// The input vectors must be normalized (unit-length).
+    /// The inputs must be unit vectors.
     ///
     /// `from_rotation_arc_2d(from, to) * from ≈ to`.
     ///
@@ -316,6 +330,7 @@
     /// # Panics
     ///
     /// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
+    #[must_use]
     pub fn from_rotation_arc_2d(from: DVec2, to: DVec2) -> Self {
         glam_assert!(from.is_normalized());
         glam_assert!(to.is_normalized());
@@ -336,31 +351,30 @@
             let z = from.x * to.y - to.x * from.y;
             let w = 1.0 + dot;
             // calculate length with x=0 and y=0 to normalize
-            let len_rcp = 1.0 / (z * z + w * w).sqrt();
+            let len_rcp = 1.0 / math::sqrt(z * z + w * w);
             Self::from_xyzw(0.0, 0.0, z * len_rcp, w * len_rcp)
         }
     }
 
-    /// Returns the rotation axis and angle (in radians) of `self`.
+    /// Returns the rotation axis (normalized) and angle (in radians) of `self`.
     #[inline]
+    #[must_use]
     pub fn to_axis_angle(self) -> (DVec3, f64) {
         const EPSILON: f64 = 1.0e-8;
-        const EPSILON_SQUARED: f64 = EPSILON * EPSILON;
-        let w = self.w;
-        let angle = w.acos_approx() * 2.0;
-        let scale_sq = f64::max(1.0 - w * w, 0.0);
-        if scale_sq >= EPSILON_SQUARED {
-            (
-                DVec3::new(self.x, self.y, self.z) * scale_sq.sqrt().recip(),
-                angle,
-            )
+        let v = DVec3::new(self.x, self.y, self.z);
+        let length = v.length();
+        if length >= EPSILON {
+            let angle = 2.0 * math::atan2(length, self.w);
+            let axis = v / length;
+            (axis, angle)
         } else {
-            (DVec3::X, angle)
+            (DVec3::X, 0.0)
         }
     }
 
     /// Returns the rotation axis scaled by the rotation in radians.
     #[inline]
+    #[must_use]
     pub fn to_scaled_axis(self) -> DVec3 {
         let (axis, angle) = self.to_axis_angle();
         axis * angle
@@ -368,26 +382,29 @@
 
     /// Returns the rotation angles for the given euler rotation sequence.
     #[inline]
+    #[must_use]
     pub fn to_euler(self, euler: EulerRot) -> (f64, f64, f64) {
         euler.convert_quat(self)
     }
 
     /// `[x, y, z, w]`
     #[inline]
+    #[must_use]
     pub fn to_array(&self) -> [f64; 4] {
         [self.x, self.y, self.z, self.w]
     }
 
     /// Returns the vector part of the quaternion.
     #[inline]
+    #[must_use]
     pub fn xyz(self) -> DVec3 {
         DVec3::new(self.x, self.y, self.z)
     }
 
     /// Returns the quaternion conjugate of `self`. For a unit quaternion the
     /// conjugate is also the inverse.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn conjugate(self) -> Self {
         Self {
             x: -self.x,
@@ -406,8 +423,8 @@
     /// # Panics
     ///
     /// Will panic if `self` is not normalized when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn inverse(self) -> Self {
         glam_assert!(self.is_normalized());
         self.conjugate()
@@ -416,6 +433,7 @@
     /// Computes the dot product of `self` and `rhs`. The dot product is
     /// equal to the cosine of the angle between two quaternion rotations.
     #[inline]
+    #[must_use]
     pub fn dot(self, rhs: Self) -> f64 {
         DVec4::from(self).dot(DVec4::from(rhs))
     }
@@ -423,6 +441,7 @@
     /// Computes the length of `self`.
     #[doc(alias = "magnitude")]
     #[inline]
+    #[must_use]
     pub fn length(self) -> f64 {
         DVec4::from(self).length()
     }
@@ -433,6 +452,7 @@
     /// root operation.
     #[doc(alias = "magnitude2")]
     #[inline]
+    #[must_use]
     pub fn length_squared(self) -> f64 {
         DVec4::from(self).length_squared()
     }
@@ -441,6 +461,7 @@
     ///
     /// For valid results, `self` must _not_ be of length zero.
     #[inline]
+    #[must_use]
     pub fn length_recip(self) -> f64 {
         DVec4::from(self).length_recip()
     }
@@ -452,8 +473,8 @@
     /// Panics
     ///
     /// Will panic if `self` is zero length when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn normalize(self) -> Self {
         Self::from_vec4(DVec4::from(self).normalize())
     }
@@ -461,11 +482,13 @@
     /// Returns `true` if, and only if, all elements are finite.
     /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
     #[inline]
+    #[must_use]
     pub fn is_finite(self) -> bool {
         DVec4::from(self).is_finite()
     }
 
     #[inline]
+    #[must_use]
     pub fn is_nan(self) -> bool {
         DVec4::from(self).is_nan()
     }
@@ -474,11 +497,13 @@
     ///
     /// Uses a precision threshold of `1e-6`.
     #[inline]
+    #[must_use]
     pub fn is_normalized(self) -> bool {
         DVec4::from(self).is_normalized()
     }
 
     #[inline]
+    #[must_use]
     pub fn is_near_identity(self) -> bool {
         // Based on https://github.com/nfrechette/rtm `rtm::quat_near_identity`
         let threshold_angle = 0.002_847_144_6;
@@ -495,7 +520,7 @@
         // If the quat.w is close to -1.0, the angle will be near 2*PI which is close to
         // a negative 0 rotation. By forcing quat.w to be positive, we'll end up with
         // the shortest path.
-        let positive_w_angle = self.w.abs().acos_approx() * 2.0;
+        let positive_w_angle = math::acos_approx(math::abs(self.w)) * 2.0;
         positive_w_angle < threshold_angle
     }
 
@@ -508,9 +533,10 @@
     ///
     /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn angle_between(self, rhs: Self) -> f64 {
         glam_assert!(self.is_normalized() && rhs.is_normalized());
-        self.dot(rhs).abs().acos_approx() * 2.0
+        math::acos_approx(math::abs(self.dot(rhs))) * 2.0
     }
 
     /// Returns true if the absolute difference of all elements between `self` and `rhs`
@@ -523,6 +549,7 @@
     /// For more see
     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
     #[inline]
+    #[must_use]
     pub fn abs_diff_eq(self, rhs: Self, max_abs_diff: f64) -> bool {
         DVec4::from(self).abs_diff_eq(DVec4::from(rhs), max_abs_diff)
     }
@@ -536,8 +563,9 @@
     /// # Panics
     ///
     /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
-    #[inline]
     #[doc(alias = "mix")]
+    #[inline]
+    #[must_use]
     pub fn lerp(self, end: Self, s: f64) -> Self {
         glam_assert!(self.is_normalized());
         glam_assert!(end.is_normalized());
@@ -559,6 +587,7 @@
     ///
     /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn slerp(self, mut end: Self, s: f64) -> Self {
         // http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/
         glam_assert!(self.is_normalized());
@@ -582,13 +611,13 @@
             // assumes lerp returns a normalized quaternion
             self.lerp(end, s)
         } else {
-            let theta = dot.acos_approx();
+            let theta = math::acos_approx(dot);
 
-            let scale1 = (theta * (1.0 - s)).sin();
-            let scale2 = (theta * s).sin();
-            let theta_sin = theta.sin();
+            let scale1 = math::sin(theta * (1.0 - s));
+            let scale2 = math::sin(theta * s);
+            let theta_sin = math::sin(theta);
 
-            self.mul(scale1).add(end.mul(scale2)).mul(theta_sin.recip())
+            self.mul(scale1).add(end.mul(scale2)).mul(1.0 / theta_sin)
         }
     }
 
@@ -598,6 +627,7 @@
     ///
     /// Will panic if `self` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn mul_vec3(self, rhs: DVec3) -> DVec3 {
         glam_assert!(self.is_normalized());
 
@@ -618,6 +648,7 @@
     ///
     /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn mul_quat(self, rhs: Self) -> Self {
         glam_assert!(self.is_normalized());
         glam_assert!(rhs.is_normalized());
@@ -634,6 +665,7 @@
 
     /// Creates a quaternion from a 3x3 rotation matrix inside a 3D affine transform.
     #[inline]
+    #[must_use]
     pub fn from_affine3(a: &crate::DAffine3) -> Self {
         #[allow(clippy::useless_conversion)]
         Self::from_rotation_axes(
@@ -644,9 +676,17 @@
     }
 
     #[inline]
-    pub fn as_f32(self) -> Quat {
+    #[must_use]
+    pub fn as_quat(self) -> Quat {
         Quat::from_xyzw(self.x as f32, self.y as f32, self.z as f32, self.w as f32)
     }
+
+    #[inline]
+    #[must_use]
+    #[deprecated(since = "0.24.2", note = "Use as_quat() instead")]
+    pub fn as_f32(self) -> Quat {
+        self.as_quat()
+    }
 }
 
 #[cfg(not(target_arch = "spirv"))]
diff --git a/src/f64/dvec2.rs b/src/f64/dvec2.rs
index c52356e..33bf6ac 100644
--- a/src/f64/dvec2.rs
+++ b/src/f64/dvec2.rs
@@ -1,18 +1,15 @@
 // Generated from vec.rs.tera template. Edit the template, not the generated file.
 
-use crate::{BVec2, DVec3};
+use crate::{f64::math, BVec2, DVec3, IVec2, UVec2, Vec2};
 
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
 use core::iter::{Product, Sum};
 use core::{f32, ops::*};
 
-#[cfg(feature = "libm")]
-#[allow(unused_imports)]
-use num_traits::Float;
-
 /// Creates a 2-dimensional vector.
 #[inline(always)]
+#[must_use]
 pub const fn dvec2(x: f64, y: f64) -> DVec2 {
     DVec2::new(x, y)
 }
@@ -37,19 +34,31 @@
     /// All negative ones.
     pub const NEG_ONE: Self = Self::splat(-1.0);
 
-    /// All NAN.
+    /// All `f64::MIN`.
+    pub const MIN: Self = Self::splat(f64::MIN);
+
+    /// All `f64::MAX`.
+    pub const MAX: Self = Self::splat(f64::MAX);
+
+    /// All `f64::NAN`.
     pub const NAN: Self = Self::splat(f64::NAN);
 
-    /// A unit-length vector pointing along the positive X axis.
+    /// All `f64::INFINITY`.
+    pub const INFINITY: Self = Self::splat(f64::INFINITY);
+
+    /// All `f64::NEG_INFINITY`.
+    pub const NEG_INFINITY: Self = Self::splat(f64::NEG_INFINITY);
+
+    /// A unit vector pointing along the positive X axis.
     pub const X: Self = Self::new(1.0, 0.0);
 
-    /// A unit-length vector pointing along the positive Y axis.
+    /// A unit vector pointing along the positive Y axis.
     pub const Y: Self = Self::new(0.0, 1.0);
 
-    /// A unit-length vector pointing along the negative X axis.
+    /// A unit vector pointing along the negative X axis.
     pub const NEG_X: Self = Self::new(-1.0, 0.0);
 
-    /// A unit-length vector pointing along the negative Y axis.
+    /// A unit vector pointing along the negative Y axis.
     pub const NEG_Y: Self = Self::new(0.0, -1.0);
 
     /// The unit axes.
@@ -57,12 +66,14 @@
 
     /// Creates a new vector.
     #[inline(always)]
+    #[must_use]
     pub const fn new(x: f64, y: f64) -> Self {
         Self { x, y }
     }
 
     /// Creates a vector with all elements set to `v`.
     #[inline]
+    #[must_use]
     pub const fn splat(v: f64) -> Self {
         Self { x: v, y: v }
     }
@@ -73,21 +84,24 @@
     /// A true element in the mask uses the corresponding element from `if_true`, and false
     /// uses the element from `if_false`.
     #[inline]
+    #[must_use]
     pub fn select(mask: BVec2, if_true: Self, if_false: Self) -> Self {
         Self {
-            x: if mask.x { if_true.x } else { if_false.x },
-            y: if mask.y { if_true.y } else { if_false.y },
+            x: if mask.test(0) { if_true.x } else { if_false.x },
+            y: if mask.test(1) { if_true.y } else { if_false.y },
         }
     }
 
     /// Creates a new vector from an array.
     #[inline]
+    #[must_use]
     pub const fn from_array(a: [f64; 2]) -> Self {
         Self::new(a[0], a[1])
     }
 
     /// `[x, y]`
     #[inline]
+    #[must_use]
     pub const fn to_array(&self) -> [f64; 2] {
         [self.x, self.y]
     }
@@ -98,6 +112,7 @@
     ///
     /// Panics if `slice` is less than 2 elements long.
     #[inline]
+    #[must_use]
     pub const fn from_slice(slice: &[f64]) -> Self {
         Self::new(slice[0], slice[1])
     }
@@ -115,18 +130,21 @@
 
     /// Creates a 3D vector from `self` and the given `z` value.
     #[inline]
+    #[must_use]
     pub const fn extend(self, z: f64) -> DVec3 {
         DVec3::new(self.x, self.y, z)
     }
 
     /// Computes the dot product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn dot(self, rhs: Self) -> f64 {
         (self.x * rhs.x) + (self.y * rhs.y)
     }
 
     /// Returns a vector where every component is the dot product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn dot_into_vec(self, rhs: Self) -> Self {
         Self::splat(self.dot(rhs))
     }
@@ -135,6 +153,7 @@
     ///
     /// In other words this computes `[self.x.min(rhs.x), self.y.min(rhs.y), ..]`.
     #[inline]
+    #[must_use]
     pub fn min(self, rhs: Self) -> Self {
         Self {
             x: self.x.min(rhs.x),
@@ -146,6 +165,7 @@
     ///
     /// In other words this computes `[self.x.max(rhs.x), self.y.max(rhs.y), ..]`.
     #[inline]
+    #[must_use]
     pub fn max(self, rhs: Self) -> Self {
         Self {
             x: self.x.max(rhs.x),
@@ -161,6 +181,7 @@
     ///
     /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn clamp(self, min: Self, max: Self) -> Self {
         glam_assert!(min.cmple(max).all(), "clamp: expected min <= max");
         self.max(min).min(max)
@@ -170,6 +191,7 @@
     ///
     /// In other words this computes `min(x, y, ..)`.
     #[inline]
+    #[must_use]
     pub fn min_element(self) -> f64 {
         self.x.min(self.y)
     }
@@ -178,6 +200,7 @@
     ///
     /// In other words this computes `max(x, y, ..)`.
     #[inline]
+    #[must_use]
     pub fn max_element(self) -> f64 {
         self.x.max(self.y)
     }
@@ -188,6 +211,7 @@
     /// In other words, this computes `[self.x == rhs.x, self.y == rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpeq(self, rhs: Self) -> BVec2 {
         BVec2::new(self.x.eq(&rhs.x), self.y.eq(&rhs.y))
     }
@@ -198,6 +222,7 @@
     /// In other words this computes `[self.x != rhs.x, self.y != rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpne(self, rhs: Self) -> BVec2 {
         BVec2::new(self.x.ne(&rhs.x), self.y.ne(&rhs.y))
     }
@@ -208,6 +233,7 @@
     /// In other words this computes `[self.x >= rhs.x, self.y >= rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpge(self, rhs: Self) -> BVec2 {
         BVec2::new(self.x.ge(&rhs.x), self.y.ge(&rhs.y))
     }
@@ -218,6 +244,7 @@
     /// In other words this computes `[self.x > rhs.x, self.y > rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpgt(self, rhs: Self) -> BVec2 {
         BVec2::new(self.x.gt(&rhs.x), self.y.gt(&rhs.y))
     }
@@ -228,6 +255,7 @@
     /// In other words this computes `[self.x <= rhs.x, self.y <= rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmple(self, rhs: Self) -> BVec2 {
         BVec2::new(self.x.le(&rhs.x), self.y.le(&rhs.y))
     }
@@ -238,16 +266,18 @@
     /// In other words this computes `[self.x < rhs.x, self.y < rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmplt(self, rhs: Self) -> BVec2 {
         BVec2::new(self.x.lt(&rhs.x), self.y.lt(&rhs.y))
     }
 
     /// Returns a vector containing the absolute value of each element of `self`.
     #[inline]
+    #[must_use]
     pub fn abs(self) -> Self {
         Self {
-            x: self.x.abs(),
-            y: self.y.abs(),
+            x: math::abs(self.x),
+            y: math::abs(self.y),
         }
     }
 
@@ -257,19 +287,21 @@
     /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
     /// - `NAN` if the number is `NAN`
     #[inline]
+    #[must_use]
     pub fn signum(self) -> Self {
         Self {
-            x: self.x.signum(),
-            y: self.y.signum(),
+            x: math::signum(self.x),
+            y: math::signum(self.y),
         }
     }
 
     /// Returns a vector with signs of `rhs` and the magnitudes of `self`.
     #[inline]
+    #[must_use]
     pub fn copysign(self, rhs: Self) -> Self {
         Self {
-            x: self.x.copysign(rhs.x),
-            y: self.y.copysign(rhs.y),
+            x: math::copysign(self.x, rhs.x),
+            y: math::copysign(self.y, rhs.y),
         }
     }
 
@@ -278,6 +310,7 @@
     /// A negative element results in a `1` bit and a positive element in a `0` bit.  Element `x` goes
     /// into the first lowest bit, element `y` into the second, etc.
     #[inline]
+    #[must_use]
     pub fn is_negative_bitmask(self) -> u32 {
         (self.x.is_sign_negative() as u32) | (self.y.is_sign_negative() as u32) << 1
     }
@@ -285,12 +318,14 @@
     /// Returns `true` if, and only if, all elements are finite.  If any element is either
     /// `NaN`, positive or negative infinity, this will return `false`.
     #[inline]
+    #[must_use]
     pub fn is_finite(self) -> bool {
         self.x.is_finite() && self.y.is_finite()
     }
 
     /// Returns `true` if any elements are `NaN`.
     #[inline]
+    #[must_use]
     pub fn is_nan(self) -> bool {
         self.x.is_nan() || self.y.is_nan()
     }
@@ -299,6 +334,7 @@
     ///
     /// In other words, this computes `[x.is_nan(), y.is_nan(), z.is_nan(), w.is_nan()]`.
     #[inline]
+    #[must_use]
     pub fn is_nan_mask(self) -> BVec2 {
         BVec2::new(self.x.is_nan(), self.y.is_nan())
     }
@@ -306,8 +342,9 @@
     /// Computes the length of `self`.
     #[doc(alias = "magnitude")]
     #[inline]
+    #[must_use]
     pub fn length(self) -> f64 {
-        self.dot(self).sqrt()
+        math::sqrt(self.dot(self))
     }
 
     /// Computes the squared length of `self`.
@@ -315,6 +352,7 @@
     /// This is faster than `length()` as it avoids a square root operation.
     #[doc(alias = "magnitude2")]
     #[inline]
+    #[must_use]
     pub fn length_squared(self) -> f64 {
         self.dot(self)
     }
@@ -323,33 +361,58 @@
     ///
     /// For valid results, `self` must _not_ be of length zero.
     #[inline]
+    #[must_use]
     pub fn length_recip(self) -> f64 {
         self.length().recip()
     }
 
     /// Computes the Euclidean distance between two points in space.
     #[inline]
+    #[must_use]
     pub fn distance(self, rhs: Self) -> f64 {
         (self - rhs).length()
     }
 
     /// Compute the squared euclidean distance between two points in space.
     #[inline]
+    #[must_use]
     pub fn distance_squared(self, rhs: Self) -> f64 {
         (self - rhs).length_squared()
     }
 
+    /// Returns the element-wise quotient of [Euclidean division] of `self` by `rhs`.
+    #[inline]
+    #[must_use]
+    pub fn div_euclid(self, rhs: Self) -> Self {
+        Self::new(
+            math::div_euclid(self.x, rhs.x),
+            math::div_euclid(self.y, rhs.y),
+        )
+    }
+
+    /// Returns the element-wise remainder of [Euclidean division] of `self` by `rhs`.
+    ///
+    /// [Euclidean division]: f64::rem_euclid
+    #[inline]
+    #[must_use]
+    pub fn rem_euclid(self, rhs: Self) -> Self {
+        Self::new(
+            math::rem_euclid(self.x, rhs.x),
+            math::rem_euclid(self.y, rhs.y),
+        )
+    }
+
     /// Returns `self` normalized to length 1.0.
     ///
     /// For valid results, `self` must _not_ be of length zero, nor very close to zero.
     ///
-    /// See also [`Self::try_normalize`] and [`Self::normalize_or_zero`].
+    /// See also [`Self::try_normalize()`] and [`Self::normalize_or_zero()`].
     ///
     /// Panics
     ///
     /// Will panic if `self` is zero length when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn normalize(self) -> Self {
         #[allow(clippy::let_and_return)]
         let normalized = self.mul(self.length_recip());
@@ -362,9 +425,9 @@
     /// In particular, if the input is zero (or very close to zero), or non-finite,
     /// the result of this operation will be `None`.
     ///
-    /// See also [`Self::normalize_or_zero`].
-    #[must_use]
+    /// See also [`Self::normalize_or_zero()`].
     #[inline]
+    #[must_use]
     pub fn try_normalize(self) -> Option<Self> {
         let rcp = self.length_recip();
         if rcp.is_finite() && rcp > 0.0 {
@@ -379,9 +442,9 @@
     /// In particular, if the input is zero (or very close to zero), or non-finite,
     /// the result of this operation will be zero.
     ///
-    /// See also [`Self::try_normalize`].
-    #[must_use]
+    /// See also [`Self::try_normalize()`].
     #[inline]
+    #[must_use]
     pub fn normalize_or_zero(self) -> Self {
         let rcp = self.length_recip();
         if rcp.is_finite() && rcp > 0.0 {
@@ -395,9 +458,10 @@
     ///
     /// Uses a precision threshold of `1e-6`.
     #[inline]
+    #[must_use]
     pub fn is_normalized(self) -> bool {
         // TODO: do something with epsilon
-        (self.length_squared() - 1.0).abs() <= 1e-4
+        math::abs(self.length_squared() - 1.0) <= 1e-4
     }
 
     /// Returns the vector projection of `self` onto `rhs`.
@@ -407,8 +471,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` is zero length when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn project_onto(self, rhs: Self) -> Self {
         let other_len_sq_rcp = rhs.dot(rhs).recip();
         glam_assert!(other_len_sq_rcp.is_finite());
@@ -425,8 +489,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` has a length of zero when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn reject_from(self, rhs: Self) -> Self {
         self - self.project_onto(rhs)
     }
@@ -438,8 +502,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` is not normalized when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn project_onto_normalized(self, rhs: Self) -> Self {
         glam_assert!(rhs.is_normalized());
         rhs * self.dot(rhs)
@@ -455,8 +519,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` is not normalized when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn reject_from_normalized(self, rhs: Self) -> Self {
         self - self.project_onto_normalized(rhs)
     }
@@ -464,30 +528,44 @@
     /// Returns a vector containing the nearest integer to a number for each element of `self`.
     /// Round half-way cases away from 0.0.
     #[inline]
+    #[must_use]
     pub fn round(self) -> Self {
         Self {
-            x: self.x.round(),
-            y: self.y.round(),
+            x: math::round(self.x),
+            y: math::round(self.y),
         }
     }
 
     /// Returns a vector containing the largest integer less than or equal to a number for each
     /// element of `self`.
     #[inline]
+    #[must_use]
     pub fn floor(self) -> Self {
         Self {
-            x: self.x.floor(),
-            y: self.y.floor(),
+            x: math::floor(self.x),
+            y: math::floor(self.y),
         }
     }
 
     /// Returns a vector containing the smallest integer greater than or equal to a number for
     /// each element of `self`.
     #[inline]
+    #[must_use]
     pub fn ceil(self) -> Self {
         Self {
-            x: self.x.ceil(),
-            y: self.y.ceil(),
+            x: math::ceil(self.x),
+            y: math::ceil(self.y),
+        }
+    }
+
+    /// Returns a vector containing the integer part each element of `self`. This means numbers are
+    /// always truncated towards zero.
+    #[inline]
+    #[must_use]
+    pub fn trunc(self) -> Self {
+        Self {
+            x: math::trunc(self.x),
+            y: math::trunc(self.y),
         }
     }
 
@@ -496,6 +574,7 @@
     ///
     /// Note that this is fast but not precise for large numbers.
     #[inline]
+    #[must_use]
     pub fn fract(self) -> Self {
         self - self.floor()
     }
@@ -503,22 +582,25 @@
     /// Returns a vector containing `e^self` (the exponential function) for each element of
     /// `self`.
     #[inline]
+    #[must_use]
     pub fn exp(self) -> Self {
-        Self::new(self.x.exp(), self.y.exp())
+        Self::new(math::exp(self.x), math::exp(self.y))
     }
 
     /// Returns a vector containing each element of `self` raised to the power of `n`.
     #[inline]
+    #[must_use]
     pub fn powf(self, n: f64) -> Self {
-        Self::new(self.x.powf(n), self.y.powf(n))
+        Self::new(math::powf(self.x, n), math::powf(self.y, n))
     }
 
     /// Returns a vector containing the reciprocal `1.0/n` of each element of `self`.
     #[inline]
+    #[must_use]
     pub fn recip(self) -> Self {
         Self {
-            x: self.x.recip(),
-            y: self.y.recip(),
+            x: 1.0 / self.x,
+            y: 1.0 / self.y,
         }
     }
 
@@ -529,6 +611,7 @@
     /// extrapolated.
     #[doc(alias = "mix")]
     #[inline]
+    #[must_use]
     pub fn lerp(self, rhs: Self, s: f64) -> Self {
         self + ((rhs - self) * s)
     }
@@ -543,6 +626,7 @@
     /// For more see
     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
     #[inline]
+    #[must_use]
     pub fn abs_diff_eq(self, rhs: Self, max_abs_diff: f64) -> bool {
         self.sub(rhs).abs().cmple(Self::splat(max_abs_diff)).all()
     }
@@ -553,33 +637,38 @@
     ///
     /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn clamp_length(self, min: f64, max: f64) -> Self {
         glam_assert!(min <= max);
         let length_sq = self.length_squared();
         if length_sq < min * min {
-            self * (length_sq.sqrt().recip() * min)
+            min * (self / math::sqrt(length_sq))
         } else if length_sq > max * max {
-            self * (length_sq.sqrt().recip() * max)
+            max * (self / math::sqrt(length_sq))
         } else {
             self
         }
     }
 
     /// Returns a vector with a length no more than `max`
+    #[inline]
+    #[must_use]
     pub fn clamp_length_max(self, max: f64) -> Self {
         let length_sq = self.length_squared();
         if length_sq > max * max {
-            self * (length_sq.sqrt().recip() * max)
+            max * (self / math::sqrt(length_sq))
         } else {
             self
         }
     }
 
     /// Returns a vector with a length no less than `min`
+    #[inline]
+    #[must_use]
     pub fn clamp_length_min(self, min: f64) -> Self {
         let length_sq = self.length_squared();
         if length_sq < min * min {
-            self * (length_sq.sqrt().recip() * min)
+            min * (self / math::sqrt(length_sq))
         } else {
             self
         }
@@ -593,33 +682,50 @@
     /// and will be heavily dependant on designing algorithms with specific target hardware in
     /// mind.
     #[inline]
+    #[must_use]
     pub fn mul_add(self, a: Self, b: Self) -> Self {
-        Self::new(self.x.mul_add(a.x, b.x), self.y.mul_add(a.y, b.y))
+        Self::new(
+            math::mul_add(self.x, a.x, b.x),
+            math::mul_add(self.y, a.y, b.y),
+        )
     }
 
     /// Creates a 2D vector containing `[angle.cos(), angle.sin()]`. This can be used in
-    /// conjunction with the `rotate` method, e.g. `Vec2::from_angle(PI).rotate(Vec2::Y)` will
-    /// create the vector [-1, 0] and rotate `Vec2::Y` around it returning `-Vec2::Y`.
+    /// conjunction with the [`rotate()`][Self::rotate()] method, e.g.
+    /// `DVec2::from_angle(PI).rotate(DVec2::Y)` will create the vector `[-1, 0]`
+    /// and rotate [`DVec2::Y`] around it returning `-DVec2::Y`.
     #[inline]
+    #[must_use]
     pub fn from_angle(angle: f64) -> Self {
-        let (sin, cos) = angle.sin_cos();
+        let (sin, cos) = math::sin_cos(angle);
         Self { x: cos, y: sin }
     }
 
-    /// Returns the angle (in radians) between `self` and `rhs`.
+    /// Returns the angle (in radians) of this vector in the range `[-π, +π]`.
     ///
-    /// The input vectors do not need to be unit length however they must be non-zero.
+    /// The input does not need to be a unit vector however it must be non-zero.
     #[inline]
-    pub fn angle_between(self, rhs: Self) -> f64 {
-        use crate::FloatEx;
-        let angle =
-            (self.dot(rhs) / (self.length_squared() * rhs.length_squared()).sqrt()).acos_approx();
+    #[must_use]
+    pub fn to_angle(self) -> f64 {
+        math::atan2(self.y, self.x)
+    }
 
-        angle * self.perp_dot(rhs).signum()
+    /// Returns the angle (in radians) between `self` and `rhs` in the range `[-π, +π]`.
+    ///
+    /// The inputs do not need to be unit vectors however they must be non-zero.
+    #[inline]
+    #[must_use]
+    pub fn angle_between(self, rhs: Self) -> f64 {
+        let angle = math::acos_approx(
+            self.dot(rhs) / math::sqrt(self.length_squared() * rhs.length_squared()),
+        );
+
+        angle * math::signum(self.perp_dot(rhs))
     }
 
     /// Returns a vector that is equal to `self` rotated by 90 degrees.
     #[inline]
+    #[must_use]
     pub fn perp(self) -> Self {
         Self {
             x: -self.y,
@@ -633,6 +739,7 @@
     #[doc(alias = "cross")]
     #[doc(alias = "determinant")]
     #[inline]
+    #[must_use]
     pub fn perp_dot(self, rhs: Self) -> f64 {
         (self.x * rhs.y) - (self.y * rhs.x)
     }
@@ -640,8 +747,8 @@
     /// Returns `rhs` rotated by the angle of `self`. If `self` is normalized,
     /// then this just rotation. This is what you usually want. Otherwise,
     /// it will be like a rotation with a multiplication by `self`'s length.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn rotate(self, rhs: Self) -> Self {
         Self {
             x: self.x * rhs.x - self.y * rhs.y,
@@ -651,21 +758,52 @@
 
     /// Casts all elements of `self` to `f32`.
     #[inline]
+    #[must_use]
     pub fn as_vec2(&self) -> crate::Vec2 {
         crate::Vec2::new(self.x as f32, self.y as f32)
     }
 
+    /// Casts all elements of `self` to `i16`.
+    #[inline]
+    #[must_use]
+    pub fn as_i16vec2(&self) -> crate::I16Vec2 {
+        crate::I16Vec2::new(self.x as i16, self.y as i16)
+    }
+
+    /// Casts all elements of `self` to `u16`.
+    #[inline]
+    #[must_use]
+    pub fn as_u16vec2(&self) -> crate::U16Vec2 {
+        crate::U16Vec2::new(self.x as u16, self.y as u16)
+    }
+
     /// Casts all elements of `self` to `i32`.
     #[inline]
+    #[must_use]
     pub fn as_ivec2(&self) -> crate::IVec2 {
         crate::IVec2::new(self.x as i32, self.y as i32)
     }
 
     /// Casts all elements of `self` to `u32`.
     #[inline]
+    #[must_use]
     pub fn as_uvec2(&self) -> crate::UVec2 {
         crate::UVec2::new(self.x as u32, self.y as u32)
     }
+
+    /// Casts all elements of `self` to `i64`.
+    #[inline]
+    #[must_use]
+    pub fn as_i64vec2(&self) -> crate::I64Vec2 {
+        crate::I64Vec2::new(self.x as i64, self.y as i64)
+    }
+
+    /// Casts all elements of `self` to `u64`.
+    #[inline]
+    #[must_use]
+    pub fn as_u64vec2(&self) -> crate::U64Vec2 {
+        crate::U64Vec2::new(self.x as u64, self.y as u64)
+    }
 }
 
 impl Default for DVec2 {
@@ -1054,3 +1192,24 @@
         (v.x, v.y)
     }
 }
+
+impl From<Vec2> for DVec2 {
+    #[inline]
+    fn from(v: Vec2) -> Self {
+        Self::new(f64::from(v.x), f64::from(v.y))
+    }
+}
+
+impl From<IVec2> for DVec2 {
+    #[inline]
+    fn from(v: IVec2) -> Self {
+        Self::new(f64::from(v.x), f64::from(v.y))
+    }
+}
+
+impl From<UVec2> for DVec2 {
+    #[inline]
+    fn from(v: UVec2) -> Self {
+        Self::new(f64::from(v.x), f64::from(v.y))
+    }
+}
diff --git a/src/f64/dvec3.rs b/src/f64/dvec3.rs
index ffdc6f2..a7b0c87 100644
--- a/src/f64/dvec3.rs
+++ b/src/f64/dvec3.rs
@@ -1,18 +1,15 @@
 // Generated from vec.rs.tera template. Edit the template, not the generated file.
 
-use crate::{BVec3, DVec2, DVec4};
+use crate::{f64::math, BVec3, DVec2, DVec4, IVec3, UVec3, Vec3};
 
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
 use core::iter::{Product, Sum};
 use core::{f32, ops::*};
 
-#[cfg(feature = "libm")]
-#[allow(unused_imports)]
-use num_traits::Float;
-
 /// Creates a 3-dimensional vector.
 #[inline(always)]
+#[must_use]
 pub const fn dvec3(x: f64, y: f64, z: f64) -> DVec3 {
     DVec3::new(x, y, z)
 }
@@ -37,25 +34,37 @@
     /// All negative ones.
     pub const NEG_ONE: Self = Self::splat(-1.0);
 
-    /// All NAN.
+    /// All `f64::MIN`.
+    pub const MIN: Self = Self::splat(f64::MIN);
+
+    /// All `f64::MAX`.
+    pub const MAX: Self = Self::splat(f64::MAX);
+
+    /// All `f64::NAN`.
     pub const NAN: Self = Self::splat(f64::NAN);
 
-    /// A unit-length vector pointing along the positive X axis.
+    /// All `f64::INFINITY`.
+    pub const INFINITY: Self = Self::splat(f64::INFINITY);
+
+    /// All `f64::NEG_INFINITY`.
+    pub const NEG_INFINITY: Self = Self::splat(f64::NEG_INFINITY);
+
+    /// A unit vector pointing along the positive X axis.
     pub const X: Self = Self::new(1.0, 0.0, 0.0);
 
-    /// A unit-length vector pointing along the positive Y axis.
+    /// A unit vector pointing along the positive Y axis.
     pub const Y: Self = Self::new(0.0, 1.0, 0.0);
 
-    /// A unit-length vector pointing along the positive Z axis.
+    /// A unit vector pointing along the positive Z axis.
     pub const Z: Self = Self::new(0.0, 0.0, 1.0);
 
-    /// A unit-length vector pointing along the negative X axis.
+    /// A unit vector pointing along the negative X axis.
     pub const NEG_X: Self = Self::new(-1.0, 0.0, 0.0);
 
-    /// A unit-length vector pointing along the negative Y axis.
+    /// A unit vector pointing along the negative Y axis.
     pub const NEG_Y: Self = Self::new(0.0, -1.0, 0.0);
 
-    /// A unit-length vector pointing along the negative Z axis.
+    /// A unit vector pointing along the negative Z axis.
     pub const NEG_Z: Self = Self::new(0.0, 0.0, -1.0);
 
     /// The unit axes.
@@ -63,12 +72,14 @@
 
     /// Creates a new vector.
     #[inline(always)]
+    #[must_use]
     pub const fn new(x: f64, y: f64, z: f64) -> Self {
         Self { x, y, z }
     }
 
     /// Creates a vector with all elements set to `v`.
     #[inline]
+    #[must_use]
     pub const fn splat(v: f64) -> Self {
         Self { x: v, y: v, z: v }
     }
@@ -79,22 +90,25 @@
     /// A true element in the mask uses the corresponding element from `if_true`, and false
     /// uses the element from `if_false`.
     #[inline]
+    #[must_use]
     pub fn select(mask: BVec3, if_true: Self, if_false: Self) -> Self {
         Self {
-            x: if mask.x { if_true.x } else { if_false.x },
-            y: if mask.y { if_true.y } else { if_false.y },
-            z: if mask.z { if_true.z } else { if_false.z },
+            x: if mask.test(0) { if_true.x } else { if_false.x },
+            y: if mask.test(1) { if_true.y } else { if_false.y },
+            z: if mask.test(2) { if_true.z } else { if_false.z },
         }
     }
 
     /// Creates a new vector from an array.
     #[inline]
+    #[must_use]
     pub const fn from_array(a: [f64; 3]) -> Self {
         Self::new(a[0], a[1], a[2])
     }
 
     /// `[x, y, z]`
     #[inline]
+    #[must_use]
     pub const fn to_array(&self) -> [f64; 3] {
         [self.x, self.y, self.z]
     }
@@ -105,6 +119,7 @@
     ///
     /// Panics if `slice` is less than 3 elements long.
     #[inline]
+    #[must_use]
     pub const fn from_slice(slice: &[f64]) -> Self {
         Self::new(slice[0], slice[1], slice[2])
     }
@@ -124,6 +139,7 @@
     /// Internal method for creating a 3D vector from a 4D vector, discarding `w`.
     #[allow(dead_code)]
     #[inline]
+    #[must_use]
     pub(crate) fn from_vec4(v: DVec4) -> Self {
         Self {
             x: v.x,
@@ -134,14 +150,16 @@
 
     /// Creates a 4D vector from `self` and the given `w` value.
     #[inline]
+    #[must_use]
     pub fn extend(self, w: f64) -> DVec4 {
         DVec4::new(self.x, self.y, self.z, w)
     }
 
     /// Creates a 2D vector from the `x` and `y` elements of `self`, discarding `z`.
     ///
-    /// Truncation may also be performed by using `self.xy()` or `DVec2::from()`.
+    /// Truncation may also be performed by using [`self.xy()`][crate::swizzles::Vec3Swizzles::xy()].
     #[inline]
+    #[must_use]
     pub fn truncate(self) -> DVec2 {
         use crate::swizzles::Vec3Swizzles;
         self.xy()
@@ -149,18 +167,21 @@
 
     /// Computes the dot product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn dot(self, rhs: Self) -> f64 {
         (self.x * rhs.x) + (self.y * rhs.y) + (self.z * rhs.z)
     }
 
     /// Returns a vector where every component is the dot product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn dot_into_vec(self, rhs: Self) -> Self {
         Self::splat(self.dot(rhs))
     }
 
     /// Computes the cross product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn cross(self, rhs: Self) -> Self {
         Self {
             x: self.y * rhs.z - rhs.y * self.z,
@@ -173,6 +194,7 @@
     ///
     /// In other words this computes `[self.x.min(rhs.x), self.y.min(rhs.y), ..]`.
     #[inline]
+    #[must_use]
     pub fn min(self, rhs: Self) -> Self {
         Self {
             x: self.x.min(rhs.x),
@@ -185,6 +207,7 @@
     ///
     /// In other words this computes `[self.x.max(rhs.x), self.y.max(rhs.y), ..]`.
     #[inline]
+    #[must_use]
     pub fn max(self, rhs: Self) -> Self {
         Self {
             x: self.x.max(rhs.x),
@@ -201,6 +224,7 @@
     ///
     /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn clamp(self, min: Self, max: Self) -> Self {
         glam_assert!(min.cmple(max).all(), "clamp: expected min <= max");
         self.max(min).min(max)
@@ -210,6 +234,7 @@
     ///
     /// In other words this computes `min(x, y, ..)`.
     #[inline]
+    #[must_use]
     pub fn min_element(self) -> f64 {
         self.x.min(self.y.min(self.z))
     }
@@ -218,6 +243,7 @@
     ///
     /// In other words this computes `max(x, y, ..)`.
     #[inline]
+    #[must_use]
     pub fn max_element(self) -> f64 {
         self.x.max(self.y.max(self.z))
     }
@@ -228,6 +254,7 @@
     /// In other words, this computes `[self.x == rhs.x, self.y == rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpeq(self, rhs: Self) -> BVec3 {
         BVec3::new(self.x.eq(&rhs.x), self.y.eq(&rhs.y), self.z.eq(&rhs.z))
     }
@@ -238,6 +265,7 @@
     /// In other words this computes `[self.x != rhs.x, self.y != rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpne(self, rhs: Self) -> BVec3 {
         BVec3::new(self.x.ne(&rhs.x), self.y.ne(&rhs.y), self.z.ne(&rhs.z))
     }
@@ -248,6 +276,7 @@
     /// In other words this computes `[self.x >= rhs.x, self.y >= rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpge(self, rhs: Self) -> BVec3 {
         BVec3::new(self.x.ge(&rhs.x), self.y.ge(&rhs.y), self.z.ge(&rhs.z))
     }
@@ -258,6 +287,7 @@
     /// In other words this computes `[self.x > rhs.x, self.y > rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpgt(self, rhs: Self) -> BVec3 {
         BVec3::new(self.x.gt(&rhs.x), self.y.gt(&rhs.y), self.z.gt(&rhs.z))
     }
@@ -268,6 +298,7 @@
     /// In other words this computes `[self.x <= rhs.x, self.y <= rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmple(self, rhs: Self) -> BVec3 {
         BVec3::new(self.x.le(&rhs.x), self.y.le(&rhs.y), self.z.le(&rhs.z))
     }
@@ -278,17 +309,19 @@
     /// In other words this computes `[self.x < rhs.x, self.y < rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmplt(self, rhs: Self) -> BVec3 {
         BVec3::new(self.x.lt(&rhs.x), self.y.lt(&rhs.y), self.z.lt(&rhs.z))
     }
 
     /// Returns a vector containing the absolute value of each element of `self`.
     #[inline]
+    #[must_use]
     pub fn abs(self) -> Self {
         Self {
-            x: self.x.abs(),
-            y: self.y.abs(),
-            z: self.z.abs(),
+            x: math::abs(self.x),
+            y: math::abs(self.y),
+            z: math::abs(self.z),
         }
     }
 
@@ -298,21 +331,23 @@
     /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
     /// - `NAN` if the number is `NAN`
     #[inline]
+    #[must_use]
     pub fn signum(self) -> Self {
         Self {
-            x: self.x.signum(),
-            y: self.y.signum(),
-            z: self.z.signum(),
+            x: math::signum(self.x),
+            y: math::signum(self.y),
+            z: math::signum(self.z),
         }
     }
 
     /// Returns a vector with signs of `rhs` and the magnitudes of `self`.
     #[inline]
+    #[must_use]
     pub fn copysign(self, rhs: Self) -> Self {
         Self {
-            x: self.x.copysign(rhs.x),
-            y: self.y.copysign(rhs.y),
-            z: self.z.copysign(rhs.z),
+            x: math::copysign(self.x, rhs.x),
+            y: math::copysign(self.y, rhs.y),
+            z: math::copysign(self.z, rhs.z),
         }
     }
 
@@ -321,6 +356,7 @@
     /// A negative element results in a `1` bit and a positive element in a `0` bit.  Element `x` goes
     /// into the first lowest bit, element `y` into the second, etc.
     #[inline]
+    #[must_use]
     pub fn is_negative_bitmask(self) -> u32 {
         (self.x.is_sign_negative() as u32)
             | (self.y.is_sign_negative() as u32) << 1
@@ -330,12 +366,14 @@
     /// Returns `true` if, and only if, all elements are finite.  If any element is either
     /// `NaN`, positive or negative infinity, this will return `false`.
     #[inline]
+    #[must_use]
     pub fn is_finite(self) -> bool {
         self.x.is_finite() && self.y.is_finite() && self.z.is_finite()
     }
 
     /// Returns `true` if any elements are `NaN`.
     #[inline]
+    #[must_use]
     pub fn is_nan(self) -> bool {
         self.x.is_nan() || self.y.is_nan() || self.z.is_nan()
     }
@@ -344,6 +382,7 @@
     ///
     /// In other words, this computes `[x.is_nan(), y.is_nan(), z.is_nan(), w.is_nan()]`.
     #[inline]
+    #[must_use]
     pub fn is_nan_mask(self) -> BVec3 {
         BVec3::new(self.x.is_nan(), self.y.is_nan(), self.z.is_nan())
     }
@@ -351,8 +390,9 @@
     /// Computes the length of `self`.
     #[doc(alias = "magnitude")]
     #[inline]
+    #[must_use]
     pub fn length(self) -> f64 {
-        self.dot(self).sqrt()
+        math::sqrt(self.dot(self))
     }
 
     /// Computes the squared length of `self`.
@@ -360,6 +400,7 @@
     /// This is faster than `length()` as it avoids a square root operation.
     #[doc(alias = "magnitude2")]
     #[inline]
+    #[must_use]
     pub fn length_squared(self) -> f64 {
         self.dot(self)
     }
@@ -368,33 +409,60 @@
     ///
     /// For valid results, `self` must _not_ be of length zero.
     #[inline]
+    #[must_use]
     pub fn length_recip(self) -> f64 {
         self.length().recip()
     }
 
     /// Computes the Euclidean distance between two points in space.
     #[inline]
+    #[must_use]
     pub fn distance(self, rhs: Self) -> f64 {
         (self - rhs).length()
     }
 
     /// Compute the squared euclidean distance between two points in space.
     #[inline]
+    #[must_use]
     pub fn distance_squared(self, rhs: Self) -> f64 {
         (self - rhs).length_squared()
     }
 
+    /// Returns the element-wise quotient of [Euclidean division] of `self` by `rhs`.
+    #[inline]
+    #[must_use]
+    pub fn div_euclid(self, rhs: Self) -> Self {
+        Self::new(
+            math::div_euclid(self.x, rhs.x),
+            math::div_euclid(self.y, rhs.y),
+            math::div_euclid(self.z, rhs.z),
+        )
+    }
+
+    /// Returns the element-wise remainder of [Euclidean division] of `self` by `rhs`.
+    ///
+    /// [Euclidean division]: f64::rem_euclid
+    #[inline]
+    #[must_use]
+    pub fn rem_euclid(self, rhs: Self) -> Self {
+        Self::new(
+            math::rem_euclid(self.x, rhs.x),
+            math::rem_euclid(self.y, rhs.y),
+            math::rem_euclid(self.z, rhs.z),
+        )
+    }
+
     /// Returns `self` normalized to length 1.0.
     ///
     /// For valid results, `self` must _not_ be of length zero, nor very close to zero.
     ///
-    /// See also [`Self::try_normalize`] and [`Self::normalize_or_zero`].
+    /// See also [`Self::try_normalize()`] and [`Self::normalize_or_zero()`].
     ///
     /// Panics
     ///
     /// Will panic if `self` is zero length when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn normalize(self) -> Self {
         #[allow(clippy::let_and_return)]
         let normalized = self.mul(self.length_recip());
@@ -407,9 +475,9 @@
     /// In particular, if the input is zero (or very close to zero), or non-finite,
     /// the result of this operation will be `None`.
     ///
-    /// See also [`Self::normalize_or_zero`].
-    #[must_use]
+    /// See also [`Self::normalize_or_zero()`].
     #[inline]
+    #[must_use]
     pub fn try_normalize(self) -> Option<Self> {
         let rcp = self.length_recip();
         if rcp.is_finite() && rcp > 0.0 {
@@ -424,9 +492,9 @@
     /// In particular, if the input is zero (or very close to zero), or non-finite,
     /// the result of this operation will be zero.
     ///
-    /// See also [`Self::try_normalize`].
-    #[must_use]
+    /// See also [`Self::try_normalize()`].
     #[inline]
+    #[must_use]
     pub fn normalize_or_zero(self) -> Self {
         let rcp = self.length_recip();
         if rcp.is_finite() && rcp > 0.0 {
@@ -440,9 +508,10 @@
     ///
     /// Uses a precision threshold of `1e-6`.
     #[inline]
+    #[must_use]
     pub fn is_normalized(self) -> bool {
         // TODO: do something with epsilon
-        (self.length_squared() - 1.0).abs() <= 1e-4
+        math::abs(self.length_squared() - 1.0) <= 1e-4
     }
 
     /// Returns the vector projection of `self` onto `rhs`.
@@ -452,8 +521,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` is zero length when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn project_onto(self, rhs: Self) -> Self {
         let other_len_sq_rcp = rhs.dot(rhs).recip();
         glam_assert!(other_len_sq_rcp.is_finite());
@@ -470,8 +539,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` has a length of zero when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn reject_from(self, rhs: Self) -> Self {
         self - self.project_onto(rhs)
     }
@@ -483,8 +552,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` is not normalized when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn project_onto_normalized(self, rhs: Self) -> Self {
         glam_assert!(rhs.is_normalized());
         rhs * self.dot(rhs)
@@ -500,8 +569,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` is not normalized when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn reject_from_normalized(self, rhs: Self) -> Self {
         self - self.project_onto_normalized(rhs)
     }
@@ -509,33 +578,48 @@
     /// Returns a vector containing the nearest integer to a number for each element of `self`.
     /// Round half-way cases away from 0.0.
     #[inline]
+    #[must_use]
     pub fn round(self) -> Self {
         Self {
-            x: self.x.round(),
-            y: self.y.round(),
-            z: self.z.round(),
+            x: math::round(self.x),
+            y: math::round(self.y),
+            z: math::round(self.z),
         }
     }
 
     /// Returns a vector containing the largest integer less than or equal to a number for each
     /// element of `self`.
     #[inline]
+    #[must_use]
     pub fn floor(self) -> Self {
         Self {
-            x: self.x.floor(),
-            y: self.y.floor(),
-            z: self.z.floor(),
+            x: math::floor(self.x),
+            y: math::floor(self.y),
+            z: math::floor(self.z),
         }
     }
 
     /// Returns a vector containing the smallest integer greater than or equal to a number for
     /// each element of `self`.
     #[inline]
+    #[must_use]
     pub fn ceil(self) -> Self {
         Self {
-            x: self.x.ceil(),
-            y: self.y.ceil(),
-            z: self.z.ceil(),
+            x: math::ceil(self.x),
+            y: math::ceil(self.y),
+            z: math::ceil(self.z),
+        }
+    }
+
+    /// Returns a vector containing the integer part each element of `self`. This means numbers are
+    /// always truncated towards zero.
+    #[inline]
+    #[must_use]
+    pub fn trunc(self) -> Self {
+        Self {
+            x: math::trunc(self.x),
+            y: math::trunc(self.y),
+            z: math::trunc(self.z),
         }
     }
 
@@ -544,6 +628,7 @@
     ///
     /// Note that this is fast but not precise for large numbers.
     #[inline]
+    #[must_use]
     pub fn fract(self) -> Self {
         self - self.floor()
     }
@@ -551,23 +636,30 @@
     /// Returns a vector containing `e^self` (the exponential function) for each element of
     /// `self`.
     #[inline]
+    #[must_use]
     pub fn exp(self) -> Self {
-        Self::new(self.x.exp(), self.y.exp(), self.z.exp())
+        Self::new(math::exp(self.x), math::exp(self.y), math::exp(self.z))
     }
 
     /// Returns a vector containing each element of `self` raised to the power of `n`.
     #[inline]
+    #[must_use]
     pub fn powf(self, n: f64) -> Self {
-        Self::new(self.x.powf(n), self.y.powf(n), self.z.powf(n))
+        Self::new(
+            math::powf(self.x, n),
+            math::powf(self.y, n),
+            math::powf(self.z, n),
+        )
     }
 
     /// Returns a vector containing the reciprocal `1.0/n` of each element of `self`.
     #[inline]
+    #[must_use]
     pub fn recip(self) -> Self {
         Self {
-            x: self.x.recip(),
-            y: self.y.recip(),
-            z: self.z.recip(),
+            x: 1.0 / self.x,
+            y: 1.0 / self.y,
+            z: 1.0 / self.z,
         }
     }
 
@@ -578,6 +670,7 @@
     /// extrapolated.
     #[doc(alias = "mix")]
     #[inline]
+    #[must_use]
     pub fn lerp(self, rhs: Self, s: f64) -> Self {
         self + ((rhs - self) * s)
     }
@@ -592,6 +685,7 @@
     /// For more see
     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
     #[inline]
+    #[must_use]
     pub fn abs_diff_eq(self, rhs: Self, max_abs_diff: f64) -> bool {
         self.sub(rhs).abs().cmple(Self::splat(max_abs_diff)).all()
     }
@@ -602,33 +696,38 @@
     ///
     /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn clamp_length(self, min: f64, max: f64) -> Self {
         glam_assert!(min <= max);
         let length_sq = self.length_squared();
         if length_sq < min * min {
-            self * (length_sq.sqrt().recip() * min)
+            min * (self / math::sqrt(length_sq))
         } else if length_sq > max * max {
-            self * (length_sq.sqrt().recip() * max)
+            max * (self / math::sqrt(length_sq))
         } else {
             self
         }
     }
 
     /// Returns a vector with a length no more than `max`
+    #[inline]
+    #[must_use]
     pub fn clamp_length_max(self, max: f64) -> Self {
         let length_sq = self.length_squared();
         if length_sq > max * max {
-            self * (length_sq.sqrt().recip() * max)
+            max * (self / math::sqrt(length_sq))
         } else {
             self
         }
     }
 
     /// Returns a vector with a length no less than `min`
+    #[inline]
+    #[must_use]
     pub fn clamp_length_min(self, min: f64) -> Self {
         let length_sq = self.length_squared();
         if length_sq < min * min {
-            self * (length_sq.sqrt().recip() * min)
+            min * (self / math::sqrt(length_sq))
         } else {
             self
         }
@@ -642,74 +741,74 @@
     /// and will be heavily dependant on designing algorithms with specific target hardware in
     /// mind.
     #[inline]
+    #[must_use]
     pub fn mul_add(self, a: Self, b: Self) -> Self {
         Self::new(
-            self.x.mul_add(a.x, b.x),
-            self.y.mul_add(a.y, b.y),
-            self.z.mul_add(a.z, b.z),
+            math::mul_add(self.x, a.x, b.x),
+            math::mul_add(self.y, a.y, b.y),
+            math::mul_add(self.z, a.z, b.z),
         )
     }
 
     /// Returns the angle (in radians) between two vectors.
     ///
-    /// The input vectors do not need to be unit length however they must be non-zero.
+    /// The inputs do not need to be unit vectors however they must be non-zero.
     #[inline]
+    #[must_use]
     pub fn angle_between(self, rhs: Self) -> f64 {
-        use crate::FloatEx;
-        self.dot(rhs)
-            .div(self.length_squared().mul(rhs.length_squared()).sqrt())
-            .acos_approx()
+        math::acos_approx(
+            self.dot(rhs)
+                .div(math::sqrt(self.length_squared().mul(rhs.length_squared()))),
+        )
     }
 
     /// Returns some vector that is orthogonal to the given one.
     ///
     /// The input vector must be finite and non-zero.
     ///
-    /// The output vector is not necessarily unit-length.
-    /// For that use [`Self::any_orthonormal_vector`] instead.
+    /// The output vector is not necessarily unit length. For that use
+    /// [`Self::any_orthonormal_vector()`] instead.
     #[inline]
+    #[must_use]
     pub fn any_orthogonal_vector(&self) -> Self {
         // This can probably be optimized
-        if self.x.abs() > self.y.abs() {
+        if math::abs(self.x) > math::abs(self.y) {
             Self::new(-self.z, 0.0, self.x) // self.cross(Self::Y)
         } else {
             Self::new(0.0, self.z, -self.y) // self.cross(Self::X)
         }
     }
 
-    /// Returns any unit-length vector that is orthogonal to the given one.
-    /// The input vector must be finite and non-zero.
+    /// Returns any unit vector that is orthogonal to the given one.
+    ///
+    /// The input vector must be unit length.
     ///
     /// # Panics
     ///
     /// Will panic if `self` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn any_orthonormal_vector(&self) -> Self {
         glam_assert!(self.is_normalized());
         // From https://graphics.pixar.com/library/OrthonormalB/paper.pdf
-        #[cfg(feature = "std")]
-        let sign = (1.0_f64).copysign(self.z);
-        #[cfg(not(feature = "std"))]
-        let sign = self.z.signum();
+        let sign = math::signum(self.z);
         let a = -1.0 / (sign + self.z);
         let b = self.x * self.y * a;
         Self::new(b, sign + self.y * self.y * a, -self.y)
     }
 
-    /// Given a unit-length vector return two other vectors that together form an orthonormal
-    /// basis.  That is, all three vectors are orthogonal to each other and are normalized.
+    /// Given a unit vector return two other vectors that together form an orthonormal
+    /// basis. That is, all three vectors are orthogonal to each other and are normalized.
     ///
     /// # Panics
     ///
     /// Will panic if `self` is not normalized when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn any_orthonormal_pair(&self) -> (Self, Self) {
         glam_assert!(self.is_normalized());
         // From https://graphics.pixar.com/library/OrthonormalB/paper.pdf
-        #[cfg(feature = "std")]
-        let sign = (1.0_f64).copysign(self.z);
-        #[cfg(not(feature = "std"))]
-        let sign = self.z.signum();
+        let sign = math::signum(self.z);
         let a = -1.0 / (sign + self.z);
         let b = self.x * self.y * a;
         (
@@ -720,27 +819,59 @@
 
     /// Casts all elements of `self` to `f32`.
     #[inline]
+    #[must_use]
     pub fn as_vec3(&self) -> crate::Vec3 {
         crate::Vec3::new(self.x as f32, self.y as f32, self.z as f32)
     }
 
     /// Casts all elements of `self` to `f32`.
     #[inline]
+    #[must_use]
     pub fn as_vec3a(&self) -> crate::Vec3A {
         crate::Vec3A::new(self.x as f32, self.y as f32, self.z as f32)
     }
 
+    /// Casts all elements of `self` to `i16`.
+    #[inline]
+    #[must_use]
+    pub fn as_i16vec3(&self) -> crate::I16Vec3 {
+        crate::I16Vec3::new(self.x as i16, self.y as i16, self.z as i16)
+    }
+
+    /// Casts all elements of `self` to `u16`.
+    #[inline]
+    #[must_use]
+    pub fn as_u16vec3(&self) -> crate::U16Vec3 {
+        crate::U16Vec3::new(self.x as u16, self.y as u16, self.z as u16)
+    }
+
     /// Casts all elements of `self` to `i32`.
     #[inline]
+    #[must_use]
     pub fn as_ivec3(&self) -> crate::IVec3 {
         crate::IVec3::new(self.x as i32, self.y as i32, self.z as i32)
     }
 
     /// Casts all elements of `self` to `u32`.
     #[inline]
+    #[must_use]
     pub fn as_uvec3(&self) -> crate::UVec3 {
         crate::UVec3::new(self.x as u32, self.y as u32, self.z as u32)
     }
+
+    /// Casts all elements of `self` to `i64`.
+    #[inline]
+    #[must_use]
+    pub fn as_i64vec3(&self) -> crate::I64Vec3 {
+        crate::I64Vec3::new(self.x as i64, self.y as i64, self.z as i64)
+    }
+
+    /// Casts all elements of `self` to `u64`.
+    #[inline]
+    #[must_use]
+    pub fn as_u64vec3(&self) -> crate::U64Vec3 {
+        crate::U64Vec3::new(self.x as u64, self.y as u64, self.z as u64)
+    }
 }
 
 impl Default for DVec3 {
@@ -1165,3 +1296,24 @@
         Self::new(v.x, v.y, z)
     }
 }
+
+impl From<Vec3> for DVec3 {
+    #[inline]
+    fn from(v: Vec3) -> Self {
+        Self::new(f64::from(v.x), f64::from(v.y), f64::from(v.z))
+    }
+}
+
+impl From<IVec3> for DVec3 {
+    #[inline]
+    fn from(v: IVec3) -> Self {
+        Self::new(f64::from(v.x), f64::from(v.y), f64::from(v.z))
+    }
+}
+
+impl From<UVec3> for DVec3 {
+    #[inline]
+    fn from(v: UVec3) -> Self {
+        Self::new(f64::from(v.x), f64::from(v.y), f64::from(v.z))
+    }
+}
diff --git a/src/f64/dvec4.rs b/src/f64/dvec4.rs
index de08d42..acd9ac5 100644
--- a/src/f64/dvec4.rs
+++ b/src/f64/dvec4.rs
@@ -1,18 +1,15 @@
 // Generated from vec.rs.tera template. Edit the template, not the generated file.
 
-use crate::{BVec4, DVec2, DVec3};
+use crate::{f64::math, BVec4, DVec2, DVec3, IVec4, UVec4, Vec4};
 
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
 use core::iter::{Product, Sum};
 use core::{f32, ops::*};
 
-#[cfg(feature = "libm")]
-#[allow(unused_imports)]
-use num_traits::Float;
-
 /// Creates a 4-dimensional vector.
 #[inline(always)]
+#[must_use]
 pub const fn dvec4(x: f64, y: f64, z: f64, w: f64) -> DVec4 {
     DVec4::new(x, y, z, w)
 }
@@ -39,31 +36,43 @@
     /// All negative ones.
     pub const NEG_ONE: Self = Self::splat(-1.0);
 
-    /// All NAN.
+    /// All `f64::MIN`.
+    pub const MIN: Self = Self::splat(f64::MIN);
+
+    /// All `f64::MAX`.
+    pub const MAX: Self = Self::splat(f64::MAX);
+
+    /// All `f64::NAN`.
     pub const NAN: Self = Self::splat(f64::NAN);
 
-    /// A unit-length vector pointing along the positive X axis.
+    /// All `f64::INFINITY`.
+    pub const INFINITY: Self = Self::splat(f64::INFINITY);
+
+    /// All `f64::NEG_INFINITY`.
+    pub const NEG_INFINITY: Self = Self::splat(f64::NEG_INFINITY);
+
+    /// A unit vector pointing along the positive X axis.
     pub const X: Self = Self::new(1.0, 0.0, 0.0, 0.0);
 
-    /// A unit-length vector pointing along the positive Y axis.
+    /// A unit vector pointing along the positive Y axis.
     pub const Y: Self = Self::new(0.0, 1.0, 0.0, 0.0);
 
-    /// A unit-length vector pointing along the positive Z axis.
+    /// A unit vector pointing along the positive Z axis.
     pub const Z: Self = Self::new(0.0, 0.0, 1.0, 0.0);
 
-    /// A unit-length vector pointing along the positive W axis.
+    /// A unit vector pointing along the positive W axis.
     pub const W: Self = Self::new(0.0, 0.0, 0.0, 1.0);
 
-    /// A unit-length vector pointing along the negative X axis.
+    /// A unit vector pointing along the negative X axis.
     pub const NEG_X: Self = Self::new(-1.0, 0.0, 0.0, 0.0);
 
-    /// A unit-length vector pointing along the negative Y axis.
+    /// A unit vector pointing along the negative Y axis.
     pub const NEG_Y: Self = Self::new(0.0, -1.0, 0.0, 0.0);
 
-    /// A unit-length vector pointing along the negative Z axis.
+    /// A unit vector pointing along the negative Z axis.
     pub const NEG_Z: Self = Self::new(0.0, 0.0, -1.0, 0.0);
 
-    /// A unit-length vector pointing along the negative W axis.
+    /// A unit vector pointing along the negative W axis.
     pub const NEG_W: Self = Self::new(0.0, 0.0, 0.0, -1.0);
 
     /// The unit axes.
@@ -71,12 +80,14 @@
 
     /// Creates a new vector.
     #[inline(always)]
+    #[must_use]
     pub const fn new(x: f64, y: f64, z: f64, w: f64) -> Self {
         Self { x, y, z, w }
     }
 
     /// Creates a vector with all elements set to `v`.
     #[inline]
+    #[must_use]
     pub const fn splat(v: f64) -> Self {
         Self {
             x: v,
@@ -95,23 +106,26 @@
     /// A true element in the mask uses the corresponding element from `if_true`, and false
     /// uses the element from `if_false`.
     #[inline]
+    #[must_use]
     pub fn select(mask: BVec4, if_true: Self, if_false: Self) -> Self {
         Self {
-            x: if mask.x { if_true.x } else { if_false.x },
-            y: if mask.y { if_true.y } else { if_false.y },
-            z: if mask.z { if_true.z } else { if_false.z },
-            w: if mask.w { if_true.w } else { if_false.w },
+            x: if mask.test(0) { if_true.x } else { if_false.x },
+            y: if mask.test(1) { if_true.y } else { if_false.y },
+            z: if mask.test(2) { if_true.z } else { if_false.z },
+            w: if mask.test(3) { if_true.w } else { if_false.w },
         }
     }
 
     /// Creates a new vector from an array.
     #[inline]
+    #[must_use]
     pub const fn from_array(a: [f64; 4]) -> Self {
         Self::new(a[0], a[1], a[2], a[3])
     }
 
     /// `[x, y, z, w]`
     #[inline]
+    #[must_use]
     pub const fn to_array(&self) -> [f64; 4] {
         [self.x, self.y, self.z, self.w]
     }
@@ -122,6 +136,7 @@
     ///
     /// Panics if `slice` is less than 4 elements long.
     #[inline]
+    #[must_use]
     pub const fn from_slice(slice: &[f64]) -> Self {
         Self::new(slice[0], slice[1], slice[2], slice[3])
     }
@@ -139,10 +154,11 @@
         slice[3] = self.w;
     }
 
-    /// Creates a 2D vector from the `x`, `y` and `z` elements of `self`, discarding `w`.
+    /// Creates a 3D vector from the `x`, `y` and `z` elements of `self`, discarding `w`.
     ///
-    /// Truncation to `DVec3` may also be performed by using `self.xyz()` or `DVec3::from()`.
+    /// Truncation to [`DVec3`] may also be performed by using [`self.xyz()`][crate::swizzles::Vec4Swizzles::xyz()].
     #[inline]
+    #[must_use]
     pub fn truncate(self) -> DVec3 {
         use crate::swizzles::Vec4Swizzles;
         self.xyz()
@@ -150,12 +166,14 @@
 
     /// Computes the dot product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn dot(self, rhs: Self) -> f64 {
         (self.x * rhs.x) + (self.y * rhs.y) + (self.z * rhs.z) + (self.w * rhs.w)
     }
 
     /// Returns a vector where every component is the dot product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn dot_into_vec(self, rhs: Self) -> Self {
         Self::splat(self.dot(rhs))
     }
@@ -164,6 +182,7 @@
     ///
     /// In other words this computes `[self.x.min(rhs.x), self.y.min(rhs.y), ..]`.
     #[inline]
+    #[must_use]
     pub fn min(self, rhs: Self) -> Self {
         Self {
             x: self.x.min(rhs.x),
@@ -177,6 +196,7 @@
     ///
     /// In other words this computes `[self.x.max(rhs.x), self.y.max(rhs.y), ..]`.
     #[inline]
+    #[must_use]
     pub fn max(self, rhs: Self) -> Self {
         Self {
             x: self.x.max(rhs.x),
@@ -194,6 +214,7 @@
     ///
     /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn clamp(self, min: Self, max: Self) -> Self {
         glam_assert!(min.cmple(max).all(), "clamp: expected min <= max");
         self.max(min).min(max)
@@ -203,6 +224,7 @@
     ///
     /// In other words this computes `min(x, y, ..)`.
     #[inline]
+    #[must_use]
     pub fn min_element(self) -> f64 {
         self.x.min(self.y.min(self.z.min(self.w)))
     }
@@ -211,6 +233,7 @@
     ///
     /// In other words this computes `max(x, y, ..)`.
     #[inline]
+    #[must_use]
     pub fn max_element(self) -> f64 {
         self.x.max(self.y.max(self.z.max(self.w)))
     }
@@ -221,6 +244,7 @@
     /// In other words, this computes `[self.x == rhs.x, self.y == rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpeq(self, rhs: Self) -> BVec4 {
         BVec4::new(
             self.x.eq(&rhs.x),
@@ -236,6 +260,7 @@
     /// In other words this computes `[self.x != rhs.x, self.y != rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpne(self, rhs: Self) -> BVec4 {
         BVec4::new(
             self.x.ne(&rhs.x),
@@ -251,6 +276,7 @@
     /// In other words this computes `[self.x >= rhs.x, self.y >= rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpge(self, rhs: Self) -> BVec4 {
         BVec4::new(
             self.x.ge(&rhs.x),
@@ -266,6 +292,7 @@
     /// In other words this computes `[self.x > rhs.x, self.y > rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpgt(self, rhs: Self) -> BVec4 {
         BVec4::new(
             self.x.gt(&rhs.x),
@@ -281,6 +308,7 @@
     /// In other words this computes `[self.x <= rhs.x, self.y <= rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmple(self, rhs: Self) -> BVec4 {
         BVec4::new(
             self.x.le(&rhs.x),
@@ -296,6 +324,7 @@
     /// In other words this computes `[self.x < rhs.x, self.y < rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmplt(self, rhs: Self) -> BVec4 {
         BVec4::new(
             self.x.lt(&rhs.x),
@@ -307,12 +336,13 @@
 
     /// Returns a vector containing the absolute value of each element of `self`.
     #[inline]
+    #[must_use]
     pub fn abs(self) -> Self {
         Self {
-            x: self.x.abs(),
-            y: self.y.abs(),
-            z: self.z.abs(),
-            w: self.w.abs(),
+            x: math::abs(self.x),
+            y: math::abs(self.y),
+            z: math::abs(self.z),
+            w: math::abs(self.w),
         }
     }
 
@@ -322,23 +352,25 @@
     /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
     /// - `NAN` if the number is `NAN`
     #[inline]
+    #[must_use]
     pub fn signum(self) -> Self {
         Self {
-            x: self.x.signum(),
-            y: self.y.signum(),
-            z: self.z.signum(),
-            w: self.w.signum(),
+            x: math::signum(self.x),
+            y: math::signum(self.y),
+            z: math::signum(self.z),
+            w: math::signum(self.w),
         }
     }
 
     /// Returns a vector with signs of `rhs` and the magnitudes of `self`.
     #[inline]
+    #[must_use]
     pub fn copysign(self, rhs: Self) -> Self {
         Self {
-            x: self.x.copysign(rhs.x),
-            y: self.y.copysign(rhs.y),
-            z: self.z.copysign(rhs.z),
-            w: self.w.copysign(rhs.w),
+            x: math::copysign(self.x, rhs.x),
+            y: math::copysign(self.y, rhs.y),
+            z: math::copysign(self.z, rhs.z),
+            w: math::copysign(self.w, rhs.w),
         }
     }
 
@@ -347,6 +379,7 @@
     /// A negative element results in a `1` bit and a positive element in a `0` bit.  Element `x` goes
     /// into the first lowest bit, element `y` into the second, etc.
     #[inline]
+    #[must_use]
     pub fn is_negative_bitmask(self) -> u32 {
         (self.x.is_sign_negative() as u32)
             | (self.y.is_sign_negative() as u32) << 1
@@ -357,12 +390,14 @@
     /// Returns `true` if, and only if, all elements are finite.  If any element is either
     /// `NaN`, positive or negative infinity, this will return `false`.
     #[inline]
+    #[must_use]
     pub fn is_finite(self) -> bool {
         self.x.is_finite() && self.y.is_finite() && self.z.is_finite() && self.w.is_finite()
     }
 
     /// Returns `true` if any elements are `NaN`.
     #[inline]
+    #[must_use]
     pub fn is_nan(self) -> bool {
         self.x.is_nan() || self.y.is_nan() || self.z.is_nan() || self.w.is_nan()
     }
@@ -371,6 +406,7 @@
     ///
     /// In other words, this computes `[x.is_nan(), y.is_nan(), z.is_nan(), w.is_nan()]`.
     #[inline]
+    #[must_use]
     pub fn is_nan_mask(self) -> BVec4 {
         BVec4::new(
             self.x.is_nan(),
@@ -383,8 +419,9 @@
     /// Computes the length of `self`.
     #[doc(alias = "magnitude")]
     #[inline]
+    #[must_use]
     pub fn length(self) -> f64 {
-        self.dot(self).sqrt()
+        math::sqrt(self.dot(self))
     }
 
     /// Computes the squared length of `self`.
@@ -392,6 +429,7 @@
     /// This is faster than `length()` as it avoids a square root operation.
     #[doc(alias = "magnitude2")]
     #[inline]
+    #[must_use]
     pub fn length_squared(self) -> f64 {
         self.dot(self)
     }
@@ -400,33 +438,62 @@
     ///
     /// For valid results, `self` must _not_ be of length zero.
     #[inline]
+    #[must_use]
     pub fn length_recip(self) -> f64 {
         self.length().recip()
     }
 
     /// Computes the Euclidean distance between two points in space.
     #[inline]
+    #[must_use]
     pub fn distance(self, rhs: Self) -> f64 {
         (self - rhs).length()
     }
 
     /// Compute the squared euclidean distance between two points in space.
     #[inline]
+    #[must_use]
     pub fn distance_squared(self, rhs: Self) -> f64 {
         (self - rhs).length_squared()
     }
 
+    /// Returns the element-wise quotient of [Euclidean division] of `self` by `rhs`.
+    #[inline]
+    #[must_use]
+    pub fn div_euclid(self, rhs: Self) -> Self {
+        Self::new(
+            math::div_euclid(self.x, rhs.x),
+            math::div_euclid(self.y, rhs.y),
+            math::div_euclid(self.z, rhs.z),
+            math::div_euclid(self.w, rhs.w),
+        )
+    }
+
+    /// Returns the element-wise remainder of [Euclidean division] of `self` by `rhs`.
+    ///
+    /// [Euclidean division]: f64::rem_euclid
+    #[inline]
+    #[must_use]
+    pub fn rem_euclid(self, rhs: Self) -> Self {
+        Self::new(
+            math::rem_euclid(self.x, rhs.x),
+            math::rem_euclid(self.y, rhs.y),
+            math::rem_euclid(self.z, rhs.z),
+            math::rem_euclid(self.w, rhs.w),
+        )
+    }
+
     /// Returns `self` normalized to length 1.0.
     ///
     /// For valid results, `self` must _not_ be of length zero, nor very close to zero.
     ///
-    /// See also [`Self::try_normalize`] and [`Self::normalize_or_zero`].
+    /// See also [`Self::try_normalize()`] and [`Self::normalize_or_zero()`].
     ///
     /// Panics
     ///
     /// Will panic if `self` is zero length when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn normalize(self) -> Self {
         #[allow(clippy::let_and_return)]
         let normalized = self.mul(self.length_recip());
@@ -439,9 +506,9 @@
     /// In particular, if the input is zero (or very close to zero), or non-finite,
     /// the result of this operation will be `None`.
     ///
-    /// See also [`Self::normalize_or_zero`].
-    #[must_use]
+    /// See also [`Self::normalize_or_zero()`].
     #[inline]
+    #[must_use]
     pub fn try_normalize(self) -> Option<Self> {
         let rcp = self.length_recip();
         if rcp.is_finite() && rcp > 0.0 {
@@ -456,9 +523,9 @@
     /// In particular, if the input is zero (or very close to zero), or non-finite,
     /// the result of this operation will be zero.
     ///
-    /// See also [`Self::try_normalize`].
-    #[must_use]
+    /// See also [`Self::try_normalize()`].
     #[inline]
+    #[must_use]
     pub fn normalize_or_zero(self) -> Self {
         let rcp = self.length_recip();
         if rcp.is_finite() && rcp > 0.0 {
@@ -472,9 +539,10 @@
     ///
     /// Uses a precision threshold of `1e-6`.
     #[inline]
+    #[must_use]
     pub fn is_normalized(self) -> bool {
         // TODO: do something with epsilon
-        (self.length_squared() - 1.0).abs() <= 1e-4
+        math::abs(self.length_squared() - 1.0) <= 1e-4
     }
 
     /// Returns the vector projection of `self` onto `rhs`.
@@ -484,8 +552,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` is zero length when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn project_onto(self, rhs: Self) -> Self {
         let other_len_sq_rcp = rhs.dot(rhs).recip();
         glam_assert!(other_len_sq_rcp.is_finite());
@@ -502,8 +570,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` has a length of zero when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn reject_from(self, rhs: Self) -> Self {
         self - self.project_onto(rhs)
     }
@@ -515,8 +583,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` is not normalized when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn project_onto_normalized(self, rhs: Self) -> Self {
         glam_assert!(rhs.is_normalized());
         rhs * self.dot(rhs)
@@ -532,8 +600,8 @@
     /// # Panics
     ///
     /// Will panic if `rhs` is not normalized when `glam_assert` is enabled.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn reject_from_normalized(self, rhs: Self) -> Self {
         self - self.project_onto_normalized(rhs)
     }
@@ -541,36 +609,52 @@
     /// Returns a vector containing the nearest integer to a number for each element of `self`.
     /// Round half-way cases away from 0.0.
     #[inline]
+    #[must_use]
     pub fn round(self) -> Self {
         Self {
-            x: self.x.round(),
-            y: self.y.round(),
-            z: self.z.round(),
-            w: self.w.round(),
+            x: math::round(self.x),
+            y: math::round(self.y),
+            z: math::round(self.z),
+            w: math::round(self.w),
         }
     }
 
     /// Returns a vector containing the largest integer less than or equal to a number for each
     /// element of `self`.
     #[inline]
+    #[must_use]
     pub fn floor(self) -> Self {
         Self {
-            x: self.x.floor(),
-            y: self.y.floor(),
-            z: self.z.floor(),
-            w: self.w.floor(),
+            x: math::floor(self.x),
+            y: math::floor(self.y),
+            z: math::floor(self.z),
+            w: math::floor(self.w),
         }
     }
 
     /// Returns a vector containing the smallest integer greater than or equal to a number for
     /// each element of `self`.
     #[inline]
+    #[must_use]
     pub fn ceil(self) -> Self {
         Self {
-            x: self.x.ceil(),
-            y: self.y.ceil(),
-            z: self.z.ceil(),
-            w: self.w.ceil(),
+            x: math::ceil(self.x),
+            y: math::ceil(self.y),
+            z: math::ceil(self.z),
+            w: math::ceil(self.w),
+        }
+    }
+
+    /// Returns a vector containing the integer part each element of `self`. This means numbers are
+    /// always truncated towards zero.
+    #[inline]
+    #[must_use]
+    pub fn trunc(self) -> Self {
+        Self {
+            x: math::trunc(self.x),
+            y: math::trunc(self.y),
+            z: math::trunc(self.z),
+            w: math::trunc(self.w),
         }
     }
 
@@ -579,6 +663,7 @@
     ///
     /// Note that this is fast but not precise for large numbers.
     #[inline]
+    #[must_use]
     pub fn fract(self) -> Self {
         self - self.floor()
     }
@@ -586,29 +671,37 @@
     /// Returns a vector containing `e^self` (the exponential function) for each element of
     /// `self`.
     #[inline]
+    #[must_use]
     pub fn exp(self) -> Self {
-        Self::new(self.x.exp(), self.y.exp(), self.z.exp(), self.w.exp())
+        Self::new(
+            math::exp(self.x),
+            math::exp(self.y),
+            math::exp(self.z),
+            math::exp(self.w),
+        )
     }
 
     /// Returns a vector containing each element of `self` raised to the power of `n`.
     #[inline]
+    #[must_use]
     pub fn powf(self, n: f64) -> Self {
         Self::new(
-            self.x.powf(n),
-            self.y.powf(n),
-            self.z.powf(n),
-            self.w.powf(n),
+            math::powf(self.x, n),
+            math::powf(self.y, n),
+            math::powf(self.z, n),
+            math::powf(self.w, n),
         )
     }
 
     /// Returns a vector containing the reciprocal `1.0/n` of each element of `self`.
     #[inline]
+    #[must_use]
     pub fn recip(self) -> Self {
         Self {
-            x: self.x.recip(),
-            y: self.y.recip(),
-            z: self.z.recip(),
-            w: self.w.recip(),
+            x: 1.0 / self.x,
+            y: 1.0 / self.y,
+            z: 1.0 / self.z,
+            w: 1.0 / self.w,
         }
     }
 
@@ -619,6 +712,7 @@
     /// extrapolated.
     #[doc(alias = "mix")]
     #[inline]
+    #[must_use]
     pub fn lerp(self, rhs: Self, s: f64) -> Self {
         self + ((rhs - self) * s)
     }
@@ -633,6 +727,7 @@
     /// For more see
     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
     #[inline]
+    #[must_use]
     pub fn abs_diff_eq(self, rhs: Self, max_abs_diff: f64) -> bool {
         self.sub(rhs).abs().cmple(Self::splat(max_abs_diff)).all()
     }
@@ -643,33 +738,38 @@
     ///
     /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn clamp_length(self, min: f64, max: f64) -> Self {
         glam_assert!(min <= max);
         let length_sq = self.length_squared();
         if length_sq < min * min {
-            self * (length_sq.sqrt().recip() * min)
+            min * (self / math::sqrt(length_sq))
         } else if length_sq > max * max {
-            self * (length_sq.sqrt().recip() * max)
+            max * (self / math::sqrt(length_sq))
         } else {
             self
         }
     }
 
     /// Returns a vector with a length no more than `max`
+    #[inline]
+    #[must_use]
     pub fn clamp_length_max(self, max: f64) -> Self {
         let length_sq = self.length_squared();
         if length_sq > max * max {
-            self * (length_sq.sqrt().recip() * max)
+            max * (self / math::sqrt(length_sq))
         } else {
             self
         }
     }
 
     /// Returns a vector with a length no less than `min`
+    #[inline]
+    #[must_use]
     pub fn clamp_length_min(self, min: f64) -> Self {
         let length_sq = self.length_squared();
         if length_sq < min * min {
-            self * (length_sq.sqrt().recip() * min)
+            min * (self / math::sqrt(length_sq))
         } else {
             self
         }
@@ -683,32 +783,64 @@
     /// and will be heavily dependant on designing algorithms with specific target hardware in
     /// mind.
     #[inline]
+    #[must_use]
     pub fn mul_add(self, a: Self, b: Self) -> Self {
         Self::new(
-            self.x.mul_add(a.x, b.x),
-            self.y.mul_add(a.y, b.y),
-            self.z.mul_add(a.z, b.z),
-            self.w.mul_add(a.w, b.w),
+            math::mul_add(self.x, a.x, b.x),
+            math::mul_add(self.y, a.y, b.y),
+            math::mul_add(self.z, a.z, b.z),
+            math::mul_add(self.w, a.w, b.w),
         )
     }
 
     /// Casts all elements of `self` to `f32`.
     #[inline]
+    #[must_use]
     pub fn as_vec4(&self) -> crate::Vec4 {
         crate::Vec4::new(self.x as f32, self.y as f32, self.z as f32, self.w as f32)
     }
 
+    /// Casts all elements of `self` to `i16`.
+    #[inline]
+    #[must_use]
+    pub fn as_i16vec4(&self) -> crate::I16Vec4 {
+        crate::I16Vec4::new(self.x as i16, self.y as i16, self.z as i16, self.w as i16)
+    }
+
+    /// Casts all elements of `self` to `u16`.
+    #[inline]
+    #[must_use]
+    pub fn as_u16vec4(&self) -> crate::U16Vec4 {
+        crate::U16Vec4::new(self.x as u16, self.y as u16, self.z as u16, self.w as u16)
+    }
+
     /// Casts all elements of `self` to `i32`.
     #[inline]
+    #[must_use]
     pub fn as_ivec4(&self) -> crate::IVec4 {
         crate::IVec4::new(self.x as i32, self.y as i32, self.z as i32, self.w as i32)
     }
 
     /// Casts all elements of `self` to `u32`.
     #[inline]
+    #[must_use]
     pub fn as_uvec4(&self) -> crate::UVec4 {
         crate::UVec4::new(self.x as u32, self.y as u32, self.z as u32, self.w as u32)
     }
+
+    /// Casts all elements of `self` to `i64`.
+    #[inline]
+    #[must_use]
+    pub fn as_i64vec4(&self) -> crate::I64Vec4 {
+        crate::I64Vec4::new(self.x as i64, self.y as i64, self.z as i64, self.w as i64)
+    }
+
+    /// Casts all elements of `self` to `u64`.
+    #[inline]
+    #[must_use]
+    pub fn as_u64vec4(&self) -> crate::U64Vec4 {
+        crate::U64Vec4::new(self.x as u64, self.y as u64, self.z as u64, self.w as u64)
+    }
 }
 
 impl Default for DVec4 {
@@ -1183,3 +1315,39 @@
         Self::new(v.x, v.y, u.x, u.y)
     }
 }
+
+impl From<Vec4> for DVec4 {
+    #[inline]
+    fn from(v: Vec4) -> Self {
+        Self::new(
+            f64::from(v.x),
+            f64::from(v.y),
+            f64::from(v.z),
+            f64::from(v.w),
+        )
+    }
+}
+
+impl From<IVec4> for DVec4 {
+    #[inline]
+    fn from(v: IVec4) -> Self {
+        Self::new(
+            f64::from(v.x),
+            f64::from(v.y),
+            f64::from(v.z),
+            f64::from(v.w),
+        )
+    }
+}
+
+impl From<UVec4> for DVec4 {
+    #[inline]
+    fn from(v: UVec4) -> Self {
+        Self::new(
+            f64::from(v.x),
+            f64::from(v.y),
+            f64::from(v.z),
+            f64::from(v.w),
+        )
+    }
+}
diff --git a/src/f64/float.rs b/src/f64/float.rs
new file mode 100644
index 0000000..219c8b0
--- /dev/null
+++ b/src/f64/float.rs
@@ -0,0 +1,21 @@
+// Generated from float.rs.tera template. Edit the template, not the generated file.
+
+use crate::float::FloatExt;
+
+impl FloatExt for f64 {
+    #[inline]
+    fn lerp(self, rhs: f64, t: f64) -> f64 {
+        self + (rhs - self) * t
+    }
+
+    #[inline]
+    fn inverse_lerp(a: f64, b: f64, v: f64) -> f64 {
+        (v - a) / (b - a)
+    }
+
+    #[inline]
+    fn remap(self, in_start: f64, in_end: f64, out_start: f64, out_end: f64) -> f64 {
+        let t = f64::inverse_lerp(in_start, in_end, self);
+        f64::lerp(out_start, out_end, t)
+    }
+}
diff --git a/src/f64/math.rs b/src/f64/math.rs
new file mode 100644
index 0000000..45ace5c
--- /dev/null
+++ b/src/f64/math.rs
@@ -0,0 +1,215 @@
+#[cfg(feature = "libm")]
+mod libm_math {
+    #[inline(always)]
+    pub(crate) fn abs(f: f64) -> f64 {
+        libm::fabs(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn acos_approx(f: f64) -> f64 {
+        libm::acos(f.clamp(-1.0, 1.0))
+    }
+
+    #[inline(always)]
+    pub(crate) fn asin(f: f64) -> f64 {
+        libm::asin(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn atan2(f: f64, other: f64) -> f64 {
+        libm::atan2(f, other)
+    }
+
+    #[inline(always)]
+    pub(crate) fn sin(f: f64) -> f64 {
+        libm::sin(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn sin_cos(f: f64) -> (f64, f64) {
+        libm::sincos(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn tan(f: f64) -> f64 {
+        libm::tan(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn sqrt(f: f64) -> f64 {
+        libm::sqrt(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn copysign(f: f64, sign: f64) -> f64 {
+        libm::copysign(f, sign)
+    }
+
+    #[inline(always)]
+    pub(crate) fn signum(f: f64) -> f64 {
+        if f.is_nan() {
+            f64::NAN
+        } else {
+            copysign(1.0, f)
+        }
+    }
+
+    #[inline(always)]
+    pub(crate) fn round(f: f64) -> f64 {
+        libm::round(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn trunc(f: f64) -> f64 {
+        libm::trunc(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn ceil(f: f64) -> f64 {
+        libm::ceil(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn floor(f: f64) -> f64 {
+        libm::floor(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn exp(f: f64) -> f64 {
+        libm::exp(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn powf(f: f64, n: f64) -> f64 {
+        libm::pow(f, n)
+    }
+
+    #[inline(always)]
+    pub(crate) fn mul_add(a: f64, b: f64, c: f64) -> f64 {
+        libm::fma(a, b, c)
+    }
+
+    #[inline]
+    pub fn div_euclid(a: f64, b: f64) -> f64 {
+        // Based on https://doc.rust-lang.org/src/std/f64.rs.html#293
+        let q = libm::trunc(a / b);
+        if a % b < 0.0 {
+            return if b > 0.0 { q - 1.0 } else { q + 1.0 };
+        }
+        q
+    }
+
+    #[inline]
+    pub fn rem_euclid(a: f64, b: f64) -> f64 {
+        let r = a % b;
+        if r < 0.0 {
+            r + abs(b)
+        } else {
+            r
+        }
+    }
+}
+
+#[cfg(not(feature = "libm"))]
+mod std_math {
+    #[inline(always)]
+    pub(crate) fn abs(f: f64) -> f64 {
+        f64::abs(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn acos_approx(f: f64) -> f64 {
+        f64::acos(f64::clamp(f, -1.0, 1.0))
+    }
+
+    #[inline(always)]
+    pub(crate) fn asin(f: f64) -> f64 {
+        f64::asin(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn atan2(f: f64, other: f64) -> f64 {
+        f64::atan2(f, other)
+    }
+
+    #[inline(always)]
+    pub(crate) fn sin(f: f64) -> f64 {
+        f64::sin(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn sin_cos(f: f64) -> (f64, f64) {
+        f64::sin_cos(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn tan(f: f64) -> f64 {
+        f64::tan(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn sqrt(f: f64) -> f64 {
+        f64::sqrt(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn copysign(f: f64, sign: f64) -> f64 {
+        f64::copysign(f, sign)
+    }
+
+    #[inline(always)]
+    pub(crate) fn signum(f: f64) -> f64 {
+        f64::signum(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn round(f: f64) -> f64 {
+        f64::round(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn trunc(f: f64) -> f64 {
+        f64::trunc(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn ceil(f: f64) -> f64 {
+        f64::ceil(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn floor(f: f64) -> f64 {
+        f64::floor(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn exp(f: f64) -> f64 {
+        f64::exp(f)
+    }
+
+    #[inline(always)]
+    pub(crate) fn powf(f: f64, n: f64) -> f64 {
+        f64::powf(f, n)
+    }
+
+    #[inline(always)]
+    pub(crate) fn mul_add(a: f64, b: f64, c: f64) -> f64 {
+        f64::mul_add(a, b, c)
+    }
+
+    #[inline]
+    pub fn div_euclid(a: f64, b: f64) -> f64 {
+        f64::div_euclid(a, b)
+    }
+
+    #[inline]
+    pub fn rem_euclid(a: f64, b: f64) -> f64 {
+        f64::rem_euclid(a, b)
+    }
+}
+
+#[cfg(feature = "libm")]
+pub(crate) use libm_math::*;
+
+#[cfg(not(feature = "libm"))]
+pub(crate) use std_math::*;
diff --git a/src/features/impl_bytemuck.rs b/src/features/impl_bytemuck.rs
index bed7ecd..1b47029 100644
--- a/src/features/impl_bytemuck.rs
+++ b/src/features/impl_bytemuck.rs
@@ -1,13 +1,23 @@
 use crate::{
-    DMat2, DMat3, DMat4, DQuat, DVec2, DVec3, DVec4, IVec2, IVec3, IVec4, Mat2, Mat3, Mat4, Quat,
-    UVec2, UVec3, UVec4, Vec2, Vec3, Vec4,
+    Affine2, Affine3A, DAffine2, DAffine3, DMat2, DMat3, DMat4, DQuat, DVec2, DVec3, DVec4,
+    I16Vec2, I16Vec3, I16Vec4, I64Vec2, I64Vec3, I64Vec4, IVec2, IVec3, IVec4, Mat2, Mat3, Mat3A,
+    Mat4, Quat, U16Vec2, U16Vec3, U16Vec4, U64Vec2, U64Vec3, U64Vec4, UVec2, UVec3, UVec4, Vec2,
+    Vec3, Vec3A, Vec4,
 };
-use bytemuck::{Pod, Zeroable};
+use bytemuck::{AnyBitPattern, Pod, Zeroable};
+
+// Affine2 contains internal padding due to Mat2 using SIMD
+unsafe impl AnyBitPattern for Affine2 {}
+unsafe impl Zeroable for Affine2 {}
+unsafe impl AnyBitPattern for Affine3A {}
+unsafe impl Zeroable for Affine3A {}
 
 unsafe impl Pod for Mat2 {}
 unsafe impl Zeroable for Mat2 {}
 unsafe impl Pod for Mat3 {}
 unsafe impl Zeroable for Mat3 {}
+unsafe impl AnyBitPattern for Mat3A {}
+unsafe impl Zeroable for Mat3A {}
 unsafe impl Pod for Mat4 {}
 unsafe impl Zeroable for Mat4 {}
 
@@ -18,9 +28,16 @@
 unsafe impl Zeroable for Vec2 {}
 unsafe impl Pod for Vec3 {}
 unsafe impl Zeroable for Vec3 {}
+unsafe impl AnyBitPattern for Vec3A {}
+unsafe impl Zeroable for Vec3A {}
 unsafe impl Pod for Vec4 {}
 unsafe impl Zeroable for Vec4 {}
 
+unsafe impl Pod for DAffine2 {}
+unsafe impl Zeroable for DAffine2 {}
+unsafe impl Pod for DAffine3 {}
+unsafe impl Zeroable for DAffine3 {}
+
 unsafe impl Pod for DMat2 {}
 unsafe impl Zeroable for DMat2 {}
 unsafe impl Pod for DMat3 {}
@@ -38,6 +55,20 @@
 unsafe impl Pod for DVec4 {}
 unsafe impl Zeroable for DVec4 {}
 
+unsafe impl Pod for I16Vec2 {}
+unsafe impl Zeroable for I16Vec2 {}
+unsafe impl Pod for I16Vec3 {}
+unsafe impl Zeroable for I16Vec3 {}
+unsafe impl Pod for I16Vec4 {}
+unsafe impl Zeroable for I16Vec4 {}
+
+unsafe impl Pod for U16Vec2 {}
+unsafe impl Zeroable for U16Vec2 {}
+unsafe impl Pod for U16Vec3 {}
+unsafe impl Zeroable for U16Vec3 {}
+unsafe impl Pod for U16Vec4 {}
+unsafe impl Zeroable for U16Vec4 {}
+
 unsafe impl Pod for IVec2 {}
 unsafe impl Zeroable for IVec2 {}
 unsafe impl Pod for IVec3 {}
@@ -52,47 +83,105 @@
 unsafe impl Pod for UVec4 {}
 unsafe impl Zeroable for UVec4 {}
 
+unsafe impl Pod for I64Vec2 {}
+unsafe impl Zeroable for I64Vec2 {}
+unsafe impl Pod for I64Vec3 {}
+unsafe impl Zeroable for I64Vec3 {}
+unsafe impl Pod for I64Vec4 {}
+unsafe impl Zeroable for I64Vec4 {}
+
+unsafe impl Pod for U64Vec2 {}
+unsafe impl Zeroable for U64Vec2 {}
+unsafe impl Pod for U64Vec3 {}
+unsafe impl Zeroable for U64Vec3 {}
+unsafe impl Pod for U64Vec4 {}
+unsafe impl Zeroable for U64Vec4 {}
+
 #[cfg(test)]
 mod test {
     use crate::{
-        DMat2, DMat3, DMat4, DQuat, DVec2, DVec3, DVec4, IVec2, IVec3, IVec4, Mat2, Mat3, Mat4,
-        Quat, UVec2, UVec3, UVec4, Vec2, Vec3, Vec4,
+        Affine2, Affine3A, DAffine2, DAffine3, DMat2, DMat3, DMat4, DQuat, DVec2, DVec3, DVec4,
+        I16Vec2, I16Vec3, I16Vec4, I64Vec2, I64Vec3, I64Vec4, IVec2, IVec3, IVec4, Mat2, Mat3,
+        Mat3A, Mat4, Quat, U16Vec2, U16Vec3, U16Vec4, U64Vec2, U64Vec3, U64Vec4, UVec2, UVec3,
+        UVec4, Vec2, Vec3, Vec3A, Vec4,
     };
     use core::mem;
 
-    macro_rules! test_t {
+    macro_rules! test_pod_t {
         ($name:ident, $t:ty) => {
             #[test]
             fn $name() {
                 let t = <$t>::default();
                 let b = bytemuck::bytes_of(&t);
-                assert_eq!(t.as_ref().as_ptr() as usize, b.as_ptr() as usize);
+                // the below loop will fail in miri if we're doing something bad here.
+                for bi in b {
+                    assert_eq!(bi, bi);
+                }
+                // should be the same address
+                assert_eq!(&t as *const $t as usize, b.as_ptr() as usize);
+                // should be the same size
                 assert_eq!(b.len(), mem::size_of_val(&t));
             }
         };
     }
 
-    test_t!(mat2, Mat2);
-    test_t!(mat3, Mat3);
-    test_t!(mat4, Mat4);
-    test_t!(quat, Quat);
-    test_t!(vec2, Vec2);
-    test_t!(vec3, Vec3);
-    test_t!(vec4, Vec4);
+    macro_rules! test_any_bit_pattern_t {
+        ($name:ident, $t:ident) => {
+            #[test]
+            fn $name() {
+                let b = [0_u8; mem::size_of::<$t>()];
+                let t: $t = bytemuck::cast(b);
+                // should be the same size
+                assert_eq!(b.len(), mem::size_of_val(&t));
+                // should be zero
+                assert_eq!(t, $t::ZERO);
+            }
+        };
+    }
 
-    test_t!(dmat2, DMat2);
-    test_t!(dmat3, DMat3);
-    test_t!(dmat4, DMat4);
-    test_t!(dquat, DQuat);
-    test_t!(dvec2, DVec2);
-    test_t!(dvec3, DVec3);
-    test_t!(dvec4, DVec4);
+    test_any_bit_pattern_t!(affine2, Affine2);
+    test_any_bit_pattern_t!(affine3a, Affine3A);
+    test_pod_t!(mat2, Mat2);
+    test_pod_t!(mat3, Mat3);
+    test_any_bit_pattern_t!(mat3a, Mat3A);
+    test_pod_t!(mat4, Mat4);
+    test_pod_t!(quat, Quat);
+    test_pod_t!(vec2, Vec2);
+    test_pod_t!(vec3, Vec3);
+    test_any_bit_pattern_t!(vec3a, Vec3A);
+    test_pod_t!(vec4, Vec4);
 
-    test_t!(ivec2, IVec2);
-    test_t!(ivec3, IVec3);
-    test_t!(ivec4, IVec4);
+    test_pod_t!(daffine2, DAffine2);
+    test_pod_t!(daffine3, DAffine3);
+    test_pod_t!(dmat2, DMat2);
+    test_pod_t!(dmat3, DMat3);
+    test_pod_t!(dmat4, DMat4);
+    test_pod_t!(dquat, DQuat);
+    test_pod_t!(dvec2, DVec2);
+    test_pod_t!(dvec3, DVec3);
+    test_pod_t!(dvec4, DVec4);
 
-    test_t!(uvec2, UVec2);
-    test_t!(uvec3, UVec3);
-    test_t!(uvec4, UVec4);
+    test_pod_t!(i16vec2, I16Vec2);
+    test_pod_t!(i16vec3, I16Vec3);
+    test_pod_t!(i16vec4, I16Vec4);
+
+    test_pod_t!(u16vec2, U16Vec2);
+    test_pod_t!(u16vec3, U16Vec3);
+    test_pod_t!(u16vec4, U16Vec4);
+
+    test_pod_t!(ivec2, IVec2);
+    test_pod_t!(ivec3, IVec3);
+    test_pod_t!(ivec4, IVec4);
+
+    test_pod_t!(uvec2, UVec2);
+    test_pod_t!(uvec3, UVec3);
+    test_pod_t!(uvec4, UVec4);
+
+    test_pod_t!(i64vec2, I64Vec2);
+    test_pod_t!(i64vec3, I64Vec3);
+    test_pod_t!(i64vec4, I64Vec4);
+
+    test_pod_t!(u64vec2, U64Vec2);
+    test_pod_t!(u64vec3, U64Vec3);
+    test_pod_t!(u64vec4, U64Vec4);
 }
diff --git a/src/features/impl_mint.rs b/src/features/impl_mint.rs
index 5c7670b..84cdcbd 100644
--- a/src/features/impl_mint.rs
+++ b/src/features/impl_mint.rs
@@ -1,8 +1,9 @@
 use mint::IntoMint;
 
 use crate::{
-    DMat2, DMat3, DMat4, DQuat, DVec2, DVec3, DVec4, IVec2, IVec3, IVec4, Mat2, Mat3, Mat3A, Mat4,
-    Quat, UVec2, UVec3, UVec4, Vec2, Vec3, Vec3A, Vec4,
+    DMat2, DMat3, DMat4, DQuat, DVec2, DVec3, DVec4, I16Vec2, I16Vec3, I16Vec4, I64Vec2, I64Vec3,
+    I64Vec4, IVec2, IVec3, IVec4, Mat2, Mat3, Mat3A, Mat4, Quat, U16Vec2, U16Vec3, U16Vec4,
+    U64Vec2, U64Vec3, U64Vec4, UVec2, UVec3, UVec4, Vec2, Vec3, Vec3A, Vec4,
 };
 
 macro_rules! impl_vec_types {
@@ -309,8 +310,12 @@
 
 impl_float_types!(f32, Mat2, Mat3, Mat4, Quat, Vec2, Vec3, Vec4);
 impl_float_types!(f64, DMat2, DMat3, DMat4, DQuat, DVec2, DVec3, DVec4);
+impl_vec_types!(i16, I16Vec2, I16Vec3, I16Vec4);
+impl_vec_types!(u16, U16Vec2, U16Vec3, U16Vec4);
 impl_vec_types!(i32, IVec2, IVec3, IVec4);
 impl_vec_types!(u32, UVec2, UVec3, UVec4);
+impl_vec_types!(i64, I64Vec2, I64Vec3, I64Vec4);
+impl_vec_types!(u64, U64Vec2, U64Vec3, U64Vec4);
 
 #[cfg(test)]
 mod test {
diff --git a/src/features/impl_rand.rs b/src/features/impl_rand.rs
index d3f33c2..3c6c19a 100644
--- a/src/features/impl_rand.rs
+++ b/src/features/impl_rand.rs
@@ -178,6 +178,16 @@
     impl_float_types!(f64, DMat2, DMat3, DMat4, DQuat, DVec2, DVec3, DVec4);
 }
 
+mod i16 {
+    use crate::{I16Vec2, I16Vec3, I16Vec4};
+    use rand::{
+        distributions::{Distribution, Standard},
+        Rng,
+    };
+
+    impl_vec_types!(i16, I16Vec2, I16Vec3, I16Vec4);
+}
+
 mod i32 {
     use crate::{IVec2, IVec3, IVec4};
     use rand::{
@@ -188,6 +198,26 @@
     impl_vec_types!(i32, IVec2, IVec3, IVec4);
 }
 
+mod i64 {
+    use crate::{I64Vec2, I64Vec3, I64Vec4};
+    use rand::{
+        distributions::{Distribution, Standard},
+        Rng,
+    };
+
+    impl_vec_types!(i64, I64Vec2, I64Vec3, I64Vec4);
+}
+
+mod u16 {
+    use crate::{U16Vec2, U16Vec3, U16Vec4};
+    use rand::{
+        distributions::{Distribution, Standard},
+        Rng,
+    };
+
+    impl_vec_types!(u16, U16Vec2, U16Vec3, U16Vec4);
+}
+
 mod u32 {
     use crate::{UVec2, UVec3, UVec4};
     use rand::{
@@ -197,3 +227,13 @@
 
     impl_vec_types!(u32, UVec2, UVec3, UVec4);
 }
+
+mod u64 {
+    use crate::{U64Vec2, U64Vec3, U64Vec4};
+    use rand::{
+        distributions::{Distribution, Standard},
+        Rng,
+    };
+
+    impl_vec_types!(u64, U64Vec2, U64Vec3, U64Vec4);
+}
diff --git a/src/features/impl_rkyv.rs b/src/features/impl_rkyv.rs
index 5c6efdc..fb72e37 100644
--- a/src/features/impl_rkyv.rs
+++ b/src/features/impl_rkyv.rs
@@ -90,6 +90,15 @@
     impl_rkyv!(DVec4);
 }
 
+mod i16 {
+    use crate::{I16Vec2, I16Vec3, I16Vec4};
+    use rkyv::{from_archived, to_archived, Archive, Deserialize, Fallible, Serialize};
+
+    impl_rkyv!(I16Vec2);
+    impl_rkyv!(I16Vec3);
+    impl_rkyv!(I16Vec4);
+}
+
 mod i32 {
     use crate::{IVec2, IVec3, IVec4};
     use rkyv::{from_archived, to_archived, Archive, Deserialize, Fallible, Serialize};
@@ -99,6 +108,24 @@
     impl_rkyv!(IVec4);
 }
 
+mod i64 {
+    use crate::{I64Vec2, I64Vec3, I64Vec4};
+    use rkyv::{from_archived, to_archived, Archive, Deserialize, Fallible, Serialize};
+
+    impl_rkyv!(I64Vec2);
+    impl_rkyv!(I64Vec3);
+    impl_rkyv!(I64Vec4);
+}
+
+mod u16 {
+    use crate::{U16Vec2, U16Vec3, U16Vec4};
+    use rkyv::{from_archived, to_archived, Archive, Deserialize, Fallible, Serialize};
+
+    impl_rkyv!(U16Vec2);
+    impl_rkyv!(U16Vec3);
+    impl_rkyv!(U16Vec4);
+}
+
 mod u32 {
     use crate::{UVec2, UVec3, UVec4};
     use rkyv::{from_archived, to_archived, Archive, Deserialize, Fallible, Serialize};
@@ -108,6 +135,15 @@
     impl_rkyv!(UVec4);
 }
 
+mod u64 {
+    use crate::{U64Vec2, U64Vec3, U64Vec4};
+    use rkyv::{from_archived, to_archived, Archive, Deserialize, Fallible, Serialize};
+
+    impl_rkyv!(U64Vec2);
+    impl_rkyv!(U64Vec3);
+    impl_rkyv!(U64Vec4);
+}
+
 #[cfg(test)]
 mod test {
     pub type DefaultSerializer = rkyv::ser::serializers::CoreSerializer<256, 256>;
@@ -175,14 +211,34 @@
         test_archive(&DVec3::new(1.0, 2.0, 3.0));
         test_archive(&DVec4::new(1.0, 2.0, 3.0, 4.0));
 
+        use crate::{I16Vec2, I16Vec3, I16Vec4};
+        test_archive(&I16Vec2::new(-1, 2));
+        test_archive(&I16Vec3::new(-1, 2, 3));
+        test_archive(&I16Vec4::new(-1, 2, 3, 4));
+
         use crate::{IVec2, IVec3, IVec4};
         test_archive(&IVec2::new(-1, 2));
         test_archive(&IVec3::new(-1, 2, 3));
         test_archive(&IVec4::new(-1, 2, 3, 4));
 
+        use crate::{I64Vec2, I64Vec3, I64Vec4};
+        test_archive(&I64Vec2::new(-1, 2));
+        test_archive(&I64Vec3::new(-1, 2, 3));
+        test_archive(&I64Vec4::new(-1, 2, 3, 4));
+
+        use crate::{U16Vec2, U16Vec3, U16Vec4};
+        test_archive(&U16Vec2::new(1, 2));
+        test_archive(&U16Vec3::new(1, 2, 3));
+        test_archive(&U16Vec4::new(1, 2, 3, 4));
+
         use crate::{UVec2, UVec3, UVec4};
         test_archive(&UVec2::new(1, 2));
         test_archive(&UVec3::new(1, 2, 3));
         test_archive(&UVec4::new(1, 2, 3, 4));
+
+        use crate::{U64Vec2, U64Vec3, U64Vec4};
+        test_archive(&U64Vec2::new(1, 2));
+        test_archive(&U64Vec3::new(1, 2, 3));
+        test_archive(&U64Vec4::new(1, 2, 3, 4));
     }
 }
diff --git a/src/features/impl_serde.rs b/src/features/impl_serde.rs
index c3a44e0..ab0db6c 100644
--- a/src/features/impl_serde.rs
+++ b/src/features/impl_serde.rs
@@ -727,6 +727,14 @@
 }
 
 #[cfg(test)]
+mod test_i16 {
+    pub const V1: i16 = 1;
+    pub const V2: i16 = 2;
+    pub const V3: i16 = 3;
+    pub const V4: i16 = 4;
+}
+
+#[cfg(test)]
 mod test_i32 {
     pub const V1: i32 = 1;
     pub const V2: i32 = 2;
@@ -735,6 +743,22 @@
 }
 
 #[cfg(test)]
+mod test_i64 {
+    pub const V1: i64 = 1;
+    pub const V2: i64 = 2;
+    pub const V3: i64 = 3;
+    pub const V4: i64 = 4;
+}
+
+#[cfg(test)]
+mod test_u16 {
+    pub const V1: u16 = 1;
+    pub const V2: u16 = 2;
+    pub const V3: u16 = 3;
+    pub const V4: u16 = 4;
+}
+
+#[cfg(test)]
 mod test_u32 {
     pub const V1: u32 = 1;
     pub const V2: u32 = 2;
@@ -743,6 +767,14 @@
 }
 
 #[cfg(test)]
+mod test_u64 {
+    pub const V1: u64 = 1;
+    pub const V2: u64 = 2;
+    pub const V3: u64 = 3;
+    pub const V4: u64 = 4;
+}
+
+#[cfg(test)]
 mod test_float {
     pub const SX0: &str = "[]";
     pub const SX1: &str = "[1.0]";
@@ -971,6 +1003,21 @@
     );
 }
 
+mod i16 {
+    #[cfg(test)]
+    use super::test_i16::*;
+    #[cfg(test)]
+    use super::test_int::*;
+    use crate::{I16Vec2, I16Vec3, I16Vec4};
+    use core::fmt;
+    use serde::{
+        de::{self, Deserialize, Deserializer, SeqAccess, Visitor},
+        ser::{Serialize, SerializeTupleStruct, Serializer},
+    };
+
+    impl_serde_vec_types!(i16, I16Vec2, I16Vec3, I16Vec4);
+}
+
 mod i32 {
     #[cfg(test)]
     use super::test_i32::*;
@@ -986,6 +1033,36 @@
     impl_serde_vec_types!(i32, IVec2, IVec3, IVec4);
 }
 
+mod i64 {
+    #[cfg(test)]
+    use super::test_i64::*;
+    #[cfg(test)]
+    use super::test_int::*;
+    use crate::{I64Vec2, I64Vec3, I64Vec4};
+    use core::fmt;
+    use serde::{
+        de::{self, Deserialize, Deserializer, SeqAccess, Visitor},
+        ser::{Serialize, SerializeTupleStruct, Serializer},
+    };
+
+    impl_serde_vec_types!(i64, I64Vec2, I64Vec3, I64Vec4);
+}
+
+mod u16 {
+    #[cfg(test)]
+    use super::test_int::*;
+    #[cfg(test)]
+    use super::test_u16::*;
+    use crate::{U16Vec2, U16Vec3, U16Vec4};
+    use core::fmt;
+    use serde::{
+        de::{self, Deserialize, Deserializer, SeqAccess, Visitor},
+        ser::{Serialize, SerializeTupleStruct, Serializer},
+    };
+
+    impl_serde_vec_types!(u16, U16Vec2, U16Vec3, U16Vec4);
+}
+
 mod u32 {
     #[cfg(test)]
     use super::test_int::*;
@@ -1000,3 +1077,196 @@
 
     impl_serde_vec_types!(u32, UVec2, UVec3, UVec4);
 }
+
+mod u64 {
+    #[cfg(test)]
+    use super::test_int::*;
+    #[cfg(test)]
+    use super::test_u64::*;
+    use crate::{U64Vec2, U64Vec3, U64Vec4};
+    use core::fmt;
+    use serde::{
+        de::{self, Deserialize, Deserializer, SeqAccess, Visitor},
+        ser::{Serialize, SerializeTupleStruct, Serializer},
+    };
+
+    impl_serde_vec_types!(u64, U64Vec2, U64Vec3, U64Vec4);
+}
+
+mod euler {
+    use crate::EulerRot;
+
+    impl serde::Serialize for EulerRot {
+        fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
+            match *self {
+                EulerRot::ZYX => {
+                    serde::Serializer::serialize_unit_variant(serializer, "EulerRot", 0u32, "ZYX")
+                }
+                EulerRot::ZXY => {
+                    serde::Serializer::serialize_unit_variant(serializer, "EulerRot", 1u32, "ZXY")
+                }
+                EulerRot::YXZ => {
+                    serde::Serializer::serialize_unit_variant(serializer, "EulerRot", 2u32, "YXZ")
+                }
+                EulerRot::YZX => {
+                    serde::Serializer::serialize_unit_variant(serializer, "EulerRot", 3u32, "YZX")
+                }
+                EulerRot::XYZ => {
+                    serde::Serializer::serialize_unit_variant(serializer, "EulerRot", 4u32, "XYZ")
+                }
+                EulerRot::XZY => {
+                    serde::Serializer::serialize_unit_variant(serializer, "EulerRot", 5u32, "XZY")
+                }
+            }
+        }
+    }
+
+    impl<'de> serde::Deserialize<'de> for EulerRot {
+        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+        where
+            D: serde::Deserializer<'de>,
+        {
+            #[allow(clippy::upper_case_acronyms)]
+            enum Field {
+                ZYX,
+                ZXY,
+                YXZ,
+                YZX,
+                XYZ,
+                XZY,
+            }
+            struct FieldVisitor;
+
+            impl<'de> serde::de::Visitor<'de> for FieldVisitor {
+                type Value = Field;
+                fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+                    core::fmt::Formatter::write_str(formatter, "variant identifier")
+                }
+                fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
+                where
+                    E: serde::de::Error,
+                {
+                    match value {
+                        0u64 => Ok(Field::ZYX),
+                        1u64 => Ok(Field::ZXY),
+                        2u64 => Ok(Field::YXZ),
+                        3u64 => Ok(Field::YZX),
+                        4u64 => Ok(Field::XYZ),
+                        5u64 => Ok(Field::XZY),
+                        _ => Err(serde::de::Error::invalid_value(
+                            serde::de::Unexpected::Unsigned(value),
+                            &"variant index 0 <= i < 6",
+                        )),
+                    }
+                }
+                fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
+                where
+                    E: serde::de::Error,
+                {
+                    match value {
+                        "ZYX" => Ok(Field::ZYX),
+                        "ZXY" => Ok(Field::ZXY),
+                        "YXZ" => Ok(Field::YXZ),
+                        "YZX" => Ok(Field::YZX),
+                        "XYZ" => Ok(Field::XYZ),
+                        "XZY" => Ok(Field::XZY),
+                        _ => Err(serde::de::Error::unknown_variant(value, VARIANTS)),
+                    }
+                }
+                fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
+                where
+                    E: serde::de::Error,
+                {
+                    match value {
+                        b"ZYX" => Ok(Field::ZYX),
+                        b"ZXY" => Ok(Field::ZXY),
+                        b"YXZ" => Ok(Field::YXZ),
+                        b"YZX" => Ok(Field::YZX),
+                        b"XYZ" => Ok(Field::XYZ),
+                        b"XZY" => Ok(Field::XZY),
+                        _ => {
+                            #[cfg(feature = "std")]
+                            let value = &String::from_utf8_lossy(value);
+                            #[cfg(not(feature = "std"))]
+                            let value =
+                                core::str::from_utf8(value).unwrap_or("\u{fffd}\u{fffd}\u{fffd}");
+                            Err(serde::de::Error::unknown_variant(value, VARIANTS))
+                        }
+                    }
+                }
+            }
+            impl<'de> serde::Deserialize<'de> for Field {
+                #[inline]
+                fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+                where
+                    D: serde::Deserializer<'de>,
+                {
+                    serde::Deserializer::deserialize_identifier(deserializer, FieldVisitor)
+                }
+            }
+            struct Visitor<'de> {
+                marker: core::marker::PhantomData<EulerRot>,
+                lifetime: core::marker::PhantomData<&'de ()>,
+            }
+            impl<'de> serde::de::Visitor<'de> for Visitor<'de> {
+                type Value = EulerRot;
+                fn expecting(
+                    &self,
+                    __formatter: &mut core::fmt::Formatter<'_>,
+                ) -> core::fmt::Result {
+                    core::fmt::Formatter::write_str(__formatter, "enum EulerRot")
+                }
+                fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
+                where
+                    A: serde::de::EnumAccess<'de>,
+                {
+                    match serde::de::EnumAccess::variant(data)? {
+                        (Field::ZYX, variant) => {
+                            serde::de::VariantAccess::unit_variant(variant)?;
+                            Ok(EulerRot::ZYX)
+                        }
+                        (Field::ZXY, variant) => {
+                            serde::de::VariantAccess::unit_variant(variant)?;
+                            Ok(EulerRot::ZXY)
+                        }
+                        (Field::YXZ, variant) => {
+                            serde::de::VariantAccess::unit_variant(variant)?;
+                            Ok(EulerRot::YXZ)
+                        }
+                        (Field::YZX, variant) => {
+                            serde::de::VariantAccess::unit_variant(variant)?;
+                            Ok(EulerRot::YZX)
+                        }
+                        (Field::XYZ, variant) => {
+                            serde::de::VariantAccess::unit_variant(variant)?;
+                            Ok(EulerRot::XYZ)
+                        }
+                        (Field::XZY, variant) => {
+                            serde::de::VariantAccess::unit_variant(variant)?;
+                            Ok(EulerRot::XZY)
+                        }
+                    }
+                }
+            }
+            const VARIANTS: &[&str] = &["ZYX", "ZXY", "YXZ", "YZX", "XYZ", "XZY"];
+            serde::Deserializer::deserialize_enum(
+                deserializer,
+                "EulerRot",
+                VARIANTS,
+                Visitor {
+                    marker: core::marker::PhantomData::<EulerRot>,
+                    lifetime: core::marker::PhantomData,
+                },
+            )
+        }
+    }
+
+    #[test]
+    fn test_euler_rot_serde() {
+        let a = EulerRot::XYZ;
+        let serialized = serde_json::to_string(&a).unwrap();
+        assert_eq!("\"XYZ\"", serialized);
+        let deserialized = serde_json::from_str(&serialized).unwrap();
+        assert_eq!(a, deserialized);
+    }
+}
diff --git a/src/float.rs b/src/float.rs
new file mode 100644
index 0000000..231b616
--- /dev/null
+++ b/src/float.rs
@@ -0,0 +1,30 @@
+/// A trait for extending [`prim@f32`] and [`prim@f64`] with extra methods.
+pub trait FloatExt {
+    /// Performs a linear interpolation between `self` and `rhs` based on the value `t`.
+    ///
+    /// When `t` is `0`, the result will be `self`.  When `t` is `1`, the result
+    /// will be `rhs`. When `t` is outside of the range `[0, 1]`, the result is linearly
+    /// extrapolated.
+    #[must_use]
+    fn lerp(self, rhs: Self, s: Self) -> Self;
+
+    /// Returns `v` normalized to the range `[a, b]`.
+    ///
+    /// When `v` is equal to `a` the result will be `0`.  When `v` is equal to `b` will be `1`.
+    ///
+    /// When `v` is outside of the range `[a, b]`, the result is linearly extrapolated.
+    ///
+    /// `a` and `b` must not be equal, otherwise the result will be either infinite or `NAN`.
+    fn inverse_lerp(a: Self, b: Self, v: Self) -> Self;
+
+    /// Remap `self` from the input range to the output range.
+    ///
+    /// When `self` is equal to `in_start` this returns `out_start`.
+    /// When `self` is equal to `in_end` this returns `out_end`.
+    ///
+    /// When `self` is outside of the range `[in_start, in_end]`, the result is linearly extrapolated.
+    ///
+    /// `in_start` and `in_end` must not be equal, otherwise the result will be either infinite or `NAN`.
+    #[must_use]
+    fn remap(self, in_start: Self, in_end: Self, out_start: Self, out_end: Self) -> Self;
+}
diff --git a/src/float_ex.rs b/src/float_ex.rs
deleted file mode 100644
index 70f382a..0000000
--- a/src/float_ex.rs
+++ /dev/null
@@ -1,51 +0,0 @@
-#[cfg(feature = "libm")]
-#[allow(unused_imports)]
-use num_traits::Float;
-
-pub(crate) trait FloatEx {
-    /// Returns a very close approximation of `self.clamp(-1.0, 1.0).acos()`.
-    fn acos_approx(self) -> Self;
-}
-
-impl FloatEx for f32 {
-    #[inline(always)]
-    fn acos_approx(self) -> Self {
-        // Based on https://github.com/microsoft/DirectXMath `XMScalarAcos`
-        // Clamp input to [-1,1].
-        let nonnegative = self >= 0.0;
-        let x = self.abs();
-        let mut omx = 1.0 - x;
-        if omx < 0.0 {
-            omx = 0.0;
-        }
-        let root = omx.sqrt();
-
-        // 7-degree minimax approximation
-        #[allow(clippy::approx_constant)]
-        let mut result = ((((((-0.001_262_491_1 * x + 0.006_670_09) * x - 0.017_088_126) * x
-            + 0.030_891_88)
-            * x
-            - 0.050_174_303)
-            * x
-            + 0.088_978_99)
-            * x
-            - 0.214_598_8)
-            * x
-            + 1.570_796_3;
-        result *= root;
-
-        // acos(x) = pi - acos(-x) when x < 0
-        if nonnegative {
-            result
-        } else {
-            core::f32::consts::PI - result
-        }
-    }
-}
-
-impl FloatEx for f64 {
-    #[inline(always)]
-    fn acos_approx(self) -> Self {
-        f64::acos(self.clamp(-1.0, 1.0))
-    }
-}
diff --git a/src/i16.rs b/src/i16.rs
new file mode 100644
index 0000000..7d9acdc
--- /dev/null
+++ b/src/i16.rs
@@ -0,0 +1,44 @@
+mod i16vec2;
+mod i16vec3;
+mod i16vec4;
+
+pub use i16vec2::{i16vec2, I16Vec2};
+pub use i16vec3::{i16vec3, I16Vec3};
+pub use i16vec4::{i16vec4, I16Vec4};
+
+#[cfg(not(target_arch = "spirv"))]
+mod test {
+    use super::*;
+
+    mod const_test_i16vec2 {
+        const_assert_eq!(4, core::mem::size_of::<super::I16Vec2>());
+
+        #[cfg(not(feature = "cuda"))]
+        const_assert_eq!(
+            core::mem::align_of::<i16>(),
+            core::mem::align_of::<super::I16Vec2>()
+        );
+        #[cfg(feature = "cuda")]
+        const_assert_eq!(4, core::mem::align_of::<super::I16Vec2>());
+    }
+
+    mod const_test_i16vec3 {
+        const_assert_eq!(
+            core::mem::align_of::<i16>(),
+            core::mem::align_of::<super::I16Vec3>()
+        );
+        const_assert_eq!(6, core::mem::size_of::<super::I16Vec3>());
+    }
+
+    mod const_test_i16vec4 {
+        const_assert_eq!(8, core::mem::size_of::<super::I16Vec4>());
+
+        #[cfg(not(feature = "cuda"))]
+        const_assert_eq!(
+            core::mem::align_of::<i16>(),
+            core::mem::align_of::<super::I16Vec4>()
+        );
+        #[cfg(feature = "cuda")]
+        const_assert_eq!(8, core::mem::align_of::<super::I16Vec4>());
+    }
+}
diff --git a/src/i16/i16vec2.rs b/src/i16/i16vec2.rs
new file mode 100644
index 0000000..7f06c1c
--- /dev/null
+++ b/src/i16/i16vec2.rs
@@ -0,0 +1,1243 @@
+// Generated from vec.rs.tera template. Edit the template, not the generated file.
+
+use crate::{BVec2, I16Vec3, I64Vec2, IVec2, U16Vec2, U64Vec2, UVec2};
+
+#[cfg(not(target_arch = "spirv"))]
+use core::fmt;
+use core::iter::{Product, Sum};
+use core::{f32, ops::*};
+
+/// Creates a 2-dimensional vector.
+#[inline(always)]
+#[must_use]
+pub const fn i16vec2(x: i16, y: i16) -> I16Vec2 {
+    I16Vec2::new(x, y)
+}
+
+/// A 2-dimensional vector.
+#[cfg_attr(not(target_arch = "spirv"), derive(Hash))]
+#[derive(Clone, Copy, PartialEq, Eq)]
+#[cfg_attr(feature = "cuda", repr(align(4)))]
+#[cfg_attr(not(target_arch = "spirv"), repr(C))]
+#[cfg_attr(target_arch = "spirv", repr(simd))]
+pub struct I16Vec2 {
+    pub x: i16,
+    pub y: i16,
+}
+
+impl I16Vec2 {
+    /// All zeroes.
+    pub const ZERO: Self = Self::splat(0);
+
+    /// All ones.
+    pub const ONE: Self = Self::splat(1);
+
+    /// All negative ones.
+    pub const NEG_ONE: Self = Self::splat(-1);
+
+    /// All `i16::MIN`.
+    pub const MIN: Self = Self::splat(i16::MIN);
+
+    /// All `i16::MAX`.
+    pub const MAX: Self = Self::splat(i16::MAX);
+
+    /// A unit vector pointing along the positive X axis.
+    pub const X: Self = Self::new(1, 0);
+
+    /// A unit vector pointing along the positive Y axis.
+    pub const Y: Self = Self::new(0, 1);
+
+    /// A unit vector pointing along the negative X axis.
+    pub const NEG_X: Self = Self::new(-1, 0);
+
+    /// A unit vector pointing along the negative Y axis.
+    pub const NEG_Y: Self = Self::new(0, -1);
+
+    /// The unit axes.
+    pub const AXES: [Self; 2] = [Self::X, Self::Y];
+
+    /// Creates a new vector.
+    #[inline(always)]
+    #[must_use]
+    pub const fn new(x: i16, y: i16) -> Self {
+        Self { x, y }
+    }
+
+    /// Creates a vector with all elements set to `v`.
+    #[inline]
+    #[must_use]
+    pub const fn splat(v: i16) -> Self {
+        Self { x: v, y: v }
+    }
+
+    /// Creates a vector from the elements in `if_true` and `if_false`, selecting which to use
+    /// for each element of `self`.
+    ///
+    /// A true element in the mask uses the corresponding element from `if_true`, and false
+    /// uses the element from `if_false`.
+    #[inline]
+    #[must_use]
+    pub fn select(mask: BVec2, if_true: Self, if_false: Self) -> Self {
+        Self {
+            x: if mask.test(0) { if_true.x } else { if_false.x },
+            y: if mask.test(1) { if_true.y } else { if_false.y },
+        }
+    }
+
+    /// Creates a new vector from an array.
+    #[inline]
+    #[must_use]
+    pub const fn from_array(a: [i16; 2]) -> Self {
+        Self::new(a[0], a[1])
+    }
+
+    /// `[x, y]`
+    #[inline]
+    #[must_use]
+    pub const fn to_array(&self) -> [i16; 2] {
+        [self.x, self.y]
+    }
+
+    /// Creates a vector from the first 2 values in `slice`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `slice` is less than 2 elements long.
+    #[inline]
+    #[must_use]
+    pub const fn from_slice(slice: &[i16]) -> Self {
+        Self::new(slice[0], slice[1])
+    }
+
+    /// Writes the elements of `self` to the first 2 elements in `slice`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `slice` is less than 2 elements long.
+    #[inline]
+    pub fn write_to_slice(self, slice: &mut [i16]) {
+        slice[0] = self.x;
+        slice[1] = self.y;
+    }
+
+    /// Creates a 3D vector from `self` and the given `z` value.
+    #[inline]
+    #[must_use]
+    pub const fn extend(self, z: i16) -> I16Vec3 {
+        I16Vec3::new(self.x, self.y, z)
+    }
+
+    /// Computes the dot product of `self` and `rhs`.
+    #[inline]
+    #[must_use]
+    pub fn dot(self, rhs: Self) -> i16 {
+        (self.x * rhs.x) + (self.y * rhs.y)
+    }
+
+    /// Returns a vector where every component is the dot product of `self` and `rhs`.
+    #[inline]
+    #[must_use]
+    pub fn dot_into_vec(self, rhs: Self) -> Self {
+        Self::splat(self.dot(rhs))
+    }
+
+    /// Returns a vector containing the minimum values for each element of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.min(rhs.x), self.y.min(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub fn min(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.min(rhs.x),
+            y: self.y.min(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the maximum values for each element of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.max(rhs.x), self.y.max(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub fn max(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.max(rhs.x),
+            y: self.y.max(rhs.y),
+        }
+    }
+
+    /// Component-wise clamping of values, similar to [`i16::clamp`].
+    ///
+    /// Each element in `min` must be less-or-equal to the corresponding element in `max`.
+    ///
+    /// # Panics
+    ///
+    /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
+    #[inline]
+    #[must_use]
+    pub fn clamp(self, min: Self, max: Self) -> Self {
+        glam_assert!(min.cmple(max).all(), "clamp: expected min <= max");
+        self.max(min).min(max)
+    }
+
+    /// Returns the horizontal minimum of `self`.
+    ///
+    /// In other words this computes `min(x, y, ..)`.
+    #[inline]
+    #[must_use]
+    pub fn min_element(self) -> i16 {
+        self.x.min(self.y)
+    }
+
+    /// Returns the horizontal maximum of `self`.
+    ///
+    /// In other words this computes `max(x, y, ..)`.
+    #[inline]
+    #[must_use]
+    pub fn max_element(self) -> i16 {
+        self.x.max(self.y)
+    }
+
+    /// Returns a vector mask containing the result of a `==` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words, this computes `[self.x == rhs.x, self.y == rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpeq(self, rhs: Self) -> BVec2 {
+        BVec2::new(self.x.eq(&rhs.x), self.y.eq(&rhs.y))
+    }
+
+    /// Returns a vector mask containing the result of a `!=` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x != rhs.x, self.y != rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpne(self, rhs: Self) -> BVec2 {
+        BVec2::new(self.x.ne(&rhs.x), self.y.ne(&rhs.y))
+    }
+
+    /// Returns a vector mask containing the result of a `>=` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x >= rhs.x, self.y >= rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpge(self, rhs: Self) -> BVec2 {
+        BVec2::new(self.x.ge(&rhs.x), self.y.ge(&rhs.y))
+    }
+
+    /// Returns a vector mask containing the result of a `>` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x > rhs.x, self.y > rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpgt(self, rhs: Self) -> BVec2 {
+        BVec2::new(self.x.gt(&rhs.x), self.y.gt(&rhs.y))
+    }
+
+    /// Returns a vector mask containing the result of a `<=` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x <= rhs.x, self.y <= rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmple(self, rhs: Self) -> BVec2 {
+        BVec2::new(self.x.le(&rhs.x), self.y.le(&rhs.y))
+    }
+
+    /// Returns a vector mask containing the result of a `<` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x < rhs.x, self.y < rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmplt(self, rhs: Self) -> BVec2 {
+        BVec2::new(self.x.lt(&rhs.x), self.y.lt(&rhs.y))
+    }
+
+    /// Returns a vector containing the absolute value of each element of `self`.
+    #[inline]
+    #[must_use]
+    pub fn abs(self) -> Self {
+        Self {
+            x: self.x.abs(),
+            y: self.y.abs(),
+        }
+    }
+
+    /// Returns a vector with elements representing the sign of `self`.
+    ///
+    ///  - `0` if the number is zero
+    ///  - `1` if the number is positive
+    ///  - `-1` if the number is negative
+    #[inline]
+    #[must_use]
+    pub fn signum(self) -> Self {
+        Self {
+            x: self.x.signum(),
+            y: self.y.signum(),
+        }
+    }
+
+    /// Returns a bitmask with the lowest 2 bits set to the sign bits from the elements of `self`.
+    ///
+    /// A negative element results in a `1` bit and a positive element in a `0` bit.  Element `x` goes
+    /// into the first lowest bit, element `y` into the second, etc.
+    #[inline]
+    #[must_use]
+    pub fn is_negative_bitmask(self) -> u32 {
+        (self.x.is_negative() as u32) | (self.y.is_negative() as u32) << 1
+    }
+
+    /// Computes the squared length of `self`.
+    #[doc(alias = "magnitude2")]
+    #[inline]
+    #[must_use]
+    pub fn length_squared(self) -> i16 {
+        self.dot(self)
+    }
+
+    /// Compute the squared euclidean distance between two points in space.
+    #[inline]
+    #[must_use]
+    pub fn distance_squared(self, rhs: Self) -> i16 {
+        (self - rhs).length_squared()
+    }
+
+    /// Returns the element-wise quotient of [Euclidean division] of `self` by `rhs`.
+    ///
+    /// # Panics
+    /// This function will panic if any `rhs` element is 0 or the division results in overflow.
+    #[inline]
+    #[must_use]
+    pub fn div_euclid(self, rhs: Self) -> Self {
+        Self::new(self.x.div_euclid(rhs.x), self.y.div_euclid(rhs.y))
+    }
+
+    /// Returns the element-wise remainder of [Euclidean division] of `self` by `rhs`.
+    ///
+    /// # Panics
+    /// This function will panic if any `rhs` element is 0 or the division results in overflow.
+    ///
+    /// [Euclidean division]: i16::rem_euclid
+    #[inline]
+    #[must_use]
+    pub fn rem_euclid(self, rhs: Self) -> Self {
+        Self::new(self.x.rem_euclid(rhs.x), self.y.rem_euclid(rhs.y))
+    }
+
+    /// Returns a vector that is equal to `self` rotated by 90 degrees.
+    #[inline]
+    #[must_use]
+    pub fn perp(self) -> Self {
+        Self {
+            x: -self.y,
+            y: self.x,
+        }
+    }
+
+    /// The perpendicular dot product of `self` and `rhs`.
+    /// Also known as the wedge product, 2D cross product, and determinant.
+    #[doc(alias = "wedge")]
+    #[doc(alias = "cross")]
+    #[doc(alias = "determinant")]
+    #[inline]
+    #[must_use]
+    pub fn perp_dot(self, rhs: Self) -> i16 {
+        (self.x * rhs.y) - (self.y * rhs.x)
+    }
+
+    /// Returns `rhs` rotated by the angle of `self`. If `self` is normalized,
+    /// then this just rotation. This is what you usually want. Otherwise,
+    /// it will be like a rotation with a multiplication by `self`'s length.
+    #[inline]
+    #[must_use]
+    pub fn rotate(self, rhs: Self) -> Self {
+        Self {
+            x: self.x * rhs.x - self.y * rhs.y,
+            y: self.y * rhs.x + self.x * rhs.y,
+        }
+    }
+
+    /// Casts all elements of `self` to `f32`.
+    #[inline]
+    #[must_use]
+    pub fn as_vec2(&self) -> crate::Vec2 {
+        crate::Vec2::new(self.x as f32, self.y as f32)
+    }
+
+    /// Casts all elements of `self` to `f64`.
+    #[inline]
+    #[must_use]
+    pub fn as_dvec2(&self) -> crate::DVec2 {
+        crate::DVec2::new(self.x as f64, self.y as f64)
+    }
+
+    /// Casts all elements of `self` to `u16`.
+    #[inline]
+    #[must_use]
+    pub fn as_u16vec2(&self) -> crate::U16Vec2 {
+        crate::U16Vec2::new(self.x as u16, self.y as u16)
+    }
+
+    /// Casts all elements of `self` to `i32`.
+    #[inline]
+    #[must_use]
+    pub fn as_ivec2(&self) -> crate::IVec2 {
+        crate::IVec2::new(self.x as i32, self.y as i32)
+    }
+
+    /// Casts all elements of `self` to `u32`.
+    #[inline]
+    #[must_use]
+    pub fn as_uvec2(&self) -> crate::UVec2 {
+        crate::UVec2::new(self.x as u32, self.y as u32)
+    }
+
+    /// Casts all elements of `self` to `i64`.
+    #[inline]
+    #[must_use]
+    pub fn as_i64vec2(&self) -> crate::I64Vec2 {
+        crate::I64Vec2::new(self.x as i64, self.y as i64)
+    }
+
+    /// Casts all elements of `self` to `u64`.
+    #[inline]
+    #[must_use]
+    pub fn as_u64vec2(&self) -> crate::U64Vec2 {
+        crate::U64Vec2::new(self.x as u64, self.y as u64)
+    }
+
+    /// Returns a vector containing the wrapping addition of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_add(rhs.x), self.y.wrapping_add(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_add(rhs.x),
+            y: self.y.wrapping_add(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the wrapping subtraction of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_sub(rhs.x), self.y.wrapping_sub(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_sub(rhs.x),
+            y: self.y.wrapping_sub(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the wrapping multiplication of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_mul(rhs.x), self.y.wrapping_mul(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_mul(rhs.x),
+            y: self.y.wrapping_mul(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the wrapping division of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_div(rhs.x), self.y.wrapping_div(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_div(rhs.x),
+            y: self.y.wrapping_div(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the saturating addition of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_add(rhs.x), self.y.saturating_add(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_add(rhs.x),
+            y: self.y.saturating_add(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the saturating subtraction of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_sub(rhs.x), self.y.saturating_sub(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_sub(rhs.x),
+            y: self.y.saturating_sub(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the saturating multiplication of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_mul(rhs.x), self.y.saturating_mul(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_mul(rhs.x),
+            y: self.y.saturating_mul(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the saturating division of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_div(rhs.x), self.y.saturating_div(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_div(rhs.x),
+            y: self.y.saturating_div(rhs.y),
+        }
+    }
+}
+
+impl Default for I16Vec2 {
+    #[inline(always)]
+    fn default() -> Self {
+        Self::ZERO
+    }
+}
+
+impl Div<I16Vec2> for I16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.div(rhs.x),
+            y: self.y.div(rhs.y),
+        }
+    }
+}
+
+impl DivAssign<I16Vec2> for I16Vec2 {
+    #[inline]
+    fn div_assign(&mut self, rhs: Self) {
+        self.x.div_assign(rhs.x);
+        self.y.div_assign(rhs.y);
+    }
+}
+
+impl Div<i16> for I16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn div(self, rhs: i16) -> Self {
+        Self {
+            x: self.x.div(rhs),
+            y: self.y.div(rhs),
+        }
+    }
+}
+
+impl DivAssign<i16> for I16Vec2 {
+    #[inline]
+    fn div_assign(&mut self, rhs: i16) {
+        self.x.div_assign(rhs);
+        self.y.div_assign(rhs);
+    }
+}
+
+impl Div<I16Vec2> for i16 {
+    type Output = I16Vec2;
+    #[inline]
+    fn div(self, rhs: I16Vec2) -> I16Vec2 {
+        I16Vec2 {
+            x: self.div(rhs.x),
+            y: self.div(rhs.y),
+        }
+    }
+}
+
+impl Mul<I16Vec2> for I16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.mul(rhs.x),
+            y: self.y.mul(rhs.y),
+        }
+    }
+}
+
+impl MulAssign<I16Vec2> for I16Vec2 {
+    #[inline]
+    fn mul_assign(&mut self, rhs: Self) {
+        self.x.mul_assign(rhs.x);
+        self.y.mul_assign(rhs.y);
+    }
+}
+
+impl Mul<i16> for I16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn mul(self, rhs: i16) -> Self {
+        Self {
+            x: self.x.mul(rhs),
+            y: self.y.mul(rhs),
+        }
+    }
+}
+
+impl MulAssign<i16> for I16Vec2 {
+    #[inline]
+    fn mul_assign(&mut self, rhs: i16) {
+        self.x.mul_assign(rhs);
+        self.y.mul_assign(rhs);
+    }
+}
+
+impl Mul<I16Vec2> for i16 {
+    type Output = I16Vec2;
+    #[inline]
+    fn mul(self, rhs: I16Vec2) -> I16Vec2 {
+        I16Vec2 {
+            x: self.mul(rhs.x),
+            y: self.mul(rhs.y),
+        }
+    }
+}
+
+impl Add<I16Vec2> for I16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.add(rhs.x),
+            y: self.y.add(rhs.y),
+        }
+    }
+}
+
+impl AddAssign<I16Vec2> for I16Vec2 {
+    #[inline]
+    fn add_assign(&mut self, rhs: Self) {
+        self.x.add_assign(rhs.x);
+        self.y.add_assign(rhs.y);
+    }
+}
+
+impl Add<i16> for I16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn add(self, rhs: i16) -> Self {
+        Self {
+            x: self.x.add(rhs),
+            y: self.y.add(rhs),
+        }
+    }
+}
+
+impl AddAssign<i16> for I16Vec2 {
+    #[inline]
+    fn add_assign(&mut self, rhs: i16) {
+        self.x.add_assign(rhs);
+        self.y.add_assign(rhs);
+    }
+}
+
+impl Add<I16Vec2> for i16 {
+    type Output = I16Vec2;
+    #[inline]
+    fn add(self, rhs: I16Vec2) -> I16Vec2 {
+        I16Vec2 {
+            x: self.add(rhs.x),
+            y: self.add(rhs.y),
+        }
+    }
+}
+
+impl Sub<I16Vec2> for I16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.sub(rhs.x),
+            y: self.y.sub(rhs.y),
+        }
+    }
+}
+
+impl SubAssign<I16Vec2> for I16Vec2 {
+    #[inline]
+    fn sub_assign(&mut self, rhs: I16Vec2) {
+        self.x.sub_assign(rhs.x);
+        self.y.sub_assign(rhs.y);
+    }
+}
+
+impl Sub<i16> for I16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn sub(self, rhs: i16) -> Self {
+        Self {
+            x: self.x.sub(rhs),
+            y: self.y.sub(rhs),
+        }
+    }
+}
+
+impl SubAssign<i16> for I16Vec2 {
+    #[inline]
+    fn sub_assign(&mut self, rhs: i16) {
+        self.x.sub_assign(rhs);
+        self.y.sub_assign(rhs);
+    }
+}
+
+impl Sub<I16Vec2> for i16 {
+    type Output = I16Vec2;
+    #[inline]
+    fn sub(self, rhs: I16Vec2) -> I16Vec2 {
+        I16Vec2 {
+            x: self.sub(rhs.x),
+            y: self.sub(rhs.y),
+        }
+    }
+}
+
+impl Rem<I16Vec2> for I16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn rem(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.rem(rhs.x),
+            y: self.y.rem(rhs.y),
+        }
+    }
+}
+
+impl RemAssign<I16Vec2> for I16Vec2 {
+    #[inline]
+    fn rem_assign(&mut self, rhs: Self) {
+        self.x.rem_assign(rhs.x);
+        self.y.rem_assign(rhs.y);
+    }
+}
+
+impl Rem<i16> for I16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn rem(self, rhs: i16) -> Self {
+        Self {
+            x: self.x.rem(rhs),
+            y: self.y.rem(rhs),
+        }
+    }
+}
+
+impl RemAssign<i16> for I16Vec2 {
+    #[inline]
+    fn rem_assign(&mut self, rhs: i16) {
+        self.x.rem_assign(rhs);
+        self.y.rem_assign(rhs);
+    }
+}
+
+impl Rem<I16Vec2> for i16 {
+    type Output = I16Vec2;
+    #[inline]
+    fn rem(self, rhs: I16Vec2) -> I16Vec2 {
+        I16Vec2 {
+            x: self.rem(rhs.x),
+            y: self.rem(rhs.y),
+        }
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl AsRef<[i16; 2]> for I16Vec2 {
+    #[inline]
+    fn as_ref(&self) -> &[i16; 2] {
+        unsafe { &*(self as *const I16Vec2 as *const [i16; 2]) }
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl AsMut<[i16; 2]> for I16Vec2 {
+    #[inline]
+    fn as_mut(&mut self) -> &mut [i16; 2] {
+        unsafe { &mut *(self as *mut I16Vec2 as *mut [i16; 2]) }
+    }
+}
+
+impl Sum for I16Vec2 {
+    #[inline]
+    fn sum<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = Self>,
+    {
+        iter.fold(Self::ZERO, Self::add)
+    }
+}
+
+impl<'a> Sum<&'a Self> for I16Vec2 {
+    #[inline]
+    fn sum<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = &'a Self>,
+    {
+        iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
+    }
+}
+
+impl Product for I16Vec2 {
+    #[inline]
+    fn product<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = Self>,
+    {
+        iter.fold(Self::ONE, Self::mul)
+    }
+}
+
+impl<'a> Product<&'a Self> for I16Vec2 {
+    #[inline]
+    fn product<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = &'a Self>,
+    {
+        iter.fold(Self::ONE, |a, &b| Self::mul(a, b))
+    }
+}
+
+impl Neg for I16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn neg(self) -> Self {
+        Self {
+            x: self.x.neg(),
+            y: self.y.neg(),
+        }
+    }
+}
+
+impl Not for I16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn not(self) -> Self::Output {
+        Self {
+            x: self.x.not(),
+            y: self.y.not(),
+        }
+    }
+}
+
+impl BitAnd for I16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn bitand(self, rhs: Self) -> Self::Output {
+        Self {
+            x: self.x.bitand(rhs.x),
+            y: self.y.bitand(rhs.y),
+        }
+    }
+}
+
+impl BitOr for I16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn bitor(self, rhs: Self) -> Self::Output {
+        Self {
+            x: self.x.bitor(rhs.x),
+            y: self.y.bitor(rhs.y),
+        }
+    }
+}
+
+impl BitXor for I16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn bitxor(self, rhs: Self) -> Self::Output {
+        Self {
+            x: self.x.bitxor(rhs.x),
+            y: self.y.bitxor(rhs.y),
+        }
+    }
+}
+
+impl BitAnd<i16> for I16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn bitand(self, rhs: i16) -> Self::Output {
+        Self {
+            x: self.x.bitand(rhs),
+            y: self.y.bitand(rhs),
+        }
+    }
+}
+
+impl BitOr<i16> for I16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn bitor(self, rhs: i16) -> Self::Output {
+        Self {
+            x: self.x.bitor(rhs),
+            y: self.y.bitor(rhs),
+        }
+    }
+}
+
+impl BitXor<i16> for I16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn bitxor(self, rhs: i16) -> Self::Output {
+        Self {
+            x: self.x.bitxor(rhs),
+            y: self.y.bitxor(rhs),
+        }
+    }
+}
+
+impl Shl<i8> for I16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i8) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i8> for I16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i8) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+        }
+    }
+}
+
+impl Shl<i16> for I16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i16) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i16> for I16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i16) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+        }
+    }
+}
+
+impl Shl<i32> for I16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i32) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i32> for I16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i32) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+        }
+    }
+}
+
+impl Shl<i64> for I16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i64> for I16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u8> for I16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u8) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u8> for I16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u8) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u16> for I16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u16) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u16> for I16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u16) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u32> for I16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u32) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u32> for I16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u32) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u64> for I16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u64> for I16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+        }
+    }
+}
+
+impl Shl<crate::IVec2> for I16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: crate::IVec2) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs.x),
+            y: self.y.shl(rhs.y),
+        }
+    }
+}
+
+impl Shr<crate::IVec2> for I16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: crate::IVec2) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs.x),
+            y: self.y.shr(rhs.y),
+        }
+    }
+}
+
+impl Shl<crate::UVec2> for I16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: crate::UVec2) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs.x),
+            y: self.y.shl(rhs.y),
+        }
+    }
+}
+
+impl Shr<crate::UVec2> for I16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: crate::UVec2) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs.x),
+            y: self.y.shr(rhs.y),
+        }
+    }
+}
+
+impl Index<usize> for I16Vec2 {
+    type Output = i16;
+    #[inline]
+    fn index(&self, index: usize) -> &Self::Output {
+        match index {
+            0 => &self.x,
+            1 => &self.y,
+            _ => panic!("index out of bounds"),
+        }
+    }
+}
+
+impl IndexMut<usize> for I16Vec2 {
+    #[inline]
+    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
+        match index {
+            0 => &mut self.x,
+            1 => &mut self.y,
+            _ => panic!("index out of bounds"),
+        }
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl fmt::Display for I16Vec2 {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "[{}, {}]", self.x, self.y)
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl fmt::Debug for I16Vec2 {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt.debug_tuple(stringify!(I16Vec2))
+            .field(&self.x)
+            .field(&self.y)
+            .finish()
+    }
+}
+
+impl From<[i16; 2]> for I16Vec2 {
+    #[inline]
+    fn from(a: [i16; 2]) -> Self {
+        Self::new(a[0], a[1])
+    }
+}
+
+impl From<I16Vec2> for [i16; 2] {
+    #[inline]
+    fn from(v: I16Vec2) -> Self {
+        [v.x, v.y]
+    }
+}
+
+impl From<(i16, i16)> for I16Vec2 {
+    #[inline]
+    fn from(t: (i16, i16)) -> Self {
+        Self::new(t.0, t.1)
+    }
+}
+
+impl From<I16Vec2> for (i16, i16) {
+    #[inline]
+    fn from(v: I16Vec2) -> Self {
+        (v.x, v.y)
+    }
+}
+
+impl TryFrom<U16Vec2> for I16Vec2 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: U16Vec2) -> Result<Self, Self::Error> {
+        Ok(Self::new(i16::try_from(v.x)?, i16::try_from(v.y)?))
+    }
+}
+
+impl TryFrom<IVec2> for I16Vec2 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: IVec2) -> Result<Self, Self::Error> {
+        Ok(Self::new(i16::try_from(v.x)?, i16::try_from(v.y)?))
+    }
+}
+
+impl TryFrom<UVec2> for I16Vec2 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: UVec2) -> Result<Self, Self::Error> {
+        Ok(Self::new(i16::try_from(v.x)?, i16::try_from(v.y)?))
+    }
+}
+
+impl TryFrom<I64Vec2> for I16Vec2 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: I64Vec2) -> Result<Self, Self::Error> {
+        Ok(Self::new(i16::try_from(v.x)?, i16::try_from(v.y)?))
+    }
+}
+
+impl TryFrom<U64Vec2> for I16Vec2 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: U64Vec2) -> Result<Self, Self::Error> {
+        Ok(Self::new(i16::try_from(v.x)?, i16::try_from(v.y)?))
+    }
+}
diff --git a/src/i16/i16vec3.rs b/src/i16/i16vec3.rs
new file mode 100644
index 0000000..5bdc6a7
--- /dev/null
+++ b/src/i16/i16vec3.rs
@@ -0,0 +1,1363 @@
+// Generated from vec.rs.tera template. Edit the template, not the generated file.
+
+use crate::{BVec3, I16Vec2, I16Vec4, I64Vec3, IVec3, U16Vec3, U64Vec3, UVec3};
+
+#[cfg(not(target_arch = "spirv"))]
+use core::fmt;
+use core::iter::{Product, Sum};
+use core::{f32, ops::*};
+
+/// Creates a 3-dimensional vector.
+#[inline(always)]
+#[must_use]
+pub const fn i16vec3(x: i16, y: i16, z: i16) -> I16Vec3 {
+    I16Vec3::new(x, y, z)
+}
+
+/// A 3-dimensional vector.
+#[cfg_attr(not(target_arch = "spirv"), derive(Hash))]
+#[derive(Clone, Copy, PartialEq, Eq)]
+#[cfg_attr(not(target_arch = "spirv"), repr(C))]
+#[cfg_attr(target_arch = "spirv", repr(simd))]
+pub struct I16Vec3 {
+    pub x: i16,
+    pub y: i16,
+    pub z: i16,
+}
+
+impl I16Vec3 {
+    /// All zeroes.
+    pub const ZERO: Self = Self::splat(0);
+
+    /// All ones.
+    pub const ONE: Self = Self::splat(1);
+
+    /// All negative ones.
+    pub const NEG_ONE: Self = Self::splat(-1);
+
+    /// All `i16::MIN`.
+    pub const MIN: Self = Self::splat(i16::MIN);
+
+    /// All `i16::MAX`.
+    pub const MAX: Self = Self::splat(i16::MAX);
+
+    /// A unit vector pointing along the positive X axis.
+    pub const X: Self = Self::new(1, 0, 0);
+
+    /// A unit vector pointing along the positive Y axis.
+    pub const Y: Self = Self::new(0, 1, 0);
+
+    /// A unit vector pointing along the positive Z axis.
+    pub const Z: Self = Self::new(0, 0, 1);
+
+    /// A unit vector pointing along the negative X axis.
+    pub const NEG_X: Self = Self::new(-1, 0, 0);
+
+    /// A unit vector pointing along the negative Y axis.
+    pub const NEG_Y: Self = Self::new(0, -1, 0);
+
+    /// A unit vector pointing along the negative Z axis.
+    pub const NEG_Z: Self = Self::new(0, 0, -1);
+
+    /// The unit axes.
+    pub const AXES: [Self; 3] = [Self::X, Self::Y, Self::Z];
+
+    /// Creates a new vector.
+    #[inline(always)]
+    #[must_use]
+    pub const fn new(x: i16, y: i16, z: i16) -> Self {
+        Self { x, y, z }
+    }
+
+    /// Creates a vector with all elements set to `v`.
+    #[inline]
+    #[must_use]
+    pub const fn splat(v: i16) -> Self {
+        Self { x: v, y: v, z: v }
+    }
+
+    /// Creates a vector from the elements in `if_true` and `if_false`, selecting which to use
+    /// for each element of `self`.
+    ///
+    /// A true element in the mask uses the corresponding element from `if_true`, and false
+    /// uses the element from `if_false`.
+    #[inline]
+    #[must_use]
+    pub fn select(mask: BVec3, if_true: Self, if_false: Self) -> Self {
+        Self {
+            x: if mask.test(0) { if_true.x } else { if_false.x },
+            y: if mask.test(1) { if_true.y } else { if_false.y },
+            z: if mask.test(2) { if_true.z } else { if_false.z },
+        }
+    }
+
+    /// Creates a new vector from an array.
+    #[inline]
+    #[must_use]
+    pub const fn from_array(a: [i16; 3]) -> Self {
+        Self::new(a[0], a[1], a[2])
+    }
+
+    /// `[x, y, z]`
+    #[inline]
+    #[must_use]
+    pub const fn to_array(&self) -> [i16; 3] {
+        [self.x, self.y, self.z]
+    }
+
+    /// Creates a vector from the first 3 values in `slice`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `slice` is less than 3 elements long.
+    #[inline]
+    #[must_use]
+    pub const fn from_slice(slice: &[i16]) -> Self {
+        Self::new(slice[0], slice[1], slice[2])
+    }
+
+    /// Writes the elements of `self` to the first 3 elements in `slice`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `slice` is less than 3 elements long.
+    #[inline]
+    pub fn write_to_slice(self, slice: &mut [i16]) {
+        slice[0] = self.x;
+        slice[1] = self.y;
+        slice[2] = self.z;
+    }
+
+    /// Internal method for creating a 3D vector from a 4D vector, discarding `w`.
+    #[allow(dead_code)]
+    #[inline]
+    #[must_use]
+    pub(crate) fn from_vec4(v: I16Vec4) -> Self {
+        Self {
+            x: v.x,
+            y: v.y,
+            z: v.z,
+        }
+    }
+
+    /// Creates a 4D vector from `self` and the given `w` value.
+    #[inline]
+    #[must_use]
+    pub fn extend(self, w: i16) -> I16Vec4 {
+        I16Vec4::new(self.x, self.y, self.z, w)
+    }
+
+    /// Creates a 2D vector from the `x` and `y` elements of `self`, discarding `z`.
+    ///
+    /// Truncation may also be performed by using [`self.xy()`][crate::swizzles::Vec3Swizzles::xy()].
+    #[inline]
+    #[must_use]
+    pub fn truncate(self) -> I16Vec2 {
+        use crate::swizzles::Vec3Swizzles;
+        self.xy()
+    }
+
+    /// Computes the dot product of `self` and `rhs`.
+    #[inline]
+    #[must_use]
+    pub fn dot(self, rhs: Self) -> i16 {
+        (self.x * rhs.x) + (self.y * rhs.y) + (self.z * rhs.z)
+    }
+
+    /// Returns a vector where every component is the dot product of `self` and `rhs`.
+    #[inline]
+    #[must_use]
+    pub fn dot_into_vec(self, rhs: Self) -> Self {
+        Self::splat(self.dot(rhs))
+    }
+
+    /// Computes the cross product of `self` and `rhs`.
+    #[inline]
+    #[must_use]
+    pub fn cross(self, rhs: Self) -> Self {
+        Self {
+            x: self.y * rhs.z - rhs.y * self.z,
+            y: self.z * rhs.x - rhs.z * self.x,
+            z: self.x * rhs.y - rhs.x * self.y,
+        }
+    }
+
+    /// Returns a vector containing the minimum values for each element of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.min(rhs.x), self.y.min(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub fn min(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.min(rhs.x),
+            y: self.y.min(rhs.y),
+            z: self.z.min(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the maximum values for each element of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.max(rhs.x), self.y.max(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub fn max(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.max(rhs.x),
+            y: self.y.max(rhs.y),
+            z: self.z.max(rhs.z),
+        }
+    }
+
+    /// Component-wise clamping of values, similar to [`i16::clamp`].
+    ///
+    /// Each element in `min` must be less-or-equal to the corresponding element in `max`.
+    ///
+    /// # Panics
+    ///
+    /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
+    #[inline]
+    #[must_use]
+    pub fn clamp(self, min: Self, max: Self) -> Self {
+        glam_assert!(min.cmple(max).all(), "clamp: expected min <= max");
+        self.max(min).min(max)
+    }
+
+    /// Returns the horizontal minimum of `self`.
+    ///
+    /// In other words this computes `min(x, y, ..)`.
+    #[inline]
+    #[must_use]
+    pub fn min_element(self) -> i16 {
+        self.x.min(self.y.min(self.z))
+    }
+
+    /// Returns the horizontal maximum of `self`.
+    ///
+    /// In other words this computes `max(x, y, ..)`.
+    #[inline]
+    #[must_use]
+    pub fn max_element(self) -> i16 {
+        self.x.max(self.y.max(self.z))
+    }
+
+    /// Returns a vector mask containing the result of a `==` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words, this computes `[self.x == rhs.x, self.y == rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpeq(self, rhs: Self) -> BVec3 {
+        BVec3::new(self.x.eq(&rhs.x), self.y.eq(&rhs.y), self.z.eq(&rhs.z))
+    }
+
+    /// Returns a vector mask containing the result of a `!=` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x != rhs.x, self.y != rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpne(self, rhs: Self) -> BVec3 {
+        BVec3::new(self.x.ne(&rhs.x), self.y.ne(&rhs.y), self.z.ne(&rhs.z))
+    }
+
+    /// Returns a vector mask containing the result of a `>=` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x >= rhs.x, self.y >= rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpge(self, rhs: Self) -> BVec3 {
+        BVec3::new(self.x.ge(&rhs.x), self.y.ge(&rhs.y), self.z.ge(&rhs.z))
+    }
+
+    /// Returns a vector mask containing the result of a `>` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x > rhs.x, self.y > rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpgt(self, rhs: Self) -> BVec3 {
+        BVec3::new(self.x.gt(&rhs.x), self.y.gt(&rhs.y), self.z.gt(&rhs.z))
+    }
+
+    /// Returns a vector mask containing the result of a `<=` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x <= rhs.x, self.y <= rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmple(self, rhs: Self) -> BVec3 {
+        BVec3::new(self.x.le(&rhs.x), self.y.le(&rhs.y), self.z.le(&rhs.z))
+    }
+
+    /// Returns a vector mask containing the result of a `<` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x < rhs.x, self.y < rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmplt(self, rhs: Self) -> BVec3 {
+        BVec3::new(self.x.lt(&rhs.x), self.y.lt(&rhs.y), self.z.lt(&rhs.z))
+    }
+
+    /// Returns a vector containing the absolute value of each element of `self`.
+    #[inline]
+    #[must_use]
+    pub fn abs(self) -> Self {
+        Self {
+            x: self.x.abs(),
+            y: self.y.abs(),
+            z: self.z.abs(),
+        }
+    }
+
+    /// Returns a vector with elements representing the sign of `self`.
+    ///
+    ///  - `0` if the number is zero
+    ///  - `1` if the number is positive
+    ///  - `-1` if the number is negative
+    #[inline]
+    #[must_use]
+    pub fn signum(self) -> Self {
+        Self {
+            x: self.x.signum(),
+            y: self.y.signum(),
+            z: self.z.signum(),
+        }
+    }
+
+    /// Returns a bitmask with the lowest 3 bits set to the sign bits from the elements of `self`.
+    ///
+    /// A negative element results in a `1` bit and a positive element in a `0` bit.  Element `x` goes
+    /// into the first lowest bit, element `y` into the second, etc.
+    #[inline]
+    #[must_use]
+    pub fn is_negative_bitmask(self) -> u32 {
+        (self.x.is_negative() as u32)
+            | (self.y.is_negative() as u32) << 1
+            | (self.z.is_negative() as u32) << 2
+    }
+
+    /// Computes the squared length of `self`.
+    #[doc(alias = "magnitude2")]
+    #[inline]
+    #[must_use]
+    pub fn length_squared(self) -> i16 {
+        self.dot(self)
+    }
+
+    /// Compute the squared euclidean distance between two points in space.
+    #[inline]
+    #[must_use]
+    pub fn distance_squared(self, rhs: Self) -> i16 {
+        (self - rhs).length_squared()
+    }
+
+    /// Returns the element-wise quotient of [Euclidean division] of `self` by `rhs`.
+    ///
+    /// # Panics
+    /// This function will panic if any `rhs` element is 0 or the division results in overflow.
+    #[inline]
+    #[must_use]
+    pub fn div_euclid(self, rhs: Self) -> Self {
+        Self::new(
+            self.x.div_euclid(rhs.x),
+            self.y.div_euclid(rhs.y),
+            self.z.div_euclid(rhs.z),
+        )
+    }
+
+    /// Returns the element-wise remainder of [Euclidean division] of `self` by `rhs`.
+    ///
+    /// # Panics
+    /// This function will panic if any `rhs` element is 0 or the division results in overflow.
+    ///
+    /// [Euclidean division]: i16::rem_euclid
+    #[inline]
+    #[must_use]
+    pub fn rem_euclid(self, rhs: Self) -> Self {
+        Self::new(
+            self.x.rem_euclid(rhs.x),
+            self.y.rem_euclid(rhs.y),
+            self.z.rem_euclid(rhs.z),
+        )
+    }
+
+    /// Casts all elements of `self` to `f32`.
+    #[inline]
+    #[must_use]
+    pub fn as_vec3(&self) -> crate::Vec3 {
+        crate::Vec3::new(self.x as f32, self.y as f32, self.z as f32)
+    }
+
+    /// Casts all elements of `self` to `f32`.
+    #[inline]
+    #[must_use]
+    pub fn as_vec3a(&self) -> crate::Vec3A {
+        crate::Vec3A::new(self.x as f32, self.y as f32, self.z as f32)
+    }
+
+    /// Casts all elements of `self` to `f64`.
+    #[inline]
+    #[must_use]
+    pub fn as_dvec3(&self) -> crate::DVec3 {
+        crate::DVec3::new(self.x as f64, self.y as f64, self.z as f64)
+    }
+
+    /// Casts all elements of `self` to `u16`.
+    #[inline]
+    #[must_use]
+    pub fn as_u16vec3(&self) -> crate::U16Vec3 {
+        crate::U16Vec3::new(self.x as u16, self.y as u16, self.z as u16)
+    }
+
+    /// Casts all elements of `self` to `i32`.
+    #[inline]
+    #[must_use]
+    pub fn as_ivec3(&self) -> crate::IVec3 {
+        crate::IVec3::new(self.x as i32, self.y as i32, self.z as i32)
+    }
+
+    /// Casts all elements of `self` to `u32`.
+    #[inline]
+    #[must_use]
+    pub fn as_uvec3(&self) -> crate::UVec3 {
+        crate::UVec3::new(self.x as u32, self.y as u32, self.z as u32)
+    }
+
+    /// Casts all elements of `self` to `i64`.
+    #[inline]
+    #[must_use]
+    pub fn as_i64vec3(&self) -> crate::I64Vec3 {
+        crate::I64Vec3::new(self.x as i64, self.y as i64, self.z as i64)
+    }
+
+    /// Casts all elements of `self` to `u64`.
+    #[inline]
+    #[must_use]
+    pub fn as_u64vec3(&self) -> crate::U64Vec3 {
+        crate::U64Vec3::new(self.x as u64, self.y as u64, self.z as u64)
+    }
+
+    /// Returns a vector containing the wrapping addition of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_add(rhs.x), self.y.wrapping_add(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_add(rhs.x),
+            y: self.y.wrapping_add(rhs.y),
+            z: self.z.wrapping_add(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the wrapping subtraction of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_sub(rhs.x), self.y.wrapping_sub(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_sub(rhs.x),
+            y: self.y.wrapping_sub(rhs.y),
+            z: self.z.wrapping_sub(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the wrapping multiplication of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_mul(rhs.x), self.y.wrapping_mul(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_mul(rhs.x),
+            y: self.y.wrapping_mul(rhs.y),
+            z: self.z.wrapping_mul(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the wrapping division of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_div(rhs.x), self.y.wrapping_div(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_div(rhs.x),
+            y: self.y.wrapping_div(rhs.y),
+            z: self.z.wrapping_div(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the saturating addition of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_add(rhs.x), self.y.saturating_add(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_add(rhs.x),
+            y: self.y.saturating_add(rhs.y),
+            z: self.z.saturating_add(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the saturating subtraction of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_sub(rhs.x), self.y.saturating_sub(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_sub(rhs.x),
+            y: self.y.saturating_sub(rhs.y),
+            z: self.z.saturating_sub(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the saturating multiplication of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_mul(rhs.x), self.y.saturating_mul(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_mul(rhs.x),
+            y: self.y.saturating_mul(rhs.y),
+            z: self.z.saturating_mul(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the saturating division of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_div(rhs.x), self.y.saturating_div(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_div(rhs.x),
+            y: self.y.saturating_div(rhs.y),
+            z: self.z.saturating_div(rhs.z),
+        }
+    }
+}
+
+impl Default for I16Vec3 {
+    #[inline(always)]
+    fn default() -> Self {
+        Self::ZERO
+    }
+}
+
+impl Div<I16Vec3> for I16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.div(rhs.x),
+            y: self.y.div(rhs.y),
+            z: self.z.div(rhs.z),
+        }
+    }
+}
+
+impl DivAssign<I16Vec3> for I16Vec3 {
+    #[inline]
+    fn div_assign(&mut self, rhs: Self) {
+        self.x.div_assign(rhs.x);
+        self.y.div_assign(rhs.y);
+        self.z.div_assign(rhs.z);
+    }
+}
+
+impl Div<i16> for I16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn div(self, rhs: i16) -> Self {
+        Self {
+            x: self.x.div(rhs),
+            y: self.y.div(rhs),
+            z: self.z.div(rhs),
+        }
+    }
+}
+
+impl DivAssign<i16> for I16Vec3 {
+    #[inline]
+    fn div_assign(&mut self, rhs: i16) {
+        self.x.div_assign(rhs);
+        self.y.div_assign(rhs);
+        self.z.div_assign(rhs);
+    }
+}
+
+impl Div<I16Vec3> for i16 {
+    type Output = I16Vec3;
+    #[inline]
+    fn div(self, rhs: I16Vec3) -> I16Vec3 {
+        I16Vec3 {
+            x: self.div(rhs.x),
+            y: self.div(rhs.y),
+            z: self.div(rhs.z),
+        }
+    }
+}
+
+impl Mul<I16Vec3> for I16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.mul(rhs.x),
+            y: self.y.mul(rhs.y),
+            z: self.z.mul(rhs.z),
+        }
+    }
+}
+
+impl MulAssign<I16Vec3> for I16Vec3 {
+    #[inline]
+    fn mul_assign(&mut self, rhs: Self) {
+        self.x.mul_assign(rhs.x);
+        self.y.mul_assign(rhs.y);
+        self.z.mul_assign(rhs.z);
+    }
+}
+
+impl Mul<i16> for I16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn mul(self, rhs: i16) -> Self {
+        Self {
+            x: self.x.mul(rhs),
+            y: self.y.mul(rhs),
+            z: self.z.mul(rhs),
+        }
+    }
+}
+
+impl MulAssign<i16> for I16Vec3 {
+    #[inline]
+    fn mul_assign(&mut self, rhs: i16) {
+        self.x.mul_assign(rhs);
+        self.y.mul_assign(rhs);
+        self.z.mul_assign(rhs);
+    }
+}
+
+impl Mul<I16Vec3> for i16 {
+    type Output = I16Vec3;
+    #[inline]
+    fn mul(self, rhs: I16Vec3) -> I16Vec3 {
+        I16Vec3 {
+            x: self.mul(rhs.x),
+            y: self.mul(rhs.y),
+            z: self.mul(rhs.z),
+        }
+    }
+}
+
+impl Add<I16Vec3> for I16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.add(rhs.x),
+            y: self.y.add(rhs.y),
+            z: self.z.add(rhs.z),
+        }
+    }
+}
+
+impl AddAssign<I16Vec3> for I16Vec3 {
+    #[inline]
+    fn add_assign(&mut self, rhs: Self) {
+        self.x.add_assign(rhs.x);
+        self.y.add_assign(rhs.y);
+        self.z.add_assign(rhs.z);
+    }
+}
+
+impl Add<i16> for I16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn add(self, rhs: i16) -> Self {
+        Self {
+            x: self.x.add(rhs),
+            y: self.y.add(rhs),
+            z: self.z.add(rhs),
+        }
+    }
+}
+
+impl AddAssign<i16> for I16Vec3 {
+    #[inline]
+    fn add_assign(&mut self, rhs: i16) {
+        self.x.add_assign(rhs);
+        self.y.add_assign(rhs);
+        self.z.add_assign(rhs);
+    }
+}
+
+impl Add<I16Vec3> for i16 {
+    type Output = I16Vec3;
+    #[inline]
+    fn add(self, rhs: I16Vec3) -> I16Vec3 {
+        I16Vec3 {
+            x: self.add(rhs.x),
+            y: self.add(rhs.y),
+            z: self.add(rhs.z),
+        }
+    }
+}
+
+impl Sub<I16Vec3> for I16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.sub(rhs.x),
+            y: self.y.sub(rhs.y),
+            z: self.z.sub(rhs.z),
+        }
+    }
+}
+
+impl SubAssign<I16Vec3> for I16Vec3 {
+    #[inline]
+    fn sub_assign(&mut self, rhs: I16Vec3) {
+        self.x.sub_assign(rhs.x);
+        self.y.sub_assign(rhs.y);
+        self.z.sub_assign(rhs.z);
+    }
+}
+
+impl Sub<i16> for I16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn sub(self, rhs: i16) -> Self {
+        Self {
+            x: self.x.sub(rhs),
+            y: self.y.sub(rhs),
+            z: self.z.sub(rhs),
+        }
+    }
+}
+
+impl SubAssign<i16> for I16Vec3 {
+    #[inline]
+    fn sub_assign(&mut self, rhs: i16) {
+        self.x.sub_assign(rhs);
+        self.y.sub_assign(rhs);
+        self.z.sub_assign(rhs);
+    }
+}
+
+impl Sub<I16Vec3> for i16 {
+    type Output = I16Vec3;
+    #[inline]
+    fn sub(self, rhs: I16Vec3) -> I16Vec3 {
+        I16Vec3 {
+            x: self.sub(rhs.x),
+            y: self.sub(rhs.y),
+            z: self.sub(rhs.z),
+        }
+    }
+}
+
+impl Rem<I16Vec3> for I16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn rem(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.rem(rhs.x),
+            y: self.y.rem(rhs.y),
+            z: self.z.rem(rhs.z),
+        }
+    }
+}
+
+impl RemAssign<I16Vec3> for I16Vec3 {
+    #[inline]
+    fn rem_assign(&mut self, rhs: Self) {
+        self.x.rem_assign(rhs.x);
+        self.y.rem_assign(rhs.y);
+        self.z.rem_assign(rhs.z);
+    }
+}
+
+impl Rem<i16> for I16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn rem(self, rhs: i16) -> Self {
+        Self {
+            x: self.x.rem(rhs),
+            y: self.y.rem(rhs),
+            z: self.z.rem(rhs),
+        }
+    }
+}
+
+impl RemAssign<i16> for I16Vec3 {
+    #[inline]
+    fn rem_assign(&mut self, rhs: i16) {
+        self.x.rem_assign(rhs);
+        self.y.rem_assign(rhs);
+        self.z.rem_assign(rhs);
+    }
+}
+
+impl Rem<I16Vec3> for i16 {
+    type Output = I16Vec3;
+    #[inline]
+    fn rem(self, rhs: I16Vec3) -> I16Vec3 {
+        I16Vec3 {
+            x: self.rem(rhs.x),
+            y: self.rem(rhs.y),
+            z: self.rem(rhs.z),
+        }
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl AsRef<[i16; 3]> for I16Vec3 {
+    #[inline]
+    fn as_ref(&self) -> &[i16; 3] {
+        unsafe { &*(self as *const I16Vec3 as *const [i16; 3]) }
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl AsMut<[i16; 3]> for I16Vec3 {
+    #[inline]
+    fn as_mut(&mut self) -> &mut [i16; 3] {
+        unsafe { &mut *(self as *mut I16Vec3 as *mut [i16; 3]) }
+    }
+}
+
+impl Sum for I16Vec3 {
+    #[inline]
+    fn sum<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = Self>,
+    {
+        iter.fold(Self::ZERO, Self::add)
+    }
+}
+
+impl<'a> Sum<&'a Self> for I16Vec3 {
+    #[inline]
+    fn sum<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = &'a Self>,
+    {
+        iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
+    }
+}
+
+impl Product for I16Vec3 {
+    #[inline]
+    fn product<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = Self>,
+    {
+        iter.fold(Self::ONE, Self::mul)
+    }
+}
+
+impl<'a> Product<&'a Self> for I16Vec3 {
+    #[inline]
+    fn product<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = &'a Self>,
+    {
+        iter.fold(Self::ONE, |a, &b| Self::mul(a, b))
+    }
+}
+
+impl Neg for I16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn neg(self) -> Self {
+        Self {
+            x: self.x.neg(),
+            y: self.y.neg(),
+            z: self.z.neg(),
+        }
+    }
+}
+
+impl Not for I16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn not(self) -> Self::Output {
+        Self {
+            x: self.x.not(),
+            y: self.y.not(),
+            z: self.z.not(),
+        }
+    }
+}
+
+impl BitAnd for I16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn bitand(self, rhs: Self) -> Self::Output {
+        Self {
+            x: self.x.bitand(rhs.x),
+            y: self.y.bitand(rhs.y),
+            z: self.z.bitand(rhs.z),
+        }
+    }
+}
+
+impl BitOr for I16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn bitor(self, rhs: Self) -> Self::Output {
+        Self {
+            x: self.x.bitor(rhs.x),
+            y: self.y.bitor(rhs.y),
+            z: self.z.bitor(rhs.z),
+        }
+    }
+}
+
+impl BitXor for I16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn bitxor(self, rhs: Self) -> Self::Output {
+        Self {
+            x: self.x.bitxor(rhs.x),
+            y: self.y.bitxor(rhs.y),
+            z: self.z.bitxor(rhs.z),
+        }
+    }
+}
+
+impl BitAnd<i16> for I16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn bitand(self, rhs: i16) -> Self::Output {
+        Self {
+            x: self.x.bitand(rhs),
+            y: self.y.bitand(rhs),
+            z: self.z.bitand(rhs),
+        }
+    }
+}
+
+impl BitOr<i16> for I16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn bitor(self, rhs: i16) -> Self::Output {
+        Self {
+            x: self.x.bitor(rhs),
+            y: self.y.bitor(rhs),
+            z: self.z.bitor(rhs),
+        }
+    }
+}
+
+impl BitXor<i16> for I16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn bitxor(self, rhs: i16) -> Self::Output {
+        Self {
+            x: self.x.bitxor(rhs),
+            y: self.y.bitxor(rhs),
+            z: self.z.bitxor(rhs),
+        }
+    }
+}
+
+impl Shl<i8> for I16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i8) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i8> for I16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i8) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+        }
+    }
+}
+
+impl Shl<i16> for I16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i16) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i16> for I16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i16) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+        }
+    }
+}
+
+impl Shl<i32> for I16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i32) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i32> for I16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i32) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+        }
+    }
+}
+
+impl Shl<i64> for I16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i64> for I16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u8> for I16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u8) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u8> for I16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u8) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u16> for I16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u16) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u16> for I16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u16) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u32> for I16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u32) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u32> for I16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u32) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u64> for I16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u64> for I16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+        }
+    }
+}
+
+impl Shl<crate::IVec3> for I16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: crate::IVec3) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs.x),
+            y: self.y.shl(rhs.y),
+            z: self.z.shl(rhs.z),
+        }
+    }
+}
+
+impl Shr<crate::IVec3> for I16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: crate::IVec3) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs.x),
+            y: self.y.shr(rhs.y),
+            z: self.z.shr(rhs.z),
+        }
+    }
+}
+
+impl Shl<crate::UVec3> for I16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: crate::UVec3) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs.x),
+            y: self.y.shl(rhs.y),
+            z: self.z.shl(rhs.z),
+        }
+    }
+}
+
+impl Shr<crate::UVec3> for I16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: crate::UVec3) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs.x),
+            y: self.y.shr(rhs.y),
+            z: self.z.shr(rhs.z),
+        }
+    }
+}
+
+impl Index<usize> for I16Vec3 {
+    type Output = i16;
+    #[inline]
+    fn index(&self, index: usize) -> &Self::Output {
+        match index {
+            0 => &self.x,
+            1 => &self.y,
+            2 => &self.z,
+            _ => panic!("index out of bounds"),
+        }
+    }
+}
+
+impl IndexMut<usize> for I16Vec3 {
+    #[inline]
+    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
+        match index {
+            0 => &mut self.x,
+            1 => &mut self.y,
+            2 => &mut self.z,
+            _ => panic!("index out of bounds"),
+        }
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl fmt::Display for I16Vec3 {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "[{}, {}, {}]", self.x, self.y, self.z)
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl fmt::Debug for I16Vec3 {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt.debug_tuple(stringify!(I16Vec3))
+            .field(&self.x)
+            .field(&self.y)
+            .field(&self.z)
+            .finish()
+    }
+}
+
+impl From<[i16; 3]> for I16Vec3 {
+    #[inline]
+    fn from(a: [i16; 3]) -> Self {
+        Self::new(a[0], a[1], a[2])
+    }
+}
+
+impl From<I16Vec3> for [i16; 3] {
+    #[inline]
+    fn from(v: I16Vec3) -> Self {
+        [v.x, v.y, v.z]
+    }
+}
+
+impl From<(i16, i16, i16)> for I16Vec3 {
+    #[inline]
+    fn from(t: (i16, i16, i16)) -> Self {
+        Self::new(t.0, t.1, t.2)
+    }
+}
+
+impl From<I16Vec3> for (i16, i16, i16) {
+    #[inline]
+    fn from(v: I16Vec3) -> Self {
+        (v.x, v.y, v.z)
+    }
+}
+
+impl From<(I16Vec2, i16)> for I16Vec3 {
+    #[inline]
+    fn from((v, z): (I16Vec2, i16)) -> Self {
+        Self::new(v.x, v.y, z)
+    }
+}
+
+impl TryFrom<U16Vec3> for I16Vec3 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: U16Vec3) -> Result<Self, Self::Error> {
+        Ok(Self::new(
+            i16::try_from(v.x)?,
+            i16::try_from(v.y)?,
+            i16::try_from(v.z)?,
+        ))
+    }
+}
+
+impl TryFrom<IVec3> for I16Vec3 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: IVec3) -> Result<Self, Self::Error> {
+        Ok(Self::new(
+            i16::try_from(v.x)?,
+            i16::try_from(v.y)?,
+            i16::try_from(v.z)?,
+        ))
+    }
+}
+
+impl TryFrom<UVec3> for I16Vec3 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: UVec3) -> Result<Self, Self::Error> {
+        Ok(Self::new(
+            i16::try_from(v.x)?,
+            i16::try_from(v.y)?,
+            i16::try_from(v.z)?,
+        ))
+    }
+}
+
+impl TryFrom<I64Vec3> for I16Vec3 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: I64Vec3) -> Result<Self, Self::Error> {
+        Ok(Self::new(
+            i16::try_from(v.x)?,
+            i16::try_from(v.y)?,
+            i16::try_from(v.z)?,
+        ))
+    }
+}
+
+impl TryFrom<U64Vec3> for I16Vec3 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: U64Vec3) -> Result<Self, Self::Error> {
+        Ok(Self::new(
+            i16::try_from(v.x)?,
+            i16::try_from(v.y)?,
+            i16::try_from(v.z)?,
+        ))
+    }
+}
diff --git a/src/i16/i16vec4.rs b/src/i16/i16vec4.rs
new file mode 100644
index 0000000..9db87cc
--- /dev/null
+++ b/src/i16/i16vec4.rs
@@ -0,0 +1,1471 @@
+// Generated from vec.rs.tera template. Edit the template, not the generated file.
+
+use crate::{BVec4, I16Vec2, I16Vec3, I64Vec4, IVec4, U16Vec4, U64Vec4, UVec4};
+
+#[cfg(not(target_arch = "spirv"))]
+use core::fmt;
+use core::iter::{Product, Sum};
+use core::{f32, ops::*};
+
+/// Creates a 4-dimensional vector.
+#[inline(always)]
+#[must_use]
+pub const fn i16vec4(x: i16, y: i16, z: i16, w: i16) -> I16Vec4 {
+    I16Vec4::new(x, y, z, w)
+}
+
+/// A 4-dimensional vector.
+#[cfg_attr(not(target_arch = "spirv"), derive(Hash))]
+#[derive(Clone, Copy, PartialEq, Eq)]
+#[cfg_attr(feature = "cuda", repr(align(8)))]
+#[cfg_attr(not(target_arch = "spirv"), repr(C))]
+#[cfg_attr(target_arch = "spirv", repr(simd))]
+pub struct I16Vec4 {
+    pub x: i16,
+    pub y: i16,
+    pub z: i16,
+    pub w: i16,
+}
+
+impl I16Vec4 {
+    /// All zeroes.
+    pub const ZERO: Self = Self::splat(0);
+
+    /// All ones.
+    pub const ONE: Self = Self::splat(1);
+
+    /// All negative ones.
+    pub const NEG_ONE: Self = Self::splat(-1);
+
+    /// All `i16::MIN`.
+    pub const MIN: Self = Self::splat(i16::MIN);
+
+    /// All `i16::MAX`.
+    pub const MAX: Self = Self::splat(i16::MAX);
+
+    /// A unit vector pointing along the positive X axis.
+    pub const X: Self = Self::new(1, 0, 0, 0);
+
+    /// A unit vector pointing along the positive Y axis.
+    pub const Y: Self = Self::new(0, 1, 0, 0);
+
+    /// A unit vector pointing along the positive Z axis.
+    pub const Z: Self = Self::new(0, 0, 1, 0);
+
+    /// A unit vector pointing along the positive W axis.
+    pub const W: Self = Self::new(0, 0, 0, 1);
+
+    /// A unit vector pointing along the negative X axis.
+    pub const NEG_X: Self = Self::new(-1, 0, 0, 0);
+
+    /// A unit vector pointing along the negative Y axis.
+    pub const NEG_Y: Self = Self::new(0, -1, 0, 0);
+
+    /// A unit vector pointing along the negative Z axis.
+    pub const NEG_Z: Self = Self::new(0, 0, -1, 0);
+
+    /// A unit vector pointing along the negative W axis.
+    pub const NEG_W: Self = Self::new(0, 0, 0, -1);
+
+    /// The unit axes.
+    pub const AXES: [Self; 4] = [Self::X, Self::Y, Self::Z, Self::W];
+
+    /// Creates a new vector.
+    #[inline(always)]
+    #[must_use]
+    pub const fn new(x: i16, y: i16, z: i16, w: i16) -> Self {
+        Self { x, y, z, w }
+    }
+
+    /// Creates a vector with all elements set to `v`.
+    #[inline]
+    #[must_use]
+    pub const fn splat(v: i16) -> Self {
+        Self {
+            x: v,
+
+            y: v,
+
+            z: v,
+
+            w: v,
+        }
+    }
+
+    /// Creates a vector from the elements in `if_true` and `if_false`, selecting which to use
+    /// for each element of `self`.
+    ///
+    /// A true element in the mask uses the corresponding element from `if_true`, and false
+    /// uses the element from `if_false`.
+    #[inline]
+    #[must_use]
+    pub fn select(mask: BVec4, if_true: Self, if_false: Self) -> Self {
+        Self {
+            x: if mask.test(0) { if_true.x } else { if_false.x },
+            y: if mask.test(1) { if_true.y } else { if_false.y },
+            z: if mask.test(2) { if_true.z } else { if_false.z },
+            w: if mask.test(3) { if_true.w } else { if_false.w },
+        }
+    }
+
+    /// Creates a new vector from an array.
+    #[inline]
+    #[must_use]
+    pub const fn from_array(a: [i16; 4]) -> Self {
+        Self::new(a[0], a[1], a[2], a[3])
+    }
+
+    /// `[x, y, z, w]`
+    #[inline]
+    #[must_use]
+    pub const fn to_array(&self) -> [i16; 4] {
+        [self.x, self.y, self.z, self.w]
+    }
+
+    /// Creates a vector from the first 4 values in `slice`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `slice` is less than 4 elements long.
+    #[inline]
+    #[must_use]
+    pub const fn from_slice(slice: &[i16]) -> Self {
+        Self::new(slice[0], slice[1], slice[2], slice[3])
+    }
+
+    /// Writes the elements of `self` to the first 4 elements in `slice`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `slice` is less than 4 elements long.
+    #[inline]
+    pub fn write_to_slice(self, slice: &mut [i16]) {
+        slice[0] = self.x;
+        slice[1] = self.y;
+        slice[2] = self.z;
+        slice[3] = self.w;
+    }
+
+    /// Creates a 3D vector from the `x`, `y` and `z` elements of `self`, discarding `w`.
+    ///
+    /// Truncation to [`I16Vec3`] may also be performed by using [`self.xyz()`][crate::swizzles::Vec4Swizzles::xyz()].
+    #[inline]
+    #[must_use]
+    pub fn truncate(self) -> I16Vec3 {
+        use crate::swizzles::Vec4Swizzles;
+        self.xyz()
+    }
+
+    /// Computes the dot product of `self` and `rhs`.
+    #[inline]
+    #[must_use]
+    pub fn dot(self, rhs: Self) -> i16 {
+        (self.x * rhs.x) + (self.y * rhs.y) + (self.z * rhs.z) + (self.w * rhs.w)
+    }
+
+    /// Returns a vector where every component is the dot product of `self` and `rhs`.
+    #[inline]
+    #[must_use]
+    pub fn dot_into_vec(self, rhs: Self) -> Self {
+        Self::splat(self.dot(rhs))
+    }
+
+    /// Returns a vector containing the minimum values for each element of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.min(rhs.x), self.y.min(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub fn min(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.min(rhs.x),
+            y: self.y.min(rhs.y),
+            z: self.z.min(rhs.z),
+            w: self.w.min(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the maximum values for each element of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.max(rhs.x), self.y.max(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub fn max(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.max(rhs.x),
+            y: self.y.max(rhs.y),
+            z: self.z.max(rhs.z),
+            w: self.w.max(rhs.w),
+        }
+    }
+
+    /// Component-wise clamping of values, similar to [`i16::clamp`].
+    ///
+    /// Each element in `min` must be less-or-equal to the corresponding element in `max`.
+    ///
+    /// # Panics
+    ///
+    /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
+    #[inline]
+    #[must_use]
+    pub fn clamp(self, min: Self, max: Self) -> Self {
+        glam_assert!(min.cmple(max).all(), "clamp: expected min <= max");
+        self.max(min).min(max)
+    }
+
+    /// Returns the horizontal minimum of `self`.
+    ///
+    /// In other words this computes `min(x, y, ..)`.
+    #[inline]
+    #[must_use]
+    pub fn min_element(self) -> i16 {
+        self.x.min(self.y.min(self.z.min(self.w)))
+    }
+
+    /// Returns the horizontal maximum of `self`.
+    ///
+    /// In other words this computes `max(x, y, ..)`.
+    #[inline]
+    #[must_use]
+    pub fn max_element(self) -> i16 {
+        self.x.max(self.y.max(self.z.max(self.w)))
+    }
+
+    /// Returns a vector mask containing the result of a `==` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words, this computes `[self.x == rhs.x, self.y == rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpeq(self, rhs: Self) -> BVec4 {
+        BVec4::new(
+            self.x.eq(&rhs.x),
+            self.y.eq(&rhs.y),
+            self.z.eq(&rhs.z),
+            self.w.eq(&rhs.w),
+        )
+    }
+
+    /// Returns a vector mask containing the result of a `!=` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x != rhs.x, self.y != rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpne(self, rhs: Self) -> BVec4 {
+        BVec4::new(
+            self.x.ne(&rhs.x),
+            self.y.ne(&rhs.y),
+            self.z.ne(&rhs.z),
+            self.w.ne(&rhs.w),
+        )
+    }
+
+    /// Returns a vector mask containing the result of a `>=` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x >= rhs.x, self.y >= rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpge(self, rhs: Self) -> BVec4 {
+        BVec4::new(
+            self.x.ge(&rhs.x),
+            self.y.ge(&rhs.y),
+            self.z.ge(&rhs.z),
+            self.w.ge(&rhs.w),
+        )
+    }
+
+    /// Returns a vector mask containing the result of a `>` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x > rhs.x, self.y > rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpgt(self, rhs: Self) -> BVec4 {
+        BVec4::new(
+            self.x.gt(&rhs.x),
+            self.y.gt(&rhs.y),
+            self.z.gt(&rhs.z),
+            self.w.gt(&rhs.w),
+        )
+    }
+
+    /// Returns a vector mask containing the result of a `<=` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x <= rhs.x, self.y <= rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmple(self, rhs: Self) -> BVec4 {
+        BVec4::new(
+            self.x.le(&rhs.x),
+            self.y.le(&rhs.y),
+            self.z.le(&rhs.z),
+            self.w.le(&rhs.w),
+        )
+    }
+
+    /// Returns a vector mask containing the result of a `<` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x < rhs.x, self.y < rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmplt(self, rhs: Self) -> BVec4 {
+        BVec4::new(
+            self.x.lt(&rhs.x),
+            self.y.lt(&rhs.y),
+            self.z.lt(&rhs.z),
+            self.w.lt(&rhs.w),
+        )
+    }
+
+    /// Returns a vector containing the absolute value of each element of `self`.
+    #[inline]
+    #[must_use]
+    pub fn abs(self) -> Self {
+        Self {
+            x: self.x.abs(),
+            y: self.y.abs(),
+            z: self.z.abs(),
+            w: self.w.abs(),
+        }
+    }
+
+    /// Returns a vector with elements representing the sign of `self`.
+    ///
+    ///  - `0` if the number is zero
+    ///  - `1` if the number is positive
+    ///  - `-1` if the number is negative
+    #[inline]
+    #[must_use]
+    pub fn signum(self) -> Self {
+        Self {
+            x: self.x.signum(),
+            y: self.y.signum(),
+            z: self.z.signum(),
+            w: self.w.signum(),
+        }
+    }
+
+    /// Returns a bitmask with the lowest 4 bits set to the sign bits from the elements of `self`.
+    ///
+    /// A negative element results in a `1` bit and a positive element in a `0` bit.  Element `x` goes
+    /// into the first lowest bit, element `y` into the second, etc.
+    #[inline]
+    #[must_use]
+    pub fn is_negative_bitmask(self) -> u32 {
+        (self.x.is_negative() as u32)
+            | (self.y.is_negative() as u32) << 1
+            | (self.z.is_negative() as u32) << 2
+            | (self.w.is_negative() as u32) << 3
+    }
+
+    /// Computes the squared length of `self`.
+    #[doc(alias = "magnitude2")]
+    #[inline]
+    #[must_use]
+    pub fn length_squared(self) -> i16 {
+        self.dot(self)
+    }
+
+    /// Compute the squared euclidean distance between two points in space.
+    #[inline]
+    #[must_use]
+    pub fn distance_squared(self, rhs: Self) -> i16 {
+        (self - rhs).length_squared()
+    }
+
+    /// Returns the element-wise quotient of [Euclidean division] of `self` by `rhs`.
+    ///
+    /// # Panics
+    /// This function will panic if any `rhs` element is 0 or the division results in overflow.
+    #[inline]
+    #[must_use]
+    pub fn div_euclid(self, rhs: Self) -> Self {
+        Self::new(
+            self.x.div_euclid(rhs.x),
+            self.y.div_euclid(rhs.y),
+            self.z.div_euclid(rhs.z),
+            self.w.div_euclid(rhs.w),
+        )
+    }
+
+    /// Returns the element-wise remainder of [Euclidean division] of `self` by `rhs`.
+    ///
+    /// # Panics
+    /// This function will panic if any `rhs` element is 0 or the division results in overflow.
+    ///
+    /// [Euclidean division]: i16::rem_euclid
+    #[inline]
+    #[must_use]
+    pub fn rem_euclid(self, rhs: Self) -> Self {
+        Self::new(
+            self.x.rem_euclid(rhs.x),
+            self.y.rem_euclid(rhs.y),
+            self.z.rem_euclid(rhs.z),
+            self.w.rem_euclid(rhs.w),
+        )
+    }
+
+    /// Casts all elements of `self` to `f32`.
+    #[inline]
+    #[must_use]
+    pub fn as_vec4(&self) -> crate::Vec4 {
+        crate::Vec4::new(self.x as f32, self.y as f32, self.z as f32, self.w as f32)
+    }
+
+    /// Casts all elements of `self` to `f64`.
+    #[inline]
+    #[must_use]
+    pub fn as_dvec4(&self) -> crate::DVec4 {
+        crate::DVec4::new(self.x as f64, self.y as f64, self.z as f64, self.w as f64)
+    }
+
+    /// Casts all elements of `self` to `u16`.
+    #[inline]
+    #[must_use]
+    pub fn as_u16vec4(&self) -> crate::U16Vec4 {
+        crate::U16Vec4::new(self.x as u16, self.y as u16, self.z as u16, self.w as u16)
+    }
+
+    /// Casts all elements of `self` to `i32`.
+    #[inline]
+    #[must_use]
+    pub fn as_ivec4(&self) -> crate::IVec4 {
+        crate::IVec4::new(self.x as i32, self.y as i32, self.z as i32, self.w as i32)
+    }
+
+    /// Casts all elements of `self` to `u32`.
+    #[inline]
+    #[must_use]
+    pub fn as_uvec4(&self) -> crate::UVec4 {
+        crate::UVec4::new(self.x as u32, self.y as u32, self.z as u32, self.w as u32)
+    }
+
+    /// Casts all elements of `self` to `i64`.
+    #[inline]
+    #[must_use]
+    pub fn as_i64vec4(&self) -> crate::I64Vec4 {
+        crate::I64Vec4::new(self.x as i64, self.y as i64, self.z as i64, self.w as i64)
+    }
+
+    /// Casts all elements of `self` to `u64`.
+    #[inline]
+    #[must_use]
+    pub fn as_u64vec4(&self) -> crate::U64Vec4 {
+        crate::U64Vec4::new(self.x as u64, self.y as u64, self.z as u64, self.w as u64)
+    }
+
+    /// Returns a vector containing the wrapping addition of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_add(rhs.x), self.y.wrapping_add(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_add(rhs.x),
+            y: self.y.wrapping_add(rhs.y),
+            z: self.z.wrapping_add(rhs.z),
+            w: self.w.wrapping_add(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the wrapping subtraction of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_sub(rhs.x), self.y.wrapping_sub(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_sub(rhs.x),
+            y: self.y.wrapping_sub(rhs.y),
+            z: self.z.wrapping_sub(rhs.z),
+            w: self.w.wrapping_sub(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the wrapping multiplication of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_mul(rhs.x), self.y.wrapping_mul(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_mul(rhs.x),
+            y: self.y.wrapping_mul(rhs.y),
+            z: self.z.wrapping_mul(rhs.z),
+            w: self.w.wrapping_mul(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the wrapping division of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_div(rhs.x), self.y.wrapping_div(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_div(rhs.x),
+            y: self.y.wrapping_div(rhs.y),
+            z: self.z.wrapping_div(rhs.z),
+            w: self.w.wrapping_div(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the saturating addition of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_add(rhs.x), self.y.saturating_add(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_add(rhs.x),
+            y: self.y.saturating_add(rhs.y),
+            z: self.z.saturating_add(rhs.z),
+            w: self.w.saturating_add(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the saturating subtraction of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_sub(rhs.x), self.y.saturating_sub(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_sub(rhs.x),
+            y: self.y.saturating_sub(rhs.y),
+            z: self.z.saturating_sub(rhs.z),
+            w: self.w.saturating_sub(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the saturating multiplication of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_mul(rhs.x), self.y.saturating_mul(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_mul(rhs.x),
+            y: self.y.saturating_mul(rhs.y),
+            z: self.z.saturating_mul(rhs.z),
+            w: self.w.saturating_mul(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the saturating division of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_div(rhs.x), self.y.saturating_div(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_div(rhs.x),
+            y: self.y.saturating_div(rhs.y),
+            z: self.z.saturating_div(rhs.z),
+            w: self.w.saturating_div(rhs.w),
+        }
+    }
+}
+
+impl Default for I16Vec4 {
+    #[inline(always)]
+    fn default() -> Self {
+        Self::ZERO
+    }
+}
+
+impl Div<I16Vec4> for I16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.div(rhs.x),
+            y: self.y.div(rhs.y),
+            z: self.z.div(rhs.z),
+            w: self.w.div(rhs.w),
+        }
+    }
+}
+
+impl DivAssign<I16Vec4> for I16Vec4 {
+    #[inline]
+    fn div_assign(&mut self, rhs: Self) {
+        self.x.div_assign(rhs.x);
+        self.y.div_assign(rhs.y);
+        self.z.div_assign(rhs.z);
+        self.w.div_assign(rhs.w);
+    }
+}
+
+impl Div<i16> for I16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn div(self, rhs: i16) -> Self {
+        Self {
+            x: self.x.div(rhs),
+            y: self.y.div(rhs),
+            z: self.z.div(rhs),
+            w: self.w.div(rhs),
+        }
+    }
+}
+
+impl DivAssign<i16> for I16Vec4 {
+    #[inline]
+    fn div_assign(&mut self, rhs: i16) {
+        self.x.div_assign(rhs);
+        self.y.div_assign(rhs);
+        self.z.div_assign(rhs);
+        self.w.div_assign(rhs);
+    }
+}
+
+impl Div<I16Vec4> for i16 {
+    type Output = I16Vec4;
+    #[inline]
+    fn div(self, rhs: I16Vec4) -> I16Vec4 {
+        I16Vec4 {
+            x: self.div(rhs.x),
+            y: self.div(rhs.y),
+            z: self.div(rhs.z),
+            w: self.div(rhs.w),
+        }
+    }
+}
+
+impl Mul<I16Vec4> for I16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.mul(rhs.x),
+            y: self.y.mul(rhs.y),
+            z: self.z.mul(rhs.z),
+            w: self.w.mul(rhs.w),
+        }
+    }
+}
+
+impl MulAssign<I16Vec4> for I16Vec4 {
+    #[inline]
+    fn mul_assign(&mut self, rhs: Self) {
+        self.x.mul_assign(rhs.x);
+        self.y.mul_assign(rhs.y);
+        self.z.mul_assign(rhs.z);
+        self.w.mul_assign(rhs.w);
+    }
+}
+
+impl Mul<i16> for I16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn mul(self, rhs: i16) -> Self {
+        Self {
+            x: self.x.mul(rhs),
+            y: self.y.mul(rhs),
+            z: self.z.mul(rhs),
+            w: self.w.mul(rhs),
+        }
+    }
+}
+
+impl MulAssign<i16> for I16Vec4 {
+    #[inline]
+    fn mul_assign(&mut self, rhs: i16) {
+        self.x.mul_assign(rhs);
+        self.y.mul_assign(rhs);
+        self.z.mul_assign(rhs);
+        self.w.mul_assign(rhs);
+    }
+}
+
+impl Mul<I16Vec4> for i16 {
+    type Output = I16Vec4;
+    #[inline]
+    fn mul(self, rhs: I16Vec4) -> I16Vec4 {
+        I16Vec4 {
+            x: self.mul(rhs.x),
+            y: self.mul(rhs.y),
+            z: self.mul(rhs.z),
+            w: self.mul(rhs.w),
+        }
+    }
+}
+
+impl Add<I16Vec4> for I16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.add(rhs.x),
+            y: self.y.add(rhs.y),
+            z: self.z.add(rhs.z),
+            w: self.w.add(rhs.w),
+        }
+    }
+}
+
+impl AddAssign<I16Vec4> for I16Vec4 {
+    #[inline]
+    fn add_assign(&mut self, rhs: Self) {
+        self.x.add_assign(rhs.x);
+        self.y.add_assign(rhs.y);
+        self.z.add_assign(rhs.z);
+        self.w.add_assign(rhs.w);
+    }
+}
+
+impl Add<i16> for I16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn add(self, rhs: i16) -> Self {
+        Self {
+            x: self.x.add(rhs),
+            y: self.y.add(rhs),
+            z: self.z.add(rhs),
+            w: self.w.add(rhs),
+        }
+    }
+}
+
+impl AddAssign<i16> for I16Vec4 {
+    #[inline]
+    fn add_assign(&mut self, rhs: i16) {
+        self.x.add_assign(rhs);
+        self.y.add_assign(rhs);
+        self.z.add_assign(rhs);
+        self.w.add_assign(rhs);
+    }
+}
+
+impl Add<I16Vec4> for i16 {
+    type Output = I16Vec4;
+    #[inline]
+    fn add(self, rhs: I16Vec4) -> I16Vec4 {
+        I16Vec4 {
+            x: self.add(rhs.x),
+            y: self.add(rhs.y),
+            z: self.add(rhs.z),
+            w: self.add(rhs.w),
+        }
+    }
+}
+
+impl Sub<I16Vec4> for I16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.sub(rhs.x),
+            y: self.y.sub(rhs.y),
+            z: self.z.sub(rhs.z),
+            w: self.w.sub(rhs.w),
+        }
+    }
+}
+
+impl SubAssign<I16Vec4> for I16Vec4 {
+    #[inline]
+    fn sub_assign(&mut self, rhs: I16Vec4) {
+        self.x.sub_assign(rhs.x);
+        self.y.sub_assign(rhs.y);
+        self.z.sub_assign(rhs.z);
+        self.w.sub_assign(rhs.w);
+    }
+}
+
+impl Sub<i16> for I16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn sub(self, rhs: i16) -> Self {
+        Self {
+            x: self.x.sub(rhs),
+            y: self.y.sub(rhs),
+            z: self.z.sub(rhs),
+            w: self.w.sub(rhs),
+        }
+    }
+}
+
+impl SubAssign<i16> for I16Vec4 {
+    #[inline]
+    fn sub_assign(&mut self, rhs: i16) {
+        self.x.sub_assign(rhs);
+        self.y.sub_assign(rhs);
+        self.z.sub_assign(rhs);
+        self.w.sub_assign(rhs);
+    }
+}
+
+impl Sub<I16Vec4> for i16 {
+    type Output = I16Vec4;
+    #[inline]
+    fn sub(self, rhs: I16Vec4) -> I16Vec4 {
+        I16Vec4 {
+            x: self.sub(rhs.x),
+            y: self.sub(rhs.y),
+            z: self.sub(rhs.z),
+            w: self.sub(rhs.w),
+        }
+    }
+}
+
+impl Rem<I16Vec4> for I16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn rem(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.rem(rhs.x),
+            y: self.y.rem(rhs.y),
+            z: self.z.rem(rhs.z),
+            w: self.w.rem(rhs.w),
+        }
+    }
+}
+
+impl RemAssign<I16Vec4> for I16Vec4 {
+    #[inline]
+    fn rem_assign(&mut self, rhs: Self) {
+        self.x.rem_assign(rhs.x);
+        self.y.rem_assign(rhs.y);
+        self.z.rem_assign(rhs.z);
+        self.w.rem_assign(rhs.w);
+    }
+}
+
+impl Rem<i16> for I16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn rem(self, rhs: i16) -> Self {
+        Self {
+            x: self.x.rem(rhs),
+            y: self.y.rem(rhs),
+            z: self.z.rem(rhs),
+            w: self.w.rem(rhs),
+        }
+    }
+}
+
+impl RemAssign<i16> for I16Vec4 {
+    #[inline]
+    fn rem_assign(&mut self, rhs: i16) {
+        self.x.rem_assign(rhs);
+        self.y.rem_assign(rhs);
+        self.z.rem_assign(rhs);
+        self.w.rem_assign(rhs);
+    }
+}
+
+impl Rem<I16Vec4> for i16 {
+    type Output = I16Vec4;
+    #[inline]
+    fn rem(self, rhs: I16Vec4) -> I16Vec4 {
+        I16Vec4 {
+            x: self.rem(rhs.x),
+            y: self.rem(rhs.y),
+            z: self.rem(rhs.z),
+            w: self.rem(rhs.w),
+        }
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl AsRef<[i16; 4]> for I16Vec4 {
+    #[inline]
+    fn as_ref(&self) -> &[i16; 4] {
+        unsafe { &*(self as *const I16Vec4 as *const [i16; 4]) }
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl AsMut<[i16; 4]> for I16Vec4 {
+    #[inline]
+    fn as_mut(&mut self) -> &mut [i16; 4] {
+        unsafe { &mut *(self as *mut I16Vec4 as *mut [i16; 4]) }
+    }
+}
+
+impl Sum for I16Vec4 {
+    #[inline]
+    fn sum<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = Self>,
+    {
+        iter.fold(Self::ZERO, Self::add)
+    }
+}
+
+impl<'a> Sum<&'a Self> for I16Vec4 {
+    #[inline]
+    fn sum<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = &'a Self>,
+    {
+        iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
+    }
+}
+
+impl Product for I16Vec4 {
+    #[inline]
+    fn product<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = Self>,
+    {
+        iter.fold(Self::ONE, Self::mul)
+    }
+}
+
+impl<'a> Product<&'a Self> for I16Vec4 {
+    #[inline]
+    fn product<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = &'a Self>,
+    {
+        iter.fold(Self::ONE, |a, &b| Self::mul(a, b))
+    }
+}
+
+impl Neg for I16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn neg(self) -> Self {
+        Self {
+            x: self.x.neg(),
+            y: self.y.neg(),
+            z: self.z.neg(),
+            w: self.w.neg(),
+        }
+    }
+}
+
+impl Not for I16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn not(self) -> Self::Output {
+        Self {
+            x: self.x.not(),
+            y: self.y.not(),
+            z: self.z.not(),
+            w: self.w.not(),
+        }
+    }
+}
+
+impl BitAnd for I16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn bitand(self, rhs: Self) -> Self::Output {
+        Self {
+            x: self.x.bitand(rhs.x),
+            y: self.y.bitand(rhs.y),
+            z: self.z.bitand(rhs.z),
+            w: self.w.bitand(rhs.w),
+        }
+    }
+}
+
+impl BitOr for I16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn bitor(self, rhs: Self) -> Self::Output {
+        Self {
+            x: self.x.bitor(rhs.x),
+            y: self.y.bitor(rhs.y),
+            z: self.z.bitor(rhs.z),
+            w: self.w.bitor(rhs.w),
+        }
+    }
+}
+
+impl BitXor for I16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn bitxor(self, rhs: Self) -> Self::Output {
+        Self {
+            x: self.x.bitxor(rhs.x),
+            y: self.y.bitxor(rhs.y),
+            z: self.z.bitxor(rhs.z),
+            w: self.w.bitxor(rhs.w),
+        }
+    }
+}
+
+impl BitAnd<i16> for I16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn bitand(self, rhs: i16) -> Self::Output {
+        Self {
+            x: self.x.bitand(rhs),
+            y: self.y.bitand(rhs),
+            z: self.z.bitand(rhs),
+            w: self.w.bitand(rhs),
+        }
+    }
+}
+
+impl BitOr<i16> for I16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn bitor(self, rhs: i16) -> Self::Output {
+        Self {
+            x: self.x.bitor(rhs),
+            y: self.y.bitor(rhs),
+            z: self.z.bitor(rhs),
+            w: self.w.bitor(rhs),
+        }
+    }
+}
+
+impl BitXor<i16> for I16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn bitxor(self, rhs: i16) -> Self::Output {
+        Self {
+            x: self.x.bitxor(rhs),
+            y: self.y.bitxor(rhs),
+            z: self.z.bitxor(rhs),
+            w: self.w.bitxor(rhs),
+        }
+    }
+}
+
+impl Shl<i8> for I16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i8) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+            w: self.w.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i8> for I16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i8) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+            w: self.w.shr(rhs),
+        }
+    }
+}
+
+impl Shl<i16> for I16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i16) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+            w: self.w.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i16> for I16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i16) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+            w: self.w.shr(rhs),
+        }
+    }
+}
+
+impl Shl<i32> for I16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i32) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+            w: self.w.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i32> for I16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i32) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+            w: self.w.shr(rhs),
+        }
+    }
+}
+
+impl Shl<i64> for I16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+            w: self.w.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i64> for I16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+            w: self.w.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u8> for I16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u8) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+            w: self.w.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u8> for I16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u8) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+            w: self.w.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u16> for I16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u16) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+            w: self.w.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u16> for I16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u16) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+            w: self.w.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u32> for I16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u32) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+            w: self.w.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u32> for I16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u32) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+            w: self.w.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u64> for I16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+            w: self.w.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u64> for I16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+            w: self.w.shr(rhs),
+        }
+    }
+}
+
+impl Shl<crate::IVec4> for I16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: crate::IVec4) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs.x),
+            y: self.y.shl(rhs.y),
+            z: self.z.shl(rhs.z),
+            w: self.w.shl(rhs.w),
+        }
+    }
+}
+
+impl Shr<crate::IVec4> for I16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: crate::IVec4) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs.x),
+            y: self.y.shr(rhs.y),
+            z: self.z.shr(rhs.z),
+            w: self.w.shr(rhs.w),
+        }
+    }
+}
+
+impl Shl<crate::UVec4> for I16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: crate::UVec4) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs.x),
+            y: self.y.shl(rhs.y),
+            z: self.z.shl(rhs.z),
+            w: self.w.shl(rhs.w),
+        }
+    }
+}
+
+impl Shr<crate::UVec4> for I16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: crate::UVec4) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs.x),
+            y: self.y.shr(rhs.y),
+            z: self.z.shr(rhs.z),
+            w: self.w.shr(rhs.w),
+        }
+    }
+}
+
+impl Index<usize> for I16Vec4 {
+    type Output = i16;
+    #[inline]
+    fn index(&self, index: usize) -> &Self::Output {
+        match index {
+            0 => &self.x,
+            1 => &self.y,
+            2 => &self.z,
+            3 => &self.w,
+            _ => panic!("index out of bounds"),
+        }
+    }
+}
+
+impl IndexMut<usize> for I16Vec4 {
+    #[inline]
+    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
+        match index {
+            0 => &mut self.x,
+            1 => &mut self.y,
+            2 => &mut self.z,
+            3 => &mut self.w,
+            _ => panic!("index out of bounds"),
+        }
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl fmt::Display for I16Vec4 {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w)
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl fmt::Debug for I16Vec4 {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt.debug_tuple(stringify!(I16Vec4))
+            .field(&self.x)
+            .field(&self.y)
+            .field(&self.z)
+            .field(&self.w)
+            .finish()
+    }
+}
+
+impl From<[i16; 4]> for I16Vec4 {
+    #[inline]
+    fn from(a: [i16; 4]) -> Self {
+        Self::new(a[0], a[1], a[2], a[3])
+    }
+}
+
+impl From<I16Vec4> for [i16; 4] {
+    #[inline]
+    fn from(v: I16Vec4) -> Self {
+        [v.x, v.y, v.z, v.w]
+    }
+}
+
+impl From<(i16, i16, i16, i16)> for I16Vec4 {
+    #[inline]
+    fn from(t: (i16, i16, i16, i16)) -> Self {
+        Self::new(t.0, t.1, t.2, t.3)
+    }
+}
+
+impl From<I16Vec4> for (i16, i16, i16, i16) {
+    #[inline]
+    fn from(v: I16Vec4) -> Self {
+        (v.x, v.y, v.z, v.w)
+    }
+}
+
+impl From<(I16Vec3, i16)> for I16Vec4 {
+    #[inline]
+    fn from((v, w): (I16Vec3, i16)) -> Self {
+        Self::new(v.x, v.y, v.z, w)
+    }
+}
+
+impl From<(i16, I16Vec3)> for I16Vec4 {
+    #[inline]
+    fn from((x, v): (i16, I16Vec3)) -> Self {
+        Self::new(x, v.x, v.y, v.z)
+    }
+}
+
+impl From<(I16Vec2, i16, i16)> for I16Vec4 {
+    #[inline]
+    fn from((v, z, w): (I16Vec2, i16, i16)) -> Self {
+        Self::new(v.x, v.y, z, w)
+    }
+}
+
+impl From<(I16Vec2, I16Vec2)> for I16Vec4 {
+    #[inline]
+    fn from((v, u): (I16Vec2, I16Vec2)) -> Self {
+        Self::new(v.x, v.y, u.x, u.y)
+    }
+}
+
+impl TryFrom<U16Vec4> for I16Vec4 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: U16Vec4) -> Result<Self, Self::Error> {
+        Ok(Self::new(
+            i16::try_from(v.x)?,
+            i16::try_from(v.y)?,
+            i16::try_from(v.z)?,
+            i16::try_from(v.w)?,
+        ))
+    }
+}
+
+impl TryFrom<IVec4> for I16Vec4 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: IVec4) -> Result<Self, Self::Error> {
+        Ok(Self::new(
+            i16::try_from(v.x)?,
+            i16::try_from(v.y)?,
+            i16::try_from(v.z)?,
+            i16::try_from(v.w)?,
+        ))
+    }
+}
+
+impl TryFrom<UVec4> for I16Vec4 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: UVec4) -> Result<Self, Self::Error> {
+        Ok(Self::new(
+            i16::try_from(v.x)?,
+            i16::try_from(v.y)?,
+            i16::try_from(v.z)?,
+            i16::try_from(v.w)?,
+        ))
+    }
+}
+
+impl TryFrom<I64Vec4> for I16Vec4 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: I64Vec4) -> Result<Self, Self::Error> {
+        Ok(Self::new(
+            i16::try_from(v.x)?,
+            i16::try_from(v.y)?,
+            i16::try_from(v.z)?,
+            i16::try_from(v.w)?,
+        ))
+    }
+}
+
+impl TryFrom<U64Vec4> for I16Vec4 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: U64Vec4) -> Result<Self, Self::Error> {
+        Ok(Self::new(
+            i16::try_from(v.x)?,
+            i16::try_from(v.y)?,
+            i16::try_from(v.z)?,
+            i16::try_from(v.w)?,
+        ))
+    }
+}
diff --git a/src/i32.rs b/src/i32.rs
index 313f56c..663607b 100644
--- a/src/i32.rs
+++ b/src/i32.rs
@@ -11,6 +11,8 @@
     use super::*;
 
     mod const_test_ivec2 {
+        const_assert_eq!(8, core::mem::size_of::<super::IVec2>());
+
         #[cfg(not(feature = "cuda"))]
         const_assert_eq!(
             core::mem::align_of::<i32>(),
@@ -18,7 +20,6 @@
         );
         #[cfg(feature = "cuda")]
         const_assert_eq!(8, core::mem::align_of::<super::IVec2>());
-        const_assert_eq!(8, core::mem::size_of::<super::IVec2>());
     }
 
     mod const_test_ivec3 {
@@ -30,6 +31,8 @@
     }
 
     mod const_test_ivec4 {
+        const_assert_eq!(16, core::mem::size_of::<super::IVec4>());
+
         #[cfg(not(feature = "cuda"))]
         const_assert_eq!(
             core::mem::align_of::<i32>(),
@@ -37,6 +40,5 @@
         );
         #[cfg(feature = "cuda")]
         const_assert_eq!(16, core::mem::align_of::<super::IVec4>());
-        const_assert_eq!(16, core::mem::size_of::<super::IVec4>());
     }
 }
diff --git a/src/i32/ivec2.rs b/src/i32/ivec2.rs
index 0a78305..fdc4c81 100644
--- a/src/i32/ivec2.rs
+++ b/src/i32/ivec2.rs
@@ -1,6 +1,6 @@
 // Generated from vec.rs.tera template. Edit the template, not the generated file.
 
-use crate::{BVec2, IVec3};
+use crate::{BVec2, I16Vec2, I64Vec2, IVec3, U16Vec2, U64Vec2, UVec2};
 
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
@@ -9,6 +9,7 @@
 
 /// Creates a 2-dimensional vector.
 #[inline(always)]
+#[must_use]
 pub const fn ivec2(x: i32, y: i32) -> IVec2 {
     IVec2::new(x, y)
 }
@@ -34,16 +35,22 @@
     /// All negative ones.
     pub const NEG_ONE: Self = Self::splat(-1);
 
-    /// A unit-length vector pointing along the positive X axis.
+    /// All `i32::MIN`.
+    pub const MIN: Self = Self::splat(i32::MIN);
+
+    /// All `i32::MAX`.
+    pub const MAX: Self = Self::splat(i32::MAX);
+
+    /// A unit vector pointing along the positive X axis.
     pub const X: Self = Self::new(1, 0);
 
-    /// A unit-length vector pointing along the positive Y axis.
+    /// A unit vector pointing along the positive Y axis.
     pub const Y: Self = Self::new(0, 1);
 
-    /// A unit-length vector pointing along the negative X axis.
+    /// A unit vector pointing along the negative X axis.
     pub const NEG_X: Self = Self::new(-1, 0);
 
-    /// A unit-length vector pointing along the negative Y axis.
+    /// A unit vector pointing along the negative Y axis.
     pub const NEG_Y: Self = Self::new(0, -1);
 
     /// The unit axes.
@@ -51,12 +58,14 @@
 
     /// Creates a new vector.
     #[inline(always)]
+    #[must_use]
     pub const fn new(x: i32, y: i32) -> Self {
         Self { x, y }
     }
 
     /// Creates a vector with all elements set to `v`.
     #[inline]
+    #[must_use]
     pub const fn splat(v: i32) -> Self {
         Self { x: v, y: v }
     }
@@ -67,21 +76,24 @@
     /// A true element in the mask uses the corresponding element from `if_true`, and false
     /// uses the element from `if_false`.
     #[inline]
+    #[must_use]
     pub fn select(mask: BVec2, if_true: Self, if_false: Self) -> Self {
         Self {
-            x: if mask.x { if_true.x } else { if_false.x },
-            y: if mask.y { if_true.y } else { if_false.y },
+            x: if mask.test(0) { if_true.x } else { if_false.x },
+            y: if mask.test(1) { if_true.y } else { if_false.y },
         }
     }
 
     /// Creates a new vector from an array.
     #[inline]
+    #[must_use]
     pub const fn from_array(a: [i32; 2]) -> Self {
         Self::new(a[0], a[1])
     }
 
     /// `[x, y]`
     #[inline]
+    #[must_use]
     pub const fn to_array(&self) -> [i32; 2] {
         [self.x, self.y]
     }
@@ -92,6 +104,7 @@
     ///
     /// Panics if `slice` is less than 2 elements long.
     #[inline]
+    #[must_use]
     pub const fn from_slice(slice: &[i32]) -> Self {
         Self::new(slice[0], slice[1])
     }
@@ -109,18 +122,21 @@
 
     /// Creates a 3D vector from `self` and the given `z` value.
     #[inline]
+    #[must_use]
     pub const fn extend(self, z: i32) -> IVec3 {
         IVec3::new(self.x, self.y, z)
     }
 
     /// Computes the dot product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn dot(self, rhs: Self) -> i32 {
         (self.x * rhs.x) + (self.y * rhs.y)
     }
 
     /// Returns a vector where every component is the dot product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn dot_into_vec(self, rhs: Self) -> Self {
         Self::splat(self.dot(rhs))
     }
@@ -129,6 +145,7 @@
     ///
     /// In other words this computes `[self.x.min(rhs.x), self.y.min(rhs.y), ..]`.
     #[inline]
+    #[must_use]
     pub fn min(self, rhs: Self) -> Self {
         Self {
             x: self.x.min(rhs.x),
@@ -140,6 +157,7 @@
     ///
     /// In other words this computes `[self.x.max(rhs.x), self.y.max(rhs.y), ..]`.
     #[inline]
+    #[must_use]
     pub fn max(self, rhs: Self) -> Self {
         Self {
             x: self.x.max(rhs.x),
@@ -155,6 +173,7 @@
     ///
     /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn clamp(self, min: Self, max: Self) -> Self {
         glam_assert!(min.cmple(max).all(), "clamp: expected min <= max");
         self.max(min).min(max)
@@ -164,6 +183,7 @@
     ///
     /// In other words this computes `min(x, y, ..)`.
     #[inline]
+    #[must_use]
     pub fn min_element(self) -> i32 {
         self.x.min(self.y)
     }
@@ -172,6 +192,7 @@
     ///
     /// In other words this computes `max(x, y, ..)`.
     #[inline]
+    #[must_use]
     pub fn max_element(self) -> i32 {
         self.x.max(self.y)
     }
@@ -182,6 +203,7 @@
     /// In other words, this computes `[self.x == rhs.x, self.y == rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpeq(self, rhs: Self) -> BVec2 {
         BVec2::new(self.x.eq(&rhs.x), self.y.eq(&rhs.y))
     }
@@ -192,6 +214,7 @@
     /// In other words this computes `[self.x != rhs.x, self.y != rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpne(self, rhs: Self) -> BVec2 {
         BVec2::new(self.x.ne(&rhs.x), self.y.ne(&rhs.y))
     }
@@ -202,6 +225,7 @@
     /// In other words this computes `[self.x >= rhs.x, self.y >= rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpge(self, rhs: Self) -> BVec2 {
         BVec2::new(self.x.ge(&rhs.x), self.y.ge(&rhs.y))
     }
@@ -212,6 +236,7 @@
     /// In other words this computes `[self.x > rhs.x, self.y > rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpgt(self, rhs: Self) -> BVec2 {
         BVec2::new(self.x.gt(&rhs.x), self.y.gt(&rhs.y))
     }
@@ -222,6 +247,7 @@
     /// In other words this computes `[self.x <= rhs.x, self.y <= rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmple(self, rhs: Self) -> BVec2 {
         BVec2::new(self.x.le(&rhs.x), self.y.le(&rhs.y))
     }
@@ -232,12 +258,14 @@
     /// In other words this computes `[self.x < rhs.x, self.y < rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmplt(self, rhs: Self) -> BVec2 {
         BVec2::new(self.x.lt(&rhs.x), self.y.lt(&rhs.y))
     }
 
     /// Returns a vector containing the absolute value of each element of `self`.
     #[inline]
+    #[must_use]
     pub fn abs(self) -> Self {
         Self {
             x: self.x.abs(),
@@ -251,6 +279,7 @@
     ///  - `1` if the number is positive
     ///  - `-1` if the number is negative
     #[inline]
+    #[must_use]
     pub fn signum(self) -> Self {
         Self {
             x: self.x.signum(),
@@ -258,23 +287,56 @@
         }
     }
 
-    /// Returns a vector with signs of `rhs` and the magnitudes of `self`.
-    #[inline]
-    pub fn copysign(self, rhs: Self) -> Self {
-        Self::select(rhs.cmpge(Self::ZERO), self, -self)
-    }
-
     /// Returns a bitmask with the lowest 2 bits set to the sign bits from the elements of `self`.
     ///
     /// A negative element results in a `1` bit and a positive element in a `0` bit.  Element `x` goes
     /// into the first lowest bit, element `y` into the second, etc.
     #[inline]
+    #[must_use]
     pub fn is_negative_bitmask(self) -> u32 {
         (self.x.is_negative() as u32) | (self.y.is_negative() as u32) << 1
     }
 
+    /// Computes the squared length of `self`.
+    #[doc(alias = "magnitude2")]
+    #[inline]
+    #[must_use]
+    pub fn length_squared(self) -> i32 {
+        self.dot(self)
+    }
+
+    /// Compute the squared euclidean distance between two points in space.
+    #[inline]
+    #[must_use]
+    pub fn distance_squared(self, rhs: Self) -> i32 {
+        (self - rhs).length_squared()
+    }
+
+    /// Returns the element-wise quotient of [Euclidean division] of `self` by `rhs`.
+    ///
+    /// # Panics
+    /// This function will panic if any `rhs` element is 0 or the division results in overflow.
+    #[inline]
+    #[must_use]
+    pub fn div_euclid(self, rhs: Self) -> Self {
+        Self::new(self.x.div_euclid(rhs.x), self.y.div_euclid(rhs.y))
+    }
+
+    /// Returns the element-wise remainder of [Euclidean division] of `self` by `rhs`.
+    ///
+    /// # Panics
+    /// This function will panic if any `rhs` element is 0 or the division results in overflow.
+    ///
+    /// [Euclidean division]: i32::rem_euclid
+    #[inline]
+    #[must_use]
+    pub fn rem_euclid(self, rhs: Self) -> Self {
+        Self::new(self.x.rem_euclid(rhs.x), self.y.rem_euclid(rhs.y))
+    }
+
     /// Returns a vector that is equal to `self` rotated by 90 degrees.
     #[inline]
+    #[must_use]
     pub fn perp(self) -> Self {
         Self {
             x: -self.y,
@@ -288,6 +350,7 @@
     #[doc(alias = "cross")]
     #[doc(alias = "determinant")]
     #[inline]
+    #[must_use]
     pub fn perp_dot(self, rhs: Self) -> i32 {
         (self.x * rhs.y) - (self.y * rhs.x)
     }
@@ -295,8 +358,8 @@
     /// Returns `rhs` rotated by the angle of `self`. If `self` is normalized,
     /// then this just rotation. This is what you usually want. Otherwise,
     /// it will be like a rotation with a multiplication by `self`'s length.
-    #[must_use]
     #[inline]
+    #[must_use]
     pub fn rotate(self, rhs: Self) -> Self {
         Self {
             x: self.x * rhs.x - self.y * rhs.y,
@@ -306,21 +369,148 @@
 
     /// Casts all elements of `self` to `f32`.
     #[inline]
+    #[must_use]
     pub fn as_vec2(&self) -> crate::Vec2 {
         crate::Vec2::new(self.x as f32, self.y as f32)
     }
 
     /// Casts all elements of `self` to `f64`.
     #[inline]
+    #[must_use]
     pub fn as_dvec2(&self) -> crate::DVec2 {
         crate::DVec2::new(self.x as f64, self.y as f64)
     }
 
+    /// Casts all elements of `self` to `i16`.
+    #[inline]
+    #[must_use]
+    pub fn as_i16vec2(&self) -> crate::I16Vec2 {
+        crate::I16Vec2::new(self.x as i16, self.y as i16)
+    }
+
+    /// Casts all elements of `self` to `u16`.
+    #[inline]
+    #[must_use]
+    pub fn as_u16vec2(&self) -> crate::U16Vec2 {
+        crate::U16Vec2::new(self.x as u16, self.y as u16)
+    }
+
     /// Casts all elements of `self` to `u32`.
     #[inline]
+    #[must_use]
     pub fn as_uvec2(&self) -> crate::UVec2 {
         crate::UVec2::new(self.x as u32, self.y as u32)
     }
+
+    /// Casts all elements of `self` to `i64`.
+    #[inline]
+    #[must_use]
+    pub fn as_i64vec2(&self) -> crate::I64Vec2 {
+        crate::I64Vec2::new(self.x as i64, self.y as i64)
+    }
+
+    /// Casts all elements of `self` to `u64`.
+    #[inline]
+    #[must_use]
+    pub fn as_u64vec2(&self) -> crate::U64Vec2 {
+        crate::U64Vec2::new(self.x as u64, self.y as u64)
+    }
+
+    /// Returns a vector containing the wrapping addition of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_add(rhs.x), self.y.wrapping_add(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_add(rhs.x),
+            y: self.y.wrapping_add(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the wrapping subtraction of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_sub(rhs.x), self.y.wrapping_sub(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_sub(rhs.x),
+            y: self.y.wrapping_sub(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the wrapping multiplication of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_mul(rhs.x), self.y.wrapping_mul(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_mul(rhs.x),
+            y: self.y.wrapping_mul(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the wrapping division of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_div(rhs.x), self.y.wrapping_div(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_div(rhs.x),
+            y: self.y.wrapping_div(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the saturating addition of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_add(rhs.x), self.y.saturating_add(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_add(rhs.x),
+            y: self.y.saturating_add(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the saturating subtraction of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_sub(rhs.x), self.y.saturating_sub(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_sub(rhs.x),
+            y: self.y.saturating_sub(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the saturating multiplication of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_mul(rhs.x), self.y.saturating_mul(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_mul(rhs.x),
+            y: self.y.saturating_mul(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the saturating division of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_div(rhs.x), self.y.saturating_div(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_div(rhs.x),
+            y: self.y.saturating_div(rhs.y),
+        }
+    }
 }
 
 impl Default for IVec2 {
@@ -785,6 +975,28 @@
     }
 }
 
+impl Shl<i64> for IVec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i64> for IVec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+        }
+    }
+}
+
 impl Shl<u8> for IVec2 {
     type Output = Self;
     #[inline]
@@ -851,6 +1063,28 @@
     }
 }
 
+impl Shl<u64> for IVec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u64> for IVec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+        }
+    }
+}
+
 impl Shl<crate::IVec2> for IVec2 {
     type Output = Self;
     #[inline]
@@ -962,3 +1196,44 @@
         (v.x, v.y)
     }
 }
+
+impl From<I16Vec2> for IVec2 {
+    #[inline]
+    fn from(v: I16Vec2) -> Self {
+        Self::new(i32::from(v.x), i32::from(v.y))
+    }
+}
+
+impl From<U16Vec2> for IVec2 {
+    #[inline]
+    fn from(v: U16Vec2) -> Self {
+        Self::new(i32::from(v.x), i32::from(v.y))
+    }
+}
+
+impl TryFrom<UVec2> for IVec2 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: UVec2) -> Result<Self, Self::Error> {
+        Ok(Self::new(i32::try_from(v.x)?, i32::try_from(v.y)?))
+    }
+}
+
+impl TryFrom<I64Vec2> for IVec2 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: I64Vec2) -> Result<Self, Self::Error> {
+        Ok(Self::new(i32::try_from(v.x)?, i32::try_from(v.y)?))
+    }
+}
+
+impl TryFrom<U64Vec2> for IVec2 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: U64Vec2) -> Result<Self, Self::Error> {
+        Ok(Self::new(i32::try_from(v.x)?, i32::try_from(v.y)?))
+    }
+}
diff --git a/src/i32/ivec3.rs b/src/i32/ivec3.rs
index 2f71ac0..1a8425b 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, IVec2, IVec4};
+use crate::{BVec3, I16Vec3, I64Vec3, IVec2, IVec4, U16Vec3, U64Vec3, UVec3};
 
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
@@ -9,6 +9,7 @@
 
 /// Creates a 3-dimensional vector.
 #[inline(always)]
+#[must_use]
 pub const fn ivec3(x: i32, y: i32, z: i32) -> IVec3 {
     IVec3::new(x, y, z)
 }
@@ -34,22 +35,28 @@
     /// All negative ones.
     pub const NEG_ONE: Self = Self::splat(-1);
 
-    /// A unit-length vector pointing along the positive X axis.
+    /// All `i32::MIN`.
+    pub const MIN: Self = Self::splat(i32::MIN);
+
+    /// All `i32::MAX`.
+    pub const MAX: Self = Self::splat(i32::MAX);
+
+    /// A unit vector pointing along the positive X axis.
     pub const X: Self = Self::new(1, 0, 0);
 
-    /// A unit-length vector pointing along the positive Y axis.
+    /// A unit vector pointing along the positive Y axis.
     pub const Y: Self = Self::new(0, 1, 0);
 
-    /// A unit-length vector pointing along the positive Z axis.
+    /// A unit vector pointing along the positive Z axis.
     pub const Z: Self = Self::new(0, 0, 1);
 
-    /// A unit-length vector pointing along the negative X axis.
+    /// A unit vector pointing along the negative X axis.
     pub const NEG_X: Self = Self::new(-1, 0, 0);
 
-    /// A unit-length vector pointing along the negative Y axis.
+    /// A unit vector pointing along the negative Y axis.
     pub const NEG_Y: Self = Self::new(0, -1, 0);
 
-    /// A unit-length vector pointing along the negative Z axis.
+    /// A unit vector pointing along the negative Z axis.
     pub const NEG_Z: Self = Self::new(0, 0, -1);
 
     /// The unit axes.
@@ -57,12 +64,14 @@
 
     /// Creates a new vector.
     #[inline(always)]
+    #[must_use]
     pub const fn new(x: i32, y: i32, z: i32) -> Self {
         Self { x, y, z }
     }
 
     /// Creates a vector with all elements set to `v`.
     #[inline]
+    #[must_use]
     pub const fn splat(v: i32) -> Self {
         Self { x: v, y: v, z: v }
     }
@@ -73,22 +82,25 @@
     /// A true element in the mask uses the corresponding element from `if_true`, and false
     /// uses the element from `if_false`.
     #[inline]
+    #[must_use]
     pub fn select(mask: BVec3, if_true: Self, if_false: Self) -> Self {
         Self {
-            x: if mask.x { if_true.x } else { if_false.x },
-            y: if mask.y { if_true.y } else { if_false.y },
-            z: if mask.z { if_true.z } else { if_false.z },
+            x: if mask.test(0) { if_true.x } else { if_false.x },
+            y: if mask.test(1) { if_true.y } else { if_false.y },
+            z: if mask.test(2) { if_true.z } else { if_false.z },
         }
     }
 
     /// Creates a new vector from an array.
     #[inline]
+    #[must_use]
     pub const fn from_array(a: [i32; 3]) -> Self {
         Self::new(a[0], a[1], a[2])
     }
 
     /// `[x, y, z]`
     #[inline]
+    #[must_use]
     pub const fn to_array(&self) -> [i32; 3] {
         [self.x, self.y, self.z]
     }
@@ -99,6 +111,7 @@
     ///
     /// Panics if `slice` is less than 3 elements long.
     #[inline]
+    #[must_use]
     pub const fn from_slice(slice: &[i32]) -> Self {
         Self::new(slice[0], slice[1], slice[2])
     }
@@ -118,6 +131,7 @@
     /// Internal method for creating a 3D vector from a 4D vector, discarding `w`.
     #[allow(dead_code)]
     #[inline]
+    #[must_use]
     pub(crate) fn from_vec4(v: IVec4) -> Self {
         Self {
             x: v.x,
@@ -128,14 +142,16 @@
 
     /// Creates a 4D vector from `self` and the given `w` value.
     #[inline]
+    #[must_use]
     pub fn extend(self, w: i32) -> IVec4 {
         IVec4::new(self.x, self.y, self.z, w)
     }
 
     /// Creates a 2D vector from the `x` and `y` elements of `self`, discarding `z`.
     ///
-    /// Truncation may also be performed by using `self.xy()` or `IVec2::from()`.
+    /// Truncation may also be performed by using [`self.xy()`][crate::swizzles::Vec3Swizzles::xy()].
     #[inline]
+    #[must_use]
     pub fn truncate(self) -> IVec2 {
         use crate::swizzles::Vec3Swizzles;
         self.xy()
@@ -143,18 +159,21 @@
 
     /// Computes the dot product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn dot(self, rhs: Self) -> i32 {
         (self.x * rhs.x) + (self.y * rhs.y) + (self.z * rhs.z)
     }
 
     /// Returns a vector where every component is the dot product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn dot_into_vec(self, rhs: Self) -> Self {
         Self::splat(self.dot(rhs))
     }
 
     /// Computes the cross product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn cross(self, rhs: Self) -> Self {
         Self {
             x: self.y * rhs.z - rhs.y * self.z,
@@ -167,6 +186,7 @@
     ///
     /// In other words this computes `[self.x.min(rhs.x), self.y.min(rhs.y), ..]`.
     #[inline]
+    #[must_use]
     pub fn min(self, rhs: Self) -> Self {
         Self {
             x: self.x.min(rhs.x),
@@ -179,6 +199,7 @@
     ///
     /// In other words this computes `[self.x.max(rhs.x), self.y.max(rhs.y), ..]`.
     #[inline]
+    #[must_use]
     pub fn max(self, rhs: Self) -> Self {
         Self {
             x: self.x.max(rhs.x),
@@ -195,6 +216,7 @@
     ///
     /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn clamp(self, min: Self, max: Self) -> Self {
         glam_assert!(min.cmple(max).all(), "clamp: expected min <= max");
         self.max(min).min(max)
@@ -204,6 +226,7 @@
     ///
     /// In other words this computes `min(x, y, ..)`.
     #[inline]
+    #[must_use]
     pub fn min_element(self) -> i32 {
         self.x.min(self.y.min(self.z))
     }
@@ -212,6 +235,7 @@
     ///
     /// In other words this computes `max(x, y, ..)`.
     #[inline]
+    #[must_use]
     pub fn max_element(self) -> i32 {
         self.x.max(self.y.max(self.z))
     }
@@ -222,6 +246,7 @@
     /// In other words, this computes `[self.x == rhs.x, self.y == rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpeq(self, rhs: Self) -> BVec3 {
         BVec3::new(self.x.eq(&rhs.x), self.y.eq(&rhs.y), self.z.eq(&rhs.z))
     }
@@ -232,6 +257,7 @@
     /// In other words this computes `[self.x != rhs.x, self.y != rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpne(self, rhs: Self) -> BVec3 {
         BVec3::new(self.x.ne(&rhs.x), self.y.ne(&rhs.y), self.z.ne(&rhs.z))
     }
@@ -242,6 +268,7 @@
     /// In other words this computes `[self.x >= rhs.x, self.y >= rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpge(self, rhs: Self) -> BVec3 {
         BVec3::new(self.x.ge(&rhs.x), self.y.ge(&rhs.y), self.z.ge(&rhs.z))
     }
@@ -252,6 +279,7 @@
     /// In other words this computes `[self.x > rhs.x, self.y > rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpgt(self, rhs: Self) -> BVec3 {
         BVec3::new(self.x.gt(&rhs.x), self.y.gt(&rhs.y), self.z.gt(&rhs.z))
     }
@@ -262,6 +290,7 @@
     /// In other words this computes `[self.x <= rhs.x, self.y <= rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmple(self, rhs: Self) -> BVec3 {
         BVec3::new(self.x.le(&rhs.x), self.y.le(&rhs.y), self.z.le(&rhs.z))
     }
@@ -272,12 +301,14 @@
     /// In other words this computes `[self.x < rhs.x, self.y < rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmplt(self, rhs: Self) -> BVec3 {
         BVec3::new(self.x.lt(&rhs.x), self.y.lt(&rhs.y), self.z.lt(&rhs.z))
     }
 
     /// Returns a vector containing the absolute value of each element of `self`.
     #[inline]
+    #[must_use]
     pub fn abs(self) -> Self {
         Self {
             x: self.x.abs(),
@@ -292,6 +323,7 @@
     ///  - `1` if the number is positive
     ///  - `-1` if the number is negative
     #[inline]
+    #[must_use]
     pub fn signum(self) -> Self {
         Self {
             x: self.x.signum(),
@@ -300,46 +332,222 @@
         }
     }
 
-    /// Returns a vector with signs of `rhs` and the magnitudes of `self`.
-    #[inline]
-    pub fn copysign(self, rhs: Self) -> Self {
-        Self::select(rhs.cmpge(Self::ZERO), self, -self)
-    }
-
     /// Returns a bitmask with the lowest 3 bits set to the sign bits from the elements of `self`.
     ///
     /// A negative element results in a `1` bit and a positive element in a `0` bit.  Element `x` goes
     /// into the first lowest bit, element `y` into the second, etc.
     #[inline]
+    #[must_use]
     pub fn is_negative_bitmask(self) -> u32 {
         (self.x.is_negative() as u32)
             | (self.y.is_negative() as u32) << 1
             | (self.z.is_negative() as u32) << 2
     }
 
+    /// Computes the squared length of `self`.
+    #[doc(alias = "magnitude2")]
+    #[inline]
+    #[must_use]
+    pub fn length_squared(self) -> i32 {
+        self.dot(self)
+    }
+
+    /// Compute the squared euclidean distance between two points in space.
+    #[inline]
+    #[must_use]
+    pub fn distance_squared(self, rhs: Self) -> i32 {
+        (self - rhs).length_squared()
+    }
+
+    /// Returns the element-wise quotient of [Euclidean division] of `self` by `rhs`.
+    ///
+    /// # Panics
+    /// This function will panic if any `rhs` element is 0 or the division results in overflow.
+    #[inline]
+    #[must_use]
+    pub fn div_euclid(self, rhs: Self) -> Self {
+        Self::new(
+            self.x.div_euclid(rhs.x),
+            self.y.div_euclid(rhs.y),
+            self.z.div_euclid(rhs.z),
+        )
+    }
+
+    /// Returns the element-wise remainder of [Euclidean division] of `self` by `rhs`.
+    ///
+    /// # Panics
+    /// This function will panic if any `rhs` element is 0 or the division results in overflow.
+    ///
+    /// [Euclidean division]: i32::rem_euclid
+    #[inline]
+    #[must_use]
+    pub fn rem_euclid(self, rhs: Self) -> Self {
+        Self::new(
+            self.x.rem_euclid(rhs.x),
+            self.y.rem_euclid(rhs.y),
+            self.z.rem_euclid(rhs.z),
+        )
+    }
+
     /// Casts all elements of `self` to `f32`.
     #[inline]
+    #[must_use]
     pub fn as_vec3(&self) -> crate::Vec3 {
         crate::Vec3::new(self.x as f32, self.y as f32, self.z as f32)
     }
 
     /// Casts all elements of `self` to `f32`.
     #[inline]
+    #[must_use]
     pub fn as_vec3a(&self) -> crate::Vec3A {
         crate::Vec3A::new(self.x as f32, self.y as f32, self.z as f32)
     }
 
     /// Casts all elements of `self` to `f64`.
     #[inline]
+    #[must_use]
     pub fn as_dvec3(&self) -> crate::DVec3 {
         crate::DVec3::new(self.x as f64, self.y as f64, self.z as f64)
     }
 
+    /// Casts all elements of `self` to `i16`.
+    #[inline]
+    #[must_use]
+    pub fn as_i16vec3(&self) -> crate::I16Vec3 {
+        crate::I16Vec3::new(self.x as i16, self.y as i16, self.z as i16)
+    }
+
+    /// Casts all elements of `self` to `u16`.
+    #[inline]
+    #[must_use]
+    pub fn as_u16vec3(&self) -> crate::U16Vec3 {
+        crate::U16Vec3::new(self.x as u16, self.y as u16, self.z as u16)
+    }
+
     /// Casts all elements of `self` to `u32`.
     #[inline]
+    #[must_use]
     pub fn as_uvec3(&self) -> crate::UVec3 {
         crate::UVec3::new(self.x as u32, self.y as u32, self.z as u32)
     }
+
+    /// Casts all elements of `self` to `i64`.
+    #[inline]
+    #[must_use]
+    pub fn as_i64vec3(&self) -> crate::I64Vec3 {
+        crate::I64Vec3::new(self.x as i64, self.y as i64, self.z as i64)
+    }
+
+    /// Casts all elements of `self` to `u64`.
+    #[inline]
+    #[must_use]
+    pub fn as_u64vec3(&self) -> crate::U64Vec3 {
+        crate::U64Vec3::new(self.x as u64, self.y as u64, self.z as u64)
+    }
+
+    /// Returns a vector containing the wrapping addition of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_add(rhs.x), self.y.wrapping_add(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_add(rhs.x),
+            y: self.y.wrapping_add(rhs.y),
+            z: self.z.wrapping_add(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the wrapping subtraction of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_sub(rhs.x), self.y.wrapping_sub(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_sub(rhs.x),
+            y: self.y.wrapping_sub(rhs.y),
+            z: self.z.wrapping_sub(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the wrapping multiplication of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_mul(rhs.x), self.y.wrapping_mul(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_mul(rhs.x),
+            y: self.y.wrapping_mul(rhs.y),
+            z: self.z.wrapping_mul(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the wrapping division of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_div(rhs.x), self.y.wrapping_div(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_div(rhs.x),
+            y: self.y.wrapping_div(rhs.y),
+            z: self.z.wrapping_div(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the saturating addition of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_add(rhs.x), self.y.saturating_add(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_add(rhs.x),
+            y: self.y.saturating_add(rhs.y),
+            z: self.z.saturating_add(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the saturating subtraction of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_sub(rhs.x), self.y.saturating_sub(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_sub(rhs.x),
+            y: self.y.saturating_sub(rhs.y),
+            z: self.z.saturating_sub(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the saturating multiplication of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_mul(rhs.x), self.y.saturating_mul(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_mul(rhs.x),
+            y: self.y.saturating_mul(rhs.y),
+            z: self.z.saturating_mul(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the saturating division of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_div(rhs.x), self.y.saturating_div(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_div(rhs.x),
+            y: self.y.saturating_div(rhs.y),
+            z: self.z.saturating_div(rhs.z),
+        }
+    }
 }
 
 impl Default for IVec3 {
@@ -843,6 +1051,30 @@
     }
 }
 
+impl Shl<i64> for IVec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i64> for IVec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+        }
+    }
+}
+
 impl Shl<u8> for IVec3 {
     type Output = Self;
     #[inline]
@@ -915,6 +1147,30 @@
     }
 }
 
+impl Shl<u64> for IVec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u64> for IVec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+        }
+    }
+}
+
 impl Shl<crate::IVec3> for IVec3 {
     type Output = Self;
     #[inline]
@@ -1040,3 +1296,56 @@
         Self::new(v.x, v.y, z)
     }
 }
+
+impl From<I16Vec3> for IVec3 {
+    #[inline]
+    fn from(v: I16Vec3) -> Self {
+        Self::new(i32::from(v.x), i32::from(v.y), i32::from(v.z))
+    }
+}
+
+impl From<U16Vec3> for IVec3 {
+    #[inline]
+    fn from(v: U16Vec3) -> Self {
+        Self::new(i32::from(v.x), i32::from(v.y), i32::from(v.z))
+    }
+}
+
+impl TryFrom<UVec3> for IVec3 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: UVec3) -> Result<Self, Self::Error> {
+        Ok(Self::new(
+            i32::try_from(v.x)?,
+            i32::try_from(v.y)?,
+            i32::try_from(v.z)?,
+        ))
+    }
+}
+
+impl TryFrom<I64Vec3> for IVec3 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: I64Vec3) -> Result<Self, Self::Error> {
+        Ok(Self::new(
+            i32::try_from(v.x)?,
+            i32::try_from(v.y)?,
+            i32::try_from(v.z)?,
+        ))
+    }
+}
+
+impl TryFrom<U64Vec3> for IVec3 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: U64Vec3) -> Result<Self, Self::Error> {
+        Ok(Self::new(
+            i32::try_from(v.x)?,
+            i32::try_from(v.y)?,
+            i32::try_from(v.z)?,
+        ))
+    }
+}
diff --git a/src/i32/ivec4.rs b/src/i32/ivec4.rs
index 7c07621..5ebdd69 100644
--- a/src/i32/ivec4.rs
+++ b/src/i32/ivec4.rs
@@ -1,6 +1,6 @@
 // Generated from vec.rs.tera template. Edit the template, not the generated file.
 
-use crate::{BVec4, IVec2, IVec3};
+use crate::{BVec4, I16Vec4, I64Vec4, IVec2, IVec3, U16Vec4, U64Vec4, UVec4};
 
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
@@ -9,6 +9,7 @@
 
 /// Creates a 4-dimensional vector.
 #[inline(always)]
+#[must_use]
 pub const fn ivec4(x: i32, y: i32, z: i32, w: i32) -> IVec4 {
     IVec4::new(x, y, z, w)
 }
@@ -36,28 +37,34 @@
     /// All negative ones.
     pub const NEG_ONE: Self = Self::splat(-1);
 
-    /// A unit-length vector pointing along the positive X axis.
+    /// All `i32::MIN`.
+    pub const MIN: Self = Self::splat(i32::MIN);
+
+    /// All `i32::MAX`.
+    pub const MAX: Self = Self::splat(i32::MAX);
+
+    /// A unit vector pointing along the positive X axis.
     pub const X: Self = Self::new(1, 0, 0, 0);
 
-    /// A unit-length vector pointing along the positive Y axis.
+    /// A unit vector pointing along the positive Y axis.
     pub const Y: Self = Self::new(0, 1, 0, 0);
 
-    /// A unit-length vector pointing along the positive Z axis.
+    /// A unit vector pointing along the positive Z axis.
     pub const Z: Self = Self::new(0, 0, 1, 0);
 
-    /// A unit-length vector pointing along the positive W axis.
+    /// A unit vector pointing along the positive W axis.
     pub const W: Self = Self::new(0, 0, 0, 1);
 
-    /// A unit-length vector pointing along the negative X axis.
+    /// A unit vector pointing along the negative X axis.
     pub const NEG_X: Self = Self::new(-1, 0, 0, 0);
 
-    /// A unit-length vector pointing along the negative Y axis.
+    /// A unit vector pointing along the negative Y axis.
     pub const NEG_Y: Self = Self::new(0, -1, 0, 0);
 
-    /// A unit-length vector pointing along the negative Z axis.
+    /// A unit vector pointing along the negative Z axis.
     pub const NEG_Z: Self = Self::new(0, 0, -1, 0);
 
-    /// A unit-length vector pointing along the negative W axis.
+    /// A unit vector pointing along the negative W axis.
     pub const NEG_W: Self = Self::new(0, 0, 0, -1);
 
     /// The unit axes.
@@ -65,12 +72,14 @@
 
     /// Creates a new vector.
     #[inline(always)]
+    #[must_use]
     pub const fn new(x: i32, y: i32, z: i32, w: i32) -> Self {
         Self { x, y, z, w }
     }
 
     /// Creates a vector with all elements set to `v`.
     #[inline]
+    #[must_use]
     pub const fn splat(v: i32) -> Self {
         Self {
             x: v,
@@ -89,23 +98,26 @@
     /// A true element in the mask uses the corresponding element from `if_true`, and false
     /// uses the element from `if_false`.
     #[inline]
+    #[must_use]
     pub fn select(mask: BVec4, if_true: Self, if_false: Self) -> Self {
         Self {
-            x: if mask.x { if_true.x } else { if_false.x },
-            y: if mask.y { if_true.y } else { if_false.y },
-            z: if mask.z { if_true.z } else { if_false.z },
-            w: if mask.w { if_true.w } else { if_false.w },
+            x: if mask.test(0) { if_true.x } else { if_false.x },
+            y: if mask.test(1) { if_true.y } else { if_false.y },
+            z: if mask.test(2) { if_true.z } else { if_false.z },
+            w: if mask.test(3) { if_true.w } else { if_false.w },
         }
     }
 
     /// Creates a new vector from an array.
     #[inline]
+    #[must_use]
     pub const fn from_array(a: [i32; 4]) -> Self {
         Self::new(a[0], a[1], a[2], a[3])
     }
 
     /// `[x, y, z, w]`
     #[inline]
+    #[must_use]
     pub const fn to_array(&self) -> [i32; 4] {
         [self.x, self.y, self.z, self.w]
     }
@@ -116,6 +128,7 @@
     ///
     /// Panics if `slice` is less than 4 elements long.
     #[inline]
+    #[must_use]
     pub const fn from_slice(slice: &[i32]) -> Self {
         Self::new(slice[0], slice[1], slice[2], slice[3])
     }
@@ -133,10 +146,11 @@
         slice[3] = self.w;
     }
 
-    /// Creates a 2D vector from the `x`, `y` and `z` elements of `self`, discarding `w`.
+    /// Creates a 3D vector from the `x`, `y` and `z` elements of `self`, discarding `w`.
     ///
-    /// Truncation to `IVec3` may also be performed by using `self.xyz()` or `IVec3::from()`.
+    /// Truncation to [`IVec3`] may also be performed by using [`self.xyz()`][crate::swizzles::Vec4Swizzles::xyz()].
     #[inline]
+    #[must_use]
     pub fn truncate(self) -> IVec3 {
         use crate::swizzles::Vec4Swizzles;
         self.xyz()
@@ -144,12 +158,14 @@
 
     /// Computes the dot product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn dot(self, rhs: Self) -> i32 {
         (self.x * rhs.x) + (self.y * rhs.y) + (self.z * rhs.z) + (self.w * rhs.w)
     }
 
     /// Returns a vector where every component is the dot product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn dot_into_vec(self, rhs: Self) -> Self {
         Self::splat(self.dot(rhs))
     }
@@ -158,6 +174,7 @@
     ///
     /// In other words this computes `[self.x.min(rhs.x), self.y.min(rhs.y), ..]`.
     #[inline]
+    #[must_use]
     pub fn min(self, rhs: Self) -> Self {
         Self {
             x: self.x.min(rhs.x),
@@ -171,6 +188,7 @@
     ///
     /// In other words this computes `[self.x.max(rhs.x), self.y.max(rhs.y), ..]`.
     #[inline]
+    #[must_use]
     pub fn max(self, rhs: Self) -> Self {
         Self {
             x: self.x.max(rhs.x),
@@ -188,6 +206,7 @@
     ///
     /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn clamp(self, min: Self, max: Self) -> Self {
         glam_assert!(min.cmple(max).all(), "clamp: expected min <= max");
         self.max(min).min(max)
@@ -197,6 +216,7 @@
     ///
     /// In other words this computes `min(x, y, ..)`.
     #[inline]
+    #[must_use]
     pub fn min_element(self) -> i32 {
         self.x.min(self.y.min(self.z.min(self.w)))
     }
@@ -205,6 +225,7 @@
     ///
     /// In other words this computes `max(x, y, ..)`.
     #[inline]
+    #[must_use]
     pub fn max_element(self) -> i32 {
         self.x.max(self.y.max(self.z.max(self.w)))
     }
@@ -215,6 +236,7 @@
     /// In other words, this computes `[self.x == rhs.x, self.y == rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpeq(self, rhs: Self) -> BVec4 {
         BVec4::new(
             self.x.eq(&rhs.x),
@@ -230,6 +252,7 @@
     /// In other words this computes `[self.x != rhs.x, self.y != rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpne(self, rhs: Self) -> BVec4 {
         BVec4::new(
             self.x.ne(&rhs.x),
@@ -245,6 +268,7 @@
     /// In other words this computes `[self.x >= rhs.x, self.y >= rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpge(self, rhs: Self) -> BVec4 {
         BVec4::new(
             self.x.ge(&rhs.x),
@@ -260,6 +284,7 @@
     /// In other words this computes `[self.x > rhs.x, self.y > rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpgt(self, rhs: Self) -> BVec4 {
         BVec4::new(
             self.x.gt(&rhs.x),
@@ -275,6 +300,7 @@
     /// In other words this computes `[self.x <= rhs.x, self.y <= rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmple(self, rhs: Self) -> BVec4 {
         BVec4::new(
             self.x.le(&rhs.x),
@@ -290,6 +316,7 @@
     /// In other words this computes `[self.x < rhs.x, self.y < rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmplt(self, rhs: Self) -> BVec4 {
         BVec4::new(
             self.x.lt(&rhs.x),
@@ -301,6 +328,7 @@
 
     /// Returns a vector containing the absolute value of each element of `self`.
     #[inline]
+    #[must_use]
     pub fn abs(self) -> Self {
         Self {
             x: self.x.abs(),
@@ -316,6 +344,7 @@
     ///  - `1` if the number is positive
     ///  - `-1` if the number is negative
     #[inline]
+    #[must_use]
     pub fn signum(self) -> Self {
         Self {
             x: self.x.signum(),
@@ -325,17 +354,12 @@
         }
     }
 
-    /// Returns a vector with signs of `rhs` and the magnitudes of `self`.
-    #[inline]
-    pub fn copysign(self, rhs: Self) -> Self {
-        Self::select(rhs.cmpge(Self::ZERO), self, -self)
-    }
-
     /// Returns a bitmask with the lowest 4 bits set to the sign bits from the elements of `self`.
     ///
     /// A negative element results in a `1` bit and a positive element in a `0` bit.  Element `x` goes
     /// into the first lowest bit, element `y` into the second, etc.
     #[inline]
+    #[must_use]
     pub fn is_negative_bitmask(self) -> u32 {
         (self.x.is_negative() as u32)
             | (self.y.is_negative() as u32) << 1
@@ -343,23 +367,213 @@
             | (self.w.is_negative() as u32) << 3
     }
 
+    /// Computes the squared length of `self`.
+    #[doc(alias = "magnitude2")]
+    #[inline]
+    #[must_use]
+    pub fn length_squared(self) -> i32 {
+        self.dot(self)
+    }
+
+    /// Compute the squared euclidean distance between two points in space.
+    #[inline]
+    #[must_use]
+    pub fn distance_squared(self, rhs: Self) -> i32 {
+        (self - rhs).length_squared()
+    }
+
+    /// Returns the element-wise quotient of [Euclidean division] of `self` by `rhs`.
+    ///
+    /// # Panics
+    /// This function will panic if any `rhs` element is 0 or the division results in overflow.
+    #[inline]
+    #[must_use]
+    pub fn div_euclid(self, rhs: Self) -> Self {
+        Self::new(
+            self.x.div_euclid(rhs.x),
+            self.y.div_euclid(rhs.y),
+            self.z.div_euclid(rhs.z),
+            self.w.div_euclid(rhs.w),
+        )
+    }
+
+    /// Returns the element-wise remainder of [Euclidean division] of `self` by `rhs`.
+    ///
+    /// # Panics
+    /// This function will panic if any `rhs` element is 0 or the division results in overflow.
+    ///
+    /// [Euclidean division]: i32::rem_euclid
+    #[inline]
+    #[must_use]
+    pub fn rem_euclid(self, rhs: Self) -> Self {
+        Self::new(
+            self.x.rem_euclid(rhs.x),
+            self.y.rem_euclid(rhs.y),
+            self.z.rem_euclid(rhs.z),
+            self.w.rem_euclid(rhs.w),
+        )
+    }
+
     /// Casts all elements of `self` to `f32`.
     #[inline]
+    #[must_use]
     pub fn as_vec4(&self) -> crate::Vec4 {
         crate::Vec4::new(self.x as f32, self.y as f32, self.z as f32, self.w as f32)
     }
 
     /// Casts all elements of `self` to `f64`.
     #[inline]
+    #[must_use]
     pub fn as_dvec4(&self) -> crate::DVec4 {
         crate::DVec4::new(self.x as f64, self.y as f64, self.z as f64, self.w as f64)
     }
 
+    /// Casts all elements of `self` to `i16`.
+    #[inline]
+    #[must_use]
+    pub fn as_i16vec4(&self) -> crate::I16Vec4 {
+        crate::I16Vec4::new(self.x as i16, self.y as i16, self.z as i16, self.w as i16)
+    }
+
+    /// Casts all elements of `self` to `u16`.
+    #[inline]
+    #[must_use]
+    pub fn as_u16vec4(&self) -> crate::U16Vec4 {
+        crate::U16Vec4::new(self.x as u16, self.y as u16, self.z as u16, self.w as u16)
+    }
+
     /// Casts all elements of `self` to `u32`.
     #[inline]
+    #[must_use]
     pub fn as_uvec4(&self) -> crate::UVec4 {
         crate::UVec4::new(self.x as u32, self.y as u32, self.z as u32, self.w as u32)
     }
+
+    /// Casts all elements of `self` to `i64`.
+    #[inline]
+    #[must_use]
+    pub fn as_i64vec4(&self) -> crate::I64Vec4 {
+        crate::I64Vec4::new(self.x as i64, self.y as i64, self.z as i64, self.w as i64)
+    }
+
+    /// Casts all elements of `self` to `u64`.
+    #[inline]
+    #[must_use]
+    pub fn as_u64vec4(&self) -> crate::U64Vec4 {
+        crate::U64Vec4::new(self.x as u64, self.y as u64, self.z as u64, self.w as u64)
+    }
+
+    /// Returns a vector containing the wrapping addition of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_add(rhs.x), self.y.wrapping_add(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_add(rhs.x),
+            y: self.y.wrapping_add(rhs.y),
+            z: self.z.wrapping_add(rhs.z),
+            w: self.w.wrapping_add(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the wrapping subtraction of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_sub(rhs.x), self.y.wrapping_sub(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_sub(rhs.x),
+            y: self.y.wrapping_sub(rhs.y),
+            z: self.z.wrapping_sub(rhs.z),
+            w: self.w.wrapping_sub(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the wrapping multiplication of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_mul(rhs.x), self.y.wrapping_mul(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_mul(rhs.x),
+            y: self.y.wrapping_mul(rhs.y),
+            z: self.z.wrapping_mul(rhs.z),
+            w: self.w.wrapping_mul(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the wrapping division of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_div(rhs.x), self.y.wrapping_div(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_div(rhs.x),
+            y: self.y.wrapping_div(rhs.y),
+            z: self.z.wrapping_div(rhs.z),
+            w: self.w.wrapping_div(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the saturating addition of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_add(rhs.x), self.y.saturating_add(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_add(rhs.x),
+            y: self.y.saturating_add(rhs.y),
+            z: self.z.saturating_add(rhs.z),
+            w: self.w.saturating_add(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the saturating subtraction of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_sub(rhs.x), self.y.saturating_sub(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_sub(rhs.x),
+            y: self.y.saturating_sub(rhs.y),
+            z: self.z.saturating_sub(rhs.z),
+            w: self.w.saturating_sub(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the saturating multiplication of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_mul(rhs.x), self.y.saturating_mul(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_mul(rhs.x),
+            y: self.y.saturating_mul(rhs.y),
+            z: self.z.saturating_mul(rhs.z),
+            w: self.w.saturating_mul(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the saturating division of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_div(rhs.x), self.y.saturating_div(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_div(rhs.x),
+            y: self.y.saturating_div(rhs.y),
+            z: self.z.saturating_div(rhs.z),
+            w: self.w.saturating_div(rhs.w),
+        }
+    }
 }
 
 impl Default for IVec4 {
@@ -902,6 +1116,32 @@
     }
 }
 
+impl Shl<i64> for IVec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+            w: self.w.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i64> for IVec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+            w: self.w.shr(rhs),
+        }
+    }
+}
+
 impl Shl<u8> for IVec4 {
     type Output = Self;
     #[inline]
@@ -980,6 +1220,32 @@
     }
 }
 
+impl Shl<u64> for IVec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+            w: self.w.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u64> for IVec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+            w: self.w.shr(rhs),
+        }
+    }
+}
+
 impl Shl<crate::IVec4> for IVec4 {
     type Output = Self;
     #[inline]
@@ -1133,3 +1399,69 @@
         Self::new(v.x, v.y, u.x, u.y)
     }
 }
+
+impl From<I16Vec4> for IVec4 {
+    #[inline]
+    fn from(v: I16Vec4) -> Self {
+        Self::new(
+            i32::from(v.x),
+            i32::from(v.y),
+            i32::from(v.z),
+            i32::from(v.w),
+        )
+    }
+}
+
+impl From<U16Vec4> for IVec4 {
+    #[inline]
+    fn from(v: U16Vec4) -> Self {
+        Self::new(
+            i32::from(v.x),
+            i32::from(v.y),
+            i32::from(v.z),
+            i32::from(v.w),
+        )
+    }
+}
+
+impl TryFrom<UVec4> for IVec4 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: UVec4) -> Result<Self, Self::Error> {
+        Ok(Self::new(
+            i32::try_from(v.x)?,
+            i32::try_from(v.y)?,
+            i32::try_from(v.z)?,
+            i32::try_from(v.w)?,
+        ))
+    }
+}
+
+impl TryFrom<I64Vec4> for IVec4 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: I64Vec4) -> Result<Self, Self::Error> {
+        Ok(Self::new(
+            i32::try_from(v.x)?,
+            i32::try_from(v.y)?,
+            i32::try_from(v.z)?,
+            i32::try_from(v.w)?,
+        ))
+    }
+}
+
+impl TryFrom<U64Vec4> for IVec4 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: U64Vec4) -> Result<Self, Self::Error> {
+        Ok(Self::new(
+            i32::try_from(v.x)?,
+            i32::try_from(v.y)?,
+            i32::try_from(v.z)?,
+            i32::try_from(v.w)?,
+        ))
+    }
+}
diff --git a/src/i64.rs b/src/i64.rs
new file mode 100644
index 0000000..03f2a0f
--- /dev/null
+++ b/src/i64.rs
@@ -0,0 +1,45 @@
+mod i64vec2;
+mod i64vec3;
+mod i64vec4;
+
+pub use i64vec2::{i64vec2, I64Vec2};
+pub use i64vec3::{i64vec3, I64Vec3};
+pub use i64vec4::{i64vec4, I64Vec4};
+
+#[cfg(not(target_arch = "spirv"))]
+mod test {
+    use super::*;
+
+    mod const_test_i64vec2 {
+        const_assert_eq!(16, core::mem::size_of::<super::I64Vec2>());
+
+        #[cfg(not(feature = "cuda"))]
+        const_assert_eq!(
+            core::mem::align_of::<i64>(),
+            core::mem::align_of::<super::I64Vec2>()
+        );
+        #[cfg(feature = "cuda")]
+        const_assert_eq!(16, core::mem::align_of::<super::I64Vec2>());
+    }
+
+    mod const_test_i64vec3 {
+        const_assert_eq!(24, core::mem::size_of::<super::I64Vec3>());
+
+        const_assert_eq!(
+            core::mem::align_of::<i64>(),
+            core::mem::align_of::<super::I64Vec3>()
+        );
+    }
+
+    mod const_test_i64vec4 {
+        const_assert_eq!(32, core::mem::size_of::<super::I64Vec4>());
+
+        #[cfg(not(feature = "cuda"))]
+        const_assert_eq!(
+            core::mem::align_of::<i64>(),
+            core::mem::align_of::<super::I64Vec4>()
+        );
+        #[cfg(feature = "cuda")]
+        const_assert_eq!(16, core::mem::align_of::<super::I64Vec4>());
+    }
+}
diff --git a/src/i64/i64vec2.rs b/src/i64/i64vec2.rs
new file mode 100644
index 0000000..b1355d1
--- /dev/null
+++ b/src/i64/i64vec2.rs
@@ -0,0 +1,1235 @@
+// Generated from vec.rs.tera template. Edit the template, not the generated file.
+
+use crate::{BVec2, I16Vec2, I64Vec3, IVec2, U16Vec2, U64Vec2, UVec2};
+
+#[cfg(not(target_arch = "spirv"))]
+use core::fmt;
+use core::iter::{Product, Sum};
+use core::{f32, ops::*};
+
+/// Creates a 2-dimensional vector.
+#[inline(always)]
+#[must_use]
+pub const fn i64vec2(x: i64, y: i64) -> I64Vec2 {
+    I64Vec2::new(x, y)
+}
+
+/// A 2-dimensional vector.
+#[cfg_attr(not(target_arch = "spirv"), derive(Hash))]
+#[derive(Clone, Copy, PartialEq, Eq)]
+#[cfg_attr(feature = "cuda", repr(align(16)))]
+#[cfg_attr(not(target_arch = "spirv"), repr(C))]
+#[cfg_attr(target_arch = "spirv", repr(simd))]
+pub struct I64Vec2 {
+    pub x: i64,
+    pub y: i64,
+}
+
+impl I64Vec2 {
+    /// All zeroes.
+    pub const ZERO: Self = Self::splat(0);
+
+    /// All ones.
+    pub const ONE: Self = Self::splat(1);
+
+    /// All negative ones.
+    pub const NEG_ONE: Self = Self::splat(-1);
+
+    /// All `i64::MIN`.
+    pub const MIN: Self = Self::splat(i64::MIN);
+
+    /// All `i64::MAX`.
+    pub const MAX: Self = Self::splat(i64::MAX);
+
+    /// A unit vector pointing along the positive X axis.
+    pub const X: Self = Self::new(1, 0);
+
+    /// A unit vector pointing along the positive Y axis.
+    pub const Y: Self = Self::new(0, 1);
+
+    /// A unit vector pointing along the negative X axis.
+    pub const NEG_X: Self = Self::new(-1, 0);
+
+    /// A unit vector pointing along the negative Y axis.
+    pub const NEG_Y: Self = Self::new(0, -1);
+
+    /// The unit axes.
+    pub const AXES: [Self; 2] = [Self::X, Self::Y];
+
+    /// Creates a new vector.
+    #[inline(always)]
+    #[must_use]
+    pub const fn new(x: i64, y: i64) -> Self {
+        Self { x, y }
+    }
+
+    /// Creates a vector with all elements set to `v`.
+    #[inline]
+    #[must_use]
+    pub const fn splat(v: i64) -> Self {
+        Self { x: v, y: v }
+    }
+
+    /// Creates a vector from the elements in `if_true` and `if_false`, selecting which to use
+    /// for each element of `self`.
+    ///
+    /// A true element in the mask uses the corresponding element from `if_true`, and false
+    /// uses the element from `if_false`.
+    #[inline]
+    #[must_use]
+    pub fn select(mask: BVec2, if_true: Self, if_false: Self) -> Self {
+        Self {
+            x: if mask.test(0) { if_true.x } else { if_false.x },
+            y: if mask.test(1) { if_true.y } else { if_false.y },
+        }
+    }
+
+    /// Creates a new vector from an array.
+    #[inline]
+    #[must_use]
+    pub const fn from_array(a: [i64; 2]) -> Self {
+        Self::new(a[0], a[1])
+    }
+
+    /// `[x, y]`
+    #[inline]
+    #[must_use]
+    pub const fn to_array(&self) -> [i64; 2] {
+        [self.x, self.y]
+    }
+
+    /// Creates a vector from the first 2 values in `slice`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `slice` is less than 2 elements long.
+    #[inline]
+    #[must_use]
+    pub const fn from_slice(slice: &[i64]) -> Self {
+        Self::new(slice[0], slice[1])
+    }
+
+    /// Writes the elements of `self` to the first 2 elements in `slice`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `slice` is less than 2 elements long.
+    #[inline]
+    pub fn write_to_slice(self, slice: &mut [i64]) {
+        slice[0] = self.x;
+        slice[1] = self.y;
+    }
+
+    /// Creates a 3D vector from `self` and the given `z` value.
+    #[inline]
+    #[must_use]
+    pub const fn extend(self, z: i64) -> I64Vec3 {
+        I64Vec3::new(self.x, self.y, z)
+    }
+
+    /// Computes the dot product of `self` and `rhs`.
+    #[inline]
+    #[must_use]
+    pub fn dot(self, rhs: Self) -> i64 {
+        (self.x * rhs.x) + (self.y * rhs.y)
+    }
+
+    /// Returns a vector where every component is the dot product of `self` and `rhs`.
+    #[inline]
+    #[must_use]
+    pub fn dot_into_vec(self, rhs: Self) -> Self {
+        Self::splat(self.dot(rhs))
+    }
+
+    /// Returns a vector containing the minimum values for each element of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.min(rhs.x), self.y.min(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub fn min(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.min(rhs.x),
+            y: self.y.min(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the maximum values for each element of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.max(rhs.x), self.y.max(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub fn max(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.max(rhs.x),
+            y: self.y.max(rhs.y),
+        }
+    }
+
+    /// Component-wise clamping of values, similar to [`i64::clamp`].
+    ///
+    /// Each element in `min` must be less-or-equal to the corresponding element in `max`.
+    ///
+    /// # Panics
+    ///
+    /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
+    #[inline]
+    #[must_use]
+    pub fn clamp(self, min: Self, max: Self) -> Self {
+        glam_assert!(min.cmple(max).all(), "clamp: expected min <= max");
+        self.max(min).min(max)
+    }
+
+    /// Returns the horizontal minimum of `self`.
+    ///
+    /// In other words this computes `min(x, y, ..)`.
+    #[inline]
+    #[must_use]
+    pub fn min_element(self) -> i64 {
+        self.x.min(self.y)
+    }
+
+    /// Returns the horizontal maximum of `self`.
+    ///
+    /// In other words this computes `max(x, y, ..)`.
+    #[inline]
+    #[must_use]
+    pub fn max_element(self) -> i64 {
+        self.x.max(self.y)
+    }
+
+    /// Returns a vector mask containing the result of a `==` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words, this computes `[self.x == rhs.x, self.y == rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpeq(self, rhs: Self) -> BVec2 {
+        BVec2::new(self.x.eq(&rhs.x), self.y.eq(&rhs.y))
+    }
+
+    /// Returns a vector mask containing the result of a `!=` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x != rhs.x, self.y != rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpne(self, rhs: Self) -> BVec2 {
+        BVec2::new(self.x.ne(&rhs.x), self.y.ne(&rhs.y))
+    }
+
+    /// Returns a vector mask containing the result of a `>=` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x >= rhs.x, self.y >= rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpge(self, rhs: Self) -> BVec2 {
+        BVec2::new(self.x.ge(&rhs.x), self.y.ge(&rhs.y))
+    }
+
+    /// Returns a vector mask containing the result of a `>` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x > rhs.x, self.y > rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpgt(self, rhs: Self) -> BVec2 {
+        BVec2::new(self.x.gt(&rhs.x), self.y.gt(&rhs.y))
+    }
+
+    /// Returns a vector mask containing the result of a `<=` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x <= rhs.x, self.y <= rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmple(self, rhs: Self) -> BVec2 {
+        BVec2::new(self.x.le(&rhs.x), self.y.le(&rhs.y))
+    }
+
+    /// Returns a vector mask containing the result of a `<` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x < rhs.x, self.y < rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmplt(self, rhs: Self) -> BVec2 {
+        BVec2::new(self.x.lt(&rhs.x), self.y.lt(&rhs.y))
+    }
+
+    /// Returns a vector containing the absolute value of each element of `self`.
+    #[inline]
+    #[must_use]
+    pub fn abs(self) -> Self {
+        Self {
+            x: self.x.abs(),
+            y: self.y.abs(),
+        }
+    }
+
+    /// Returns a vector with elements representing the sign of `self`.
+    ///
+    ///  - `0` if the number is zero
+    ///  - `1` if the number is positive
+    ///  - `-1` if the number is negative
+    #[inline]
+    #[must_use]
+    pub fn signum(self) -> Self {
+        Self {
+            x: self.x.signum(),
+            y: self.y.signum(),
+        }
+    }
+
+    /// Returns a bitmask with the lowest 2 bits set to the sign bits from the elements of `self`.
+    ///
+    /// A negative element results in a `1` bit and a positive element in a `0` bit.  Element `x` goes
+    /// into the first lowest bit, element `y` into the second, etc.
+    #[inline]
+    #[must_use]
+    pub fn is_negative_bitmask(self) -> u32 {
+        (self.x.is_negative() as u32) | (self.y.is_negative() as u32) << 1
+    }
+
+    /// Computes the squared length of `self`.
+    #[doc(alias = "magnitude2")]
+    #[inline]
+    #[must_use]
+    pub fn length_squared(self) -> i64 {
+        self.dot(self)
+    }
+
+    /// Compute the squared euclidean distance between two points in space.
+    #[inline]
+    #[must_use]
+    pub fn distance_squared(self, rhs: Self) -> i64 {
+        (self - rhs).length_squared()
+    }
+
+    /// Returns the element-wise quotient of [Euclidean division] of `self` by `rhs`.
+    ///
+    /// # Panics
+    /// This function will panic if any `rhs` element is 0 or the division results in overflow.
+    #[inline]
+    #[must_use]
+    pub fn div_euclid(self, rhs: Self) -> Self {
+        Self::new(self.x.div_euclid(rhs.x), self.y.div_euclid(rhs.y))
+    }
+
+    /// Returns the element-wise remainder of [Euclidean division] of `self` by `rhs`.
+    ///
+    /// # Panics
+    /// This function will panic if any `rhs` element is 0 or the division results in overflow.
+    ///
+    /// [Euclidean division]: i64::rem_euclid
+    #[inline]
+    #[must_use]
+    pub fn rem_euclid(self, rhs: Self) -> Self {
+        Self::new(self.x.rem_euclid(rhs.x), self.y.rem_euclid(rhs.y))
+    }
+
+    /// Returns a vector that is equal to `self` rotated by 90 degrees.
+    #[inline]
+    #[must_use]
+    pub fn perp(self) -> Self {
+        Self {
+            x: -self.y,
+            y: self.x,
+        }
+    }
+
+    /// The perpendicular dot product of `self` and `rhs`.
+    /// Also known as the wedge product, 2D cross product, and determinant.
+    #[doc(alias = "wedge")]
+    #[doc(alias = "cross")]
+    #[doc(alias = "determinant")]
+    #[inline]
+    #[must_use]
+    pub fn perp_dot(self, rhs: Self) -> i64 {
+        (self.x * rhs.y) - (self.y * rhs.x)
+    }
+
+    /// Returns `rhs` rotated by the angle of `self`. If `self` is normalized,
+    /// then this just rotation. This is what you usually want. Otherwise,
+    /// it will be like a rotation with a multiplication by `self`'s length.
+    #[inline]
+    #[must_use]
+    pub fn rotate(self, rhs: Self) -> Self {
+        Self {
+            x: self.x * rhs.x - self.y * rhs.y,
+            y: self.y * rhs.x + self.x * rhs.y,
+        }
+    }
+
+    /// Casts all elements of `self` to `f32`.
+    #[inline]
+    #[must_use]
+    pub fn as_vec2(&self) -> crate::Vec2 {
+        crate::Vec2::new(self.x as f32, self.y as f32)
+    }
+
+    /// Casts all elements of `self` to `f64`.
+    #[inline]
+    #[must_use]
+    pub fn as_dvec2(&self) -> crate::DVec2 {
+        crate::DVec2::new(self.x as f64, self.y as f64)
+    }
+
+    /// Casts all elements of `self` to `i16`.
+    #[inline]
+    #[must_use]
+    pub fn as_i16vec2(&self) -> crate::I16Vec2 {
+        crate::I16Vec2::new(self.x as i16, self.y as i16)
+    }
+
+    /// Casts all elements of `self` to `u16`.
+    #[inline]
+    #[must_use]
+    pub fn as_u16vec2(&self) -> crate::U16Vec2 {
+        crate::U16Vec2::new(self.x as u16, self.y as u16)
+    }
+
+    /// Casts all elements of `self` to `i32`.
+    #[inline]
+    #[must_use]
+    pub fn as_ivec2(&self) -> crate::IVec2 {
+        crate::IVec2::new(self.x as i32, self.y as i32)
+    }
+
+    /// Casts all elements of `self` to `u32`.
+    #[inline]
+    #[must_use]
+    pub fn as_uvec2(&self) -> crate::UVec2 {
+        crate::UVec2::new(self.x as u32, self.y as u32)
+    }
+
+    /// Casts all elements of `self` to `u64`.
+    #[inline]
+    #[must_use]
+    pub fn as_u64vec2(&self) -> crate::U64Vec2 {
+        crate::U64Vec2::new(self.x as u64, self.y as u64)
+    }
+
+    /// Returns a vector containing the wrapping addition of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_add(rhs.x), self.y.wrapping_add(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_add(rhs.x),
+            y: self.y.wrapping_add(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the wrapping subtraction of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_sub(rhs.x), self.y.wrapping_sub(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_sub(rhs.x),
+            y: self.y.wrapping_sub(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the wrapping multiplication of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_mul(rhs.x), self.y.wrapping_mul(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_mul(rhs.x),
+            y: self.y.wrapping_mul(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the wrapping division of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_div(rhs.x), self.y.wrapping_div(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_div(rhs.x),
+            y: self.y.wrapping_div(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the saturating addition of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_add(rhs.x), self.y.saturating_add(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_add(rhs.x),
+            y: self.y.saturating_add(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the saturating subtraction of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_sub(rhs.x), self.y.saturating_sub(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_sub(rhs.x),
+            y: self.y.saturating_sub(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the saturating multiplication of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_mul(rhs.x), self.y.saturating_mul(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_mul(rhs.x),
+            y: self.y.saturating_mul(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the saturating division of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_div(rhs.x), self.y.saturating_div(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_div(rhs.x),
+            y: self.y.saturating_div(rhs.y),
+        }
+    }
+}
+
+impl Default for I64Vec2 {
+    #[inline(always)]
+    fn default() -> Self {
+        Self::ZERO
+    }
+}
+
+impl Div<I64Vec2> for I64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.div(rhs.x),
+            y: self.y.div(rhs.y),
+        }
+    }
+}
+
+impl DivAssign<I64Vec2> for I64Vec2 {
+    #[inline]
+    fn div_assign(&mut self, rhs: Self) {
+        self.x.div_assign(rhs.x);
+        self.y.div_assign(rhs.y);
+    }
+}
+
+impl Div<i64> for I64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn div(self, rhs: i64) -> Self {
+        Self {
+            x: self.x.div(rhs),
+            y: self.y.div(rhs),
+        }
+    }
+}
+
+impl DivAssign<i64> for I64Vec2 {
+    #[inline]
+    fn div_assign(&mut self, rhs: i64) {
+        self.x.div_assign(rhs);
+        self.y.div_assign(rhs);
+    }
+}
+
+impl Div<I64Vec2> for i64 {
+    type Output = I64Vec2;
+    #[inline]
+    fn div(self, rhs: I64Vec2) -> I64Vec2 {
+        I64Vec2 {
+            x: self.div(rhs.x),
+            y: self.div(rhs.y),
+        }
+    }
+}
+
+impl Mul<I64Vec2> for I64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.mul(rhs.x),
+            y: self.y.mul(rhs.y),
+        }
+    }
+}
+
+impl MulAssign<I64Vec2> for I64Vec2 {
+    #[inline]
+    fn mul_assign(&mut self, rhs: Self) {
+        self.x.mul_assign(rhs.x);
+        self.y.mul_assign(rhs.y);
+    }
+}
+
+impl Mul<i64> for I64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn mul(self, rhs: i64) -> Self {
+        Self {
+            x: self.x.mul(rhs),
+            y: self.y.mul(rhs),
+        }
+    }
+}
+
+impl MulAssign<i64> for I64Vec2 {
+    #[inline]
+    fn mul_assign(&mut self, rhs: i64) {
+        self.x.mul_assign(rhs);
+        self.y.mul_assign(rhs);
+    }
+}
+
+impl Mul<I64Vec2> for i64 {
+    type Output = I64Vec2;
+    #[inline]
+    fn mul(self, rhs: I64Vec2) -> I64Vec2 {
+        I64Vec2 {
+            x: self.mul(rhs.x),
+            y: self.mul(rhs.y),
+        }
+    }
+}
+
+impl Add<I64Vec2> for I64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.add(rhs.x),
+            y: self.y.add(rhs.y),
+        }
+    }
+}
+
+impl AddAssign<I64Vec2> for I64Vec2 {
+    #[inline]
+    fn add_assign(&mut self, rhs: Self) {
+        self.x.add_assign(rhs.x);
+        self.y.add_assign(rhs.y);
+    }
+}
+
+impl Add<i64> for I64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn add(self, rhs: i64) -> Self {
+        Self {
+            x: self.x.add(rhs),
+            y: self.y.add(rhs),
+        }
+    }
+}
+
+impl AddAssign<i64> for I64Vec2 {
+    #[inline]
+    fn add_assign(&mut self, rhs: i64) {
+        self.x.add_assign(rhs);
+        self.y.add_assign(rhs);
+    }
+}
+
+impl Add<I64Vec2> for i64 {
+    type Output = I64Vec2;
+    #[inline]
+    fn add(self, rhs: I64Vec2) -> I64Vec2 {
+        I64Vec2 {
+            x: self.add(rhs.x),
+            y: self.add(rhs.y),
+        }
+    }
+}
+
+impl Sub<I64Vec2> for I64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.sub(rhs.x),
+            y: self.y.sub(rhs.y),
+        }
+    }
+}
+
+impl SubAssign<I64Vec2> for I64Vec2 {
+    #[inline]
+    fn sub_assign(&mut self, rhs: I64Vec2) {
+        self.x.sub_assign(rhs.x);
+        self.y.sub_assign(rhs.y);
+    }
+}
+
+impl Sub<i64> for I64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn sub(self, rhs: i64) -> Self {
+        Self {
+            x: self.x.sub(rhs),
+            y: self.y.sub(rhs),
+        }
+    }
+}
+
+impl SubAssign<i64> for I64Vec2 {
+    #[inline]
+    fn sub_assign(&mut self, rhs: i64) {
+        self.x.sub_assign(rhs);
+        self.y.sub_assign(rhs);
+    }
+}
+
+impl Sub<I64Vec2> for i64 {
+    type Output = I64Vec2;
+    #[inline]
+    fn sub(self, rhs: I64Vec2) -> I64Vec2 {
+        I64Vec2 {
+            x: self.sub(rhs.x),
+            y: self.sub(rhs.y),
+        }
+    }
+}
+
+impl Rem<I64Vec2> for I64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn rem(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.rem(rhs.x),
+            y: self.y.rem(rhs.y),
+        }
+    }
+}
+
+impl RemAssign<I64Vec2> for I64Vec2 {
+    #[inline]
+    fn rem_assign(&mut self, rhs: Self) {
+        self.x.rem_assign(rhs.x);
+        self.y.rem_assign(rhs.y);
+    }
+}
+
+impl Rem<i64> for I64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn rem(self, rhs: i64) -> Self {
+        Self {
+            x: self.x.rem(rhs),
+            y: self.y.rem(rhs),
+        }
+    }
+}
+
+impl RemAssign<i64> for I64Vec2 {
+    #[inline]
+    fn rem_assign(&mut self, rhs: i64) {
+        self.x.rem_assign(rhs);
+        self.y.rem_assign(rhs);
+    }
+}
+
+impl Rem<I64Vec2> for i64 {
+    type Output = I64Vec2;
+    #[inline]
+    fn rem(self, rhs: I64Vec2) -> I64Vec2 {
+        I64Vec2 {
+            x: self.rem(rhs.x),
+            y: self.rem(rhs.y),
+        }
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl AsRef<[i64; 2]> for I64Vec2 {
+    #[inline]
+    fn as_ref(&self) -> &[i64; 2] {
+        unsafe { &*(self as *const I64Vec2 as *const [i64; 2]) }
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl AsMut<[i64; 2]> for I64Vec2 {
+    #[inline]
+    fn as_mut(&mut self) -> &mut [i64; 2] {
+        unsafe { &mut *(self as *mut I64Vec2 as *mut [i64; 2]) }
+    }
+}
+
+impl Sum for I64Vec2 {
+    #[inline]
+    fn sum<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = Self>,
+    {
+        iter.fold(Self::ZERO, Self::add)
+    }
+}
+
+impl<'a> Sum<&'a Self> for I64Vec2 {
+    #[inline]
+    fn sum<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = &'a Self>,
+    {
+        iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
+    }
+}
+
+impl Product for I64Vec2 {
+    #[inline]
+    fn product<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = Self>,
+    {
+        iter.fold(Self::ONE, Self::mul)
+    }
+}
+
+impl<'a> Product<&'a Self> for I64Vec2 {
+    #[inline]
+    fn product<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = &'a Self>,
+    {
+        iter.fold(Self::ONE, |a, &b| Self::mul(a, b))
+    }
+}
+
+impl Neg for I64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn neg(self) -> Self {
+        Self {
+            x: self.x.neg(),
+            y: self.y.neg(),
+        }
+    }
+}
+
+impl Not for I64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn not(self) -> Self::Output {
+        Self {
+            x: self.x.not(),
+            y: self.y.not(),
+        }
+    }
+}
+
+impl BitAnd for I64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn bitand(self, rhs: Self) -> Self::Output {
+        Self {
+            x: self.x.bitand(rhs.x),
+            y: self.y.bitand(rhs.y),
+        }
+    }
+}
+
+impl BitOr for I64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn bitor(self, rhs: Self) -> Self::Output {
+        Self {
+            x: self.x.bitor(rhs.x),
+            y: self.y.bitor(rhs.y),
+        }
+    }
+}
+
+impl BitXor for I64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn bitxor(self, rhs: Self) -> Self::Output {
+        Self {
+            x: self.x.bitxor(rhs.x),
+            y: self.y.bitxor(rhs.y),
+        }
+    }
+}
+
+impl BitAnd<i64> for I64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn bitand(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.bitand(rhs),
+            y: self.y.bitand(rhs),
+        }
+    }
+}
+
+impl BitOr<i64> for I64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn bitor(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.bitor(rhs),
+            y: self.y.bitor(rhs),
+        }
+    }
+}
+
+impl BitXor<i64> for I64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn bitxor(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.bitxor(rhs),
+            y: self.y.bitxor(rhs),
+        }
+    }
+}
+
+impl Shl<i8> for I64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i8) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i8> for I64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i8) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+        }
+    }
+}
+
+impl Shl<i16> for I64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i16) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i16> for I64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i16) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+        }
+    }
+}
+
+impl Shl<i32> for I64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i32) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i32> for I64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i32) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+        }
+    }
+}
+
+impl Shl<i64> for I64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i64> for I64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u8> for I64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u8) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u8> for I64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u8) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u16> for I64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u16) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u16> for I64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u16) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u32> for I64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u32) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u32> for I64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u32) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u64> for I64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u64> for I64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+        }
+    }
+}
+
+impl Shl<crate::IVec2> for I64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: crate::IVec2) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs.x),
+            y: self.y.shl(rhs.y),
+        }
+    }
+}
+
+impl Shr<crate::IVec2> for I64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: crate::IVec2) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs.x),
+            y: self.y.shr(rhs.y),
+        }
+    }
+}
+
+impl Shl<crate::UVec2> for I64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: crate::UVec2) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs.x),
+            y: self.y.shl(rhs.y),
+        }
+    }
+}
+
+impl Shr<crate::UVec2> for I64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: crate::UVec2) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs.x),
+            y: self.y.shr(rhs.y),
+        }
+    }
+}
+
+impl Index<usize> for I64Vec2 {
+    type Output = i64;
+    #[inline]
+    fn index(&self, index: usize) -> &Self::Output {
+        match index {
+            0 => &self.x,
+            1 => &self.y,
+            _ => panic!("index out of bounds"),
+        }
+    }
+}
+
+impl IndexMut<usize> for I64Vec2 {
+    #[inline]
+    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
+        match index {
+            0 => &mut self.x,
+            1 => &mut self.y,
+            _ => panic!("index out of bounds"),
+        }
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl fmt::Display for I64Vec2 {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "[{}, {}]", self.x, self.y)
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl fmt::Debug for I64Vec2 {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt.debug_tuple(stringify!(I64Vec2))
+            .field(&self.x)
+            .field(&self.y)
+            .finish()
+    }
+}
+
+impl From<[i64; 2]> for I64Vec2 {
+    #[inline]
+    fn from(a: [i64; 2]) -> Self {
+        Self::new(a[0], a[1])
+    }
+}
+
+impl From<I64Vec2> for [i64; 2] {
+    #[inline]
+    fn from(v: I64Vec2) -> Self {
+        [v.x, v.y]
+    }
+}
+
+impl From<(i64, i64)> for I64Vec2 {
+    #[inline]
+    fn from(t: (i64, i64)) -> Self {
+        Self::new(t.0, t.1)
+    }
+}
+
+impl From<I64Vec2> for (i64, i64) {
+    #[inline]
+    fn from(v: I64Vec2) -> Self {
+        (v.x, v.y)
+    }
+}
+
+impl From<I16Vec2> for I64Vec2 {
+    #[inline]
+    fn from(v: I16Vec2) -> Self {
+        Self::new(i64::from(v.x), i64::from(v.y))
+    }
+}
+
+impl From<U16Vec2> for I64Vec2 {
+    #[inline]
+    fn from(v: U16Vec2) -> Self {
+        Self::new(i64::from(v.x), i64::from(v.y))
+    }
+}
+
+impl From<IVec2> for I64Vec2 {
+    #[inline]
+    fn from(v: IVec2) -> Self {
+        Self::new(i64::from(v.x), i64::from(v.y))
+    }
+}
+
+impl From<UVec2> for I64Vec2 {
+    #[inline]
+    fn from(v: UVec2) -> Self {
+        Self::new(i64::from(v.x), i64::from(v.y))
+    }
+}
+
+impl TryFrom<U64Vec2> for I64Vec2 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: U64Vec2) -> Result<Self, Self::Error> {
+        Ok(Self::new(i64::try_from(v.x)?, i64::try_from(v.y)?))
+    }
+}
diff --git a/src/i64/i64vec3.rs b/src/i64/i64vec3.rs
new file mode 100644
index 0000000..336e817
--- /dev/null
+++ b/src/i64/i64vec3.rs
@@ -0,0 +1,1339 @@
+// Generated from vec.rs.tera template. Edit the template, not the generated file.
+
+use crate::{BVec3, I16Vec3, I64Vec2, I64Vec4, IVec3, U16Vec3, U64Vec3, UVec3};
+
+#[cfg(not(target_arch = "spirv"))]
+use core::fmt;
+use core::iter::{Product, Sum};
+use core::{f32, ops::*};
+
+/// Creates a 3-dimensional vector.
+#[inline(always)]
+#[must_use]
+pub const fn i64vec3(x: i64, y: i64, z: i64) -> I64Vec3 {
+    I64Vec3::new(x, y, z)
+}
+
+/// A 3-dimensional vector.
+#[cfg_attr(not(target_arch = "spirv"), derive(Hash))]
+#[derive(Clone, Copy, PartialEq, Eq)]
+#[cfg_attr(not(target_arch = "spirv"), repr(C))]
+#[cfg_attr(target_arch = "spirv", repr(simd))]
+pub struct I64Vec3 {
+    pub x: i64,
+    pub y: i64,
+    pub z: i64,
+}
+
+impl I64Vec3 {
+    /// All zeroes.
+    pub const ZERO: Self = Self::splat(0);
+
+    /// All ones.
+    pub const ONE: Self = Self::splat(1);
+
+    /// All negative ones.
+    pub const NEG_ONE: Self = Self::splat(-1);
+
+    /// All `i64::MIN`.
+    pub const MIN: Self = Self::splat(i64::MIN);
+
+    /// All `i64::MAX`.
+    pub const MAX: Self = Self::splat(i64::MAX);
+
+    /// A unit vector pointing along the positive X axis.
+    pub const X: Self = Self::new(1, 0, 0);
+
+    /// A unit vector pointing along the positive Y axis.
+    pub const Y: Self = Self::new(0, 1, 0);
+
+    /// A unit vector pointing along the positive Z axis.
+    pub const Z: Self = Self::new(0, 0, 1);
+
+    /// A unit vector pointing along the negative X axis.
+    pub const NEG_X: Self = Self::new(-1, 0, 0);
+
+    /// A unit vector pointing along the negative Y axis.
+    pub const NEG_Y: Self = Self::new(0, -1, 0);
+
+    /// A unit vector pointing along the negative Z axis.
+    pub const NEG_Z: Self = Self::new(0, 0, -1);
+
+    /// The unit axes.
+    pub const AXES: [Self; 3] = [Self::X, Self::Y, Self::Z];
+
+    /// Creates a new vector.
+    #[inline(always)]
+    #[must_use]
+    pub const fn new(x: i64, y: i64, z: i64) -> Self {
+        Self { x, y, z }
+    }
+
+    /// Creates a vector with all elements set to `v`.
+    #[inline]
+    #[must_use]
+    pub const fn splat(v: i64) -> Self {
+        Self { x: v, y: v, z: v }
+    }
+
+    /// Creates a vector from the elements in `if_true` and `if_false`, selecting which to use
+    /// for each element of `self`.
+    ///
+    /// A true element in the mask uses the corresponding element from `if_true`, and false
+    /// uses the element from `if_false`.
+    #[inline]
+    #[must_use]
+    pub fn select(mask: BVec3, if_true: Self, if_false: Self) -> Self {
+        Self {
+            x: if mask.test(0) { if_true.x } else { if_false.x },
+            y: if mask.test(1) { if_true.y } else { if_false.y },
+            z: if mask.test(2) { if_true.z } else { if_false.z },
+        }
+    }
+
+    /// Creates a new vector from an array.
+    #[inline]
+    #[must_use]
+    pub const fn from_array(a: [i64; 3]) -> Self {
+        Self::new(a[0], a[1], a[2])
+    }
+
+    /// `[x, y, z]`
+    #[inline]
+    #[must_use]
+    pub const fn to_array(&self) -> [i64; 3] {
+        [self.x, self.y, self.z]
+    }
+
+    /// Creates a vector from the first 3 values in `slice`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `slice` is less than 3 elements long.
+    #[inline]
+    #[must_use]
+    pub const fn from_slice(slice: &[i64]) -> Self {
+        Self::new(slice[0], slice[1], slice[2])
+    }
+
+    /// Writes the elements of `self` to the first 3 elements in `slice`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `slice` is less than 3 elements long.
+    #[inline]
+    pub fn write_to_slice(self, slice: &mut [i64]) {
+        slice[0] = self.x;
+        slice[1] = self.y;
+        slice[2] = self.z;
+    }
+
+    /// Internal method for creating a 3D vector from a 4D vector, discarding `w`.
+    #[allow(dead_code)]
+    #[inline]
+    #[must_use]
+    pub(crate) fn from_vec4(v: I64Vec4) -> Self {
+        Self {
+            x: v.x,
+            y: v.y,
+            z: v.z,
+        }
+    }
+
+    /// Creates a 4D vector from `self` and the given `w` value.
+    #[inline]
+    #[must_use]
+    pub fn extend(self, w: i64) -> I64Vec4 {
+        I64Vec4::new(self.x, self.y, self.z, w)
+    }
+
+    /// Creates a 2D vector from the `x` and `y` elements of `self`, discarding `z`.
+    ///
+    /// Truncation may also be performed by using [`self.xy()`][crate::swizzles::Vec3Swizzles::xy()].
+    #[inline]
+    #[must_use]
+    pub fn truncate(self) -> I64Vec2 {
+        use crate::swizzles::Vec3Swizzles;
+        self.xy()
+    }
+
+    /// Computes the dot product of `self` and `rhs`.
+    #[inline]
+    #[must_use]
+    pub fn dot(self, rhs: Self) -> i64 {
+        (self.x * rhs.x) + (self.y * rhs.y) + (self.z * rhs.z)
+    }
+
+    /// Returns a vector where every component is the dot product of `self` and `rhs`.
+    #[inline]
+    #[must_use]
+    pub fn dot_into_vec(self, rhs: Self) -> Self {
+        Self::splat(self.dot(rhs))
+    }
+
+    /// Computes the cross product of `self` and `rhs`.
+    #[inline]
+    #[must_use]
+    pub fn cross(self, rhs: Self) -> Self {
+        Self {
+            x: self.y * rhs.z - rhs.y * self.z,
+            y: self.z * rhs.x - rhs.z * self.x,
+            z: self.x * rhs.y - rhs.x * self.y,
+        }
+    }
+
+    /// Returns a vector containing the minimum values for each element of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.min(rhs.x), self.y.min(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub fn min(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.min(rhs.x),
+            y: self.y.min(rhs.y),
+            z: self.z.min(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the maximum values for each element of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.max(rhs.x), self.y.max(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub fn max(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.max(rhs.x),
+            y: self.y.max(rhs.y),
+            z: self.z.max(rhs.z),
+        }
+    }
+
+    /// Component-wise clamping of values, similar to [`i64::clamp`].
+    ///
+    /// Each element in `min` must be less-or-equal to the corresponding element in `max`.
+    ///
+    /// # Panics
+    ///
+    /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
+    #[inline]
+    #[must_use]
+    pub fn clamp(self, min: Self, max: Self) -> Self {
+        glam_assert!(min.cmple(max).all(), "clamp: expected min <= max");
+        self.max(min).min(max)
+    }
+
+    /// Returns the horizontal minimum of `self`.
+    ///
+    /// In other words this computes `min(x, y, ..)`.
+    #[inline]
+    #[must_use]
+    pub fn min_element(self) -> i64 {
+        self.x.min(self.y.min(self.z))
+    }
+
+    /// Returns the horizontal maximum of `self`.
+    ///
+    /// In other words this computes `max(x, y, ..)`.
+    #[inline]
+    #[must_use]
+    pub fn max_element(self) -> i64 {
+        self.x.max(self.y.max(self.z))
+    }
+
+    /// Returns a vector mask containing the result of a `==` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words, this computes `[self.x == rhs.x, self.y == rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpeq(self, rhs: Self) -> BVec3 {
+        BVec3::new(self.x.eq(&rhs.x), self.y.eq(&rhs.y), self.z.eq(&rhs.z))
+    }
+
+    /// Returns a vector mask containing the result of a `!=` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x != rhs.x, self.y != rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpne(self, rhs: Self) -> BVec3 {
+        BVec3::new(self.x.ne(&rhs.x), self.y.ne(&rhs.y), self.z.ne(&rhs.z))
+    }
+
+    /// Returns a vector mask containing the result of a `>=` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x >= rhs.x, self.y >= rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpge(self, rhs: Self) -> BVec3 {
+        BVec3::new(self.x.ge(&rhs.x), self.y.ge(&rhs.y), self.z.ge(&rhs.z))
+    }
+
+    /// Returns a vector mask containing the result of a `>` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x > rhs.x, self.y > rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpgt(self, rhs: Self) -> BVec3 {
+        BVec3::new(self.x.gt(&rhs.x), self.y.gt(&rhs.y), self.z.gt(&rhs.z))
+    }
+
+    /// Returns a vector mask containing the result of a `<=` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x <= rhs.x, self.y <= rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmple(self, rhs: Self) -> BVec3 {
+        BVec3::new(self.x.le(&rhs.x), self.y.le(&rhs.y), self.z.le(&rhs.z))
+    }
+
+    /// Returns a vector mask containing the result of a `<` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x < rhs.x, self.y < rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmplt(self, rhs: Self) -> BVec3 {
+        BVec3::new(self.x.lt(&rhs.x), self.y.lt(&rhs.y), self.z.lt(&rhs.z))
+    }
+
+    /// Returns a vector containing the absolute value of each element of `self`.
+    #[inline]
+    #[must_use]
+    pub fn abs(self) -> Self {
+        Self {
+            x: self.x.abs(),
+            y: self.y.abs(),
+            z: self.z.abs(),
+        }
+    }
+
+    /// Returns a vector with elements representing the sign of `self`.
+    ///
+    ///  - `0` if the number is zero
+    ///  - `1` if the number is positive
+    ///  - `-1` if the number is negative
+    #[inline]
+    #[must_use]
+    pub fn signum(self) -> Self {
+        Self {
+            x: self.x.signum(),
+            y: self.y.signum(),
+            z: self.z.signum(),
+        }
+    }
+
+    /// Returns a bitmask with the lowest 3 bits set to the sign bits from the elements of `self`.
+    ///
+    /// A negative element results in a `1` bit and a positive element in a `0` bit.  Element `x` goes
+    /// into the first lowest bit, element `y` into the second, etc.
+    #[inline]
+    #[must_use]
+    pub fn is_negative_bitmask(self) -> u32 {
+        (self.x.is_negative() as u32)
+            | (self.y.is_negative() as u32) << 1
+            | (self.z.is_negative() as u32) << 2
+    }
+
+    /// Computes the squared length of `self`.
+    #[doc(alias = "magnitude2")]
+    #[inline]
+    #[must_use]
+    pub fn length_squared(self) -> i64 {
+        self.dot(self)
+    }
+
+    /// Compute the squared euclidean distance between two points in space.
+    #[inline]
+    #[must_use]
+    pub fn distance_squared(self, rhs: Self) -> i64 {
+        (self - rhs).length_squared()
+    }
+
+    /// Returns the element-wise quotient of [Euclidean division] of `self` by `rhs`.
+    ///
+    /// # Panics
+    /// This function will panic if any `rhs` element is 0 or the division results in overflow.
+    #[inline]
+    #[must_use]
+    pub fn div_euclid(self, rhs: Self) -> Self {
+        Self::new(
+            self.x.div_euclid(rhs.x),
+            self.y.div_euclid(rhs.y),
+            self.z.div_euclid(rhs.z),
+        )
+    }
+
+    /// Returns the element-wise remainder of [Euclidean division] of `self` by `rhs`.
+    ///
+    /// # Panics
+    /// This function will panic if any `rhs` element is 0 or the division results in overflow.
+    ///
+    /// [Euclidean division]: i64::rem_euclid
+    #[inline]
+    #[must_use]
+    pub fn rem_euclid(self, rhs: Self) -> Self {
+        Self::new(
+            self.x.rem_euclid(rhs.x),
+            self.y.rem_euclid(rhs.y),
+            self.z.rem_euclid(rhs.z),
+        )
+    }
+
+    /// Casts all elements of `self` to `f32`.
+    #[inline]
+    #[must_use]
+    pub fn as_vec3(&self) -> crate::Vec3 {
+        crate::Vec3::new(self.x as f32, self.y as f32, self.z as f32)
+    }
+
+    /// Casts all elements of `self` to `f32`.
+    #[inline]
+    #[must_use]
+    pub fn as_vec3a(&self) -> crate::Vec3A {
+        crate::Vec3A::new(self.x as f32, self.y as f32, self.z as f32)
+    }
+
+    /// Casts all elements of `self` to `f64`.
+    #[inline]
+    #[must_use]
+    pub fn as_dvec3(&self) -> crate::DVec3 {
+        crate::DVec3::new(self.x as f64, self.y as f64, self.z as f64)
+    }
+
+    /// Casts all elements of `self` to `i16`.
+    #[inline]
+    #[must_use]
+    pub fn as_i16vec3(&self) -> crate::I16Vec3 {
+        crate::I16Vec3::new(self.x as i16, self.y as i16, self.z as i16)
+    }
+
+    /// Casts all elements of `self` to `u16`.
+    #[inline]
+    #[must_use]
+    pub fn as_u16vec3(&self) -> crate::U16Vec3 {
+        crate::U16Vec3::new(self.x as u16, self.y as u16, self.z as u16)
+    }
+
+    /// Casts all elements of `self` to `i32`.
+    #[inline]
+    #[must_use]
+    pub fn as_ivec3(&self) -> crate::IVec3 {
+        crate::IVec3::new(self.x as i32, self.y as i32, self.z as i32)
+    }
+
+    /// Casts all elements of `self` to `u32`.
+    #[inline]
+    #[must_use]
+    pub fn as_uvec3(&self) -> crate::UVec3 {
+        crate::UVec3::new(self.x as u32, self.y as u32, self.z as u32)
+    }
+
+    /// Casts all elements of `self` to `u64`.
+    #[inline]
+    #[must_use]
+    pub fn as_u64vec3(&self) -> crate::U64Vec3 {
+        crate::U64Vec3::new(self.x as u64, self.y as u64, self.z as u64)
+    }
+
+    /// Returns a vector containing the wrapping addition of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_add(rhs.x), self.y.wrapping_add(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_add(rhs.x),
+            y: self.y.wrapping_add(rhs.y),
+            z: self.z.wrapping_add(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the wrapping subtraction of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_sub(rhs.x), self.y.wrapping_sub(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_sub(rhs.x),
+            y: self.y.wrapping_sub(rhs.y),
+            z: self.z.wrapping_sub(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the wrapping multiplication of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_mul(rhs.x), self.y.wrapping_mul(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_mul(rhs.x),
+            y: self.y.wrapping_mul(rhs.y),
+            z: self.z.wrapping_mul(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the wrapping division of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_div(rhs.x), self.y.wrapping_div(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_div(rhs.x),
+            y: self.y.wrapping_div(rhs.y),
+            z: self.z.wrapping_div(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the saturating addition of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_add(rhs.x), self.y.saturating_add(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_add(rhs.x),
+            y: self.y.saturating_add(rhs.y),
+            z: self.z.saturating_add(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the saturating subtraction of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_sub(rhs.x), self.y.saturating_sub(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_sub(rhs.x),
+            y: self.y.saturating_sub(rhs.y),
+            z: self.z.saturating_sub(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the saturating multiplication of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_mul(rhs.x), self.y.saturating_mul(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_mul(rhs.x),
+            y: self.y.saturating_mul(rhs.y),
+            z: self.z.saturating_mul(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the saturating division of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_div(rhs.x), self.y.saturating_div(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_div(rhs.x),
+            y: self.y.saturating_div(rhs.y),
+            z: self.z.saturating_div(rhs.z),
+        }
+    }
+}
+
+impl Default for I64Vec3 {
+    #[inline(always)]
+    fn default() -> Self {
+        Self::ZERO
+    }
+}
+
+impl Div<I64Vec3> for I64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.div(rhs.x),
+            y: self.y.div(rhs.y),
+            z: self.z.div(rhs.z),
+        }
+    }
+}
+
+impl DivAssign<I64Vec3> for I64Vec3 {
+    #[inline]
+    fn div_assign(&mut self, rhs: Self) {
+        self.x.div_assign(rhs.x);
+        self.y.div_assign(rhs.y);
+        self.z.div_assign(rhs.z);
+    }
+}
+
+impl Div<i64> for I64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn div(self, rhs: i64) -> Self {
+        Self {
+            x: self.x.div(rhs),
+            y: self.y.div(rhs),
+            z: self.z.div(rhs),
+        }
+    }
+}
+
+impl DivAssign<i64> for I64Vec3 {
+    #[inline]
+    fn div_assign(&mut self, rhs: i64) {
+        self.x.div_assign(rhs);
+        self.y.div_assign(rhs);
+        self.z.div_assign(rhs);
+    }
+}
+
+impl Div<I64Vec3> for i64 {
+    type Output = I64Vec3;
+    #[inline]
+    fn div(self, rhs: I64Vec3) -> I64Vec3 {
+        I64Vec3 {
+            x: self.div(rhs.x),
+            y: self.div(rhs.y),
+            z: self.div(rhs.z),
+        }
+    }
+}
+
+impl Mul<I64Vec3> for I64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.mul(rhs.x),
+            y: self.y.mul(rhs.y),
+            z: self.z.mul(rhs.z),
+        }
+    }
+}
+
+impl MulAssign<I64Vec3> for I64Vec3 {
+    #[inline]
+    fn mul_assign(&mut self, rhs: Self) {
+        self.x.mul_assign(rhs.x);
+        self.y.mul_assign(rhs.y);
+        self.z.mul_assign(rhs.z);
+    }
+}
+
+impl Mul<i64> for I64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn mul(self, rhs: i64) -> Self {
+        Self {
+            x: self.x.mul(rhs),
+            y: self.y.mul(rhs),
+            z: self.z.mul(rhs),
+        }
+    }
+}
+
+impl MulAssign<i64> for I64Vec3 {
+    #[inline]
+    fn mul_assign(&mut self, rhs: i64) {
+        self.x.mul_assign(rhs);
+        self.y.mul_assign(rhs);
+        self.z.mul_assign(rhs);
+    }
+}
+
+impl Mul<I64Vec3> for i64 {
+    type Output = I64Vec3;
+    #[inline]
+    fn mul(self, rhs: I64Vec3) -> I64Vec3 {
+        I64Vec3 {
+            x: self.mul(rhs.x),
+            y: self.mul(rhs.y),
+            z: self.mul(rhs.z),
+        }
+    }
+}
+
+impl Add<I64Vec3> for I64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.add(rhs.x),
+            y: self.y.add(rhs.y),
+            z: self.z.add(rhs.z),
+        }
+    }
+}
+
+impl AddAssign<I64Vec3> for I64Vec3 {
+    #[inline]
+    fn add_assign(&mut self, rhs: Self) {
+        self.x.add_assign(rhs.x);
+        self.y.add_assign(rhs.y);
+        self.z.add_assign(rhs.z);
+    }
+}
+
+impl Add<i64> for I64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn add(self, rhs: i64) -> Self {
+        Self {
+            x: self.x.add(rhs),
+            y: self.y.add(rhs),
+            z: self.z.add(rhs),
+        }
+    }
+}
+
+impl AddAssign<i64> for I64Vec3 {
+    #[inline]
+    fn add_assign(&mut self, rhs: i64) {
+        self.x.add_assign(rhs);
+        self.y.add_assign(rhs);
+        self.z.add_assign(rhs);
+    }
+}
+
+impl Add<I64Vec3> for i64 {
+    type Output = I64Vec3;
+    #[inline]
+    fn add(self, rhs: I64Vec3) -> I64Vec3 {
+        I64Vec3 {
+            x: self.add(rhs.x),
+            y: self.add(rhs.y),
+            z: self.add(rhs.z),
+        }
+    }
+}
+
+impl Sub<I64Vec3> for I64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.sub(rhs.x),
+            y: self.y.sub(rhs.y),
+            z: self.z.sub(rhs.z),
+        }
+    }
+}
+
+impl SubAssign<I64Vec3> for I64Vec3 {
+    #[inline]
+    fn sub_assign(&mut self, rhs: I64Vec3) {
+        self.x.sub_assign(rhs.x);
+        self.y.sub_assign(rhs.y);
+        self.z.sub_assign(rhs.z);
+    }
+}
+
+impl Sub<i64> for I64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn sub(self, rhs: i64) -> Self {
+        Self {
+            x: self.x.sub(rhs),
+            y: self.y.sub(rhs),
+            z: self.z.sub(rhs),
+        }
+    }
+}
+
+impl SubAssign<i64> for I64Vec3 {
+    #[inline]
+    fn sub_assign(&mut self, rhs: i64) {
+        self.x.sub_assign(rhs);
+        self.y.sub_assign(rhs);
+        self.z.sub_assign(rhs);
+    }
+}
+
+impl Sub<I64Vec3> for i64 {
+    type Output = I64Vec3;
+    #[inline]
+    fn sub(self, rhs: I64Vec3) -> I64Vec3 {
+        I64Vec3 {
+            x: self.sub(rhs.x),
+            y: self.sub(rhs.y),
+            z: self.sub(rhs.z),
+        }
+    }
+}
+
+impl Rem<I64Vec3> for I64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn rem(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.rem(rhs.x),
+            y: self.y.rem(rhs.y),
+            z: self.z.rem(rhs.z),
+        }
+    }
+}
+
+impl RemAssign<I64Vec3> for I64Vec3 {
+    #[inline]
+    fn rem_assign(&mut self, rhs: Self) {
+        self.x.rem_assign(rhs.x);
+        self.y.rem_assign(rhs.y);
+        self.z.rem_assign(rhs.z);
+    }
+}
+
+impl Rem<i64> for I64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn rem(self, rhs: i64) -> Self {
+        Self {
+            x: self.x.rem(rhs),
+            y: self.y.rem(rhs),
+            z: self.z.rem(rhs),
+        }
+    }
+}
+
+impl RemAssign<i64> for I64Vec3 {
+    #[inline]
+    fn rem_assign(&mut self, rhs: i64) {
+        self.x.rem_assign(rhs);
+        self.y.rem_assign(rhs);
+        self.z.rem_assign(rhs);
+    }
+}
+
+impl Rem<I64Vec3> for i64 {
+    type Output = I64Vec3;
+    #[inline]
+    fn rem(self, rhs: I64Vec3) -> I64Vec3 {
+        I64Vec3 {
+            x: self.rem(rhs.x),
+            y: self.rem(rhs.y),
+            z: self.rem(rhs.z),
+        }
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl AsRef<[i64; 3]> for I64Vec3 {
+    #[inline]
+    fn as_ref(&self) -> &[i64; 3] {
+        unsafe { &*(self as *const I64Vec3 as *const [i64; 3]) }
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl AsMut<[i64; 3]> for I64Vec3 {
+    #[inline]
+    fn as_mut(&mut self) -> &mut [i64; 3] {
+        unsafe { &mut *(self as *mut I64Vec3 as *mut [i64; 3]) }
+    }
+}
+
+impl Sum for I64Vec3 {
+    #[inline]
+    fn sum<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = Self>,
+    {
+        iter.fold(Self::ZERO, Self::add)
+    }
+}
+
+impl<'a> Sum<&'a Self> for I64Vec3 {
+    #[inline]
+    fn sum<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = &'a Self>,
+    {
+        iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
+    }
+}
+
+impl Product for I64Vec3 {
+    #[inline]
+    fn product<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = Self>,
+    {
+        iter.fold(Self::ONE, Self::mul)
+    }
+}
+
+impl<'a> Product<&'a Self> for I64Vec3 {
+    #[inline]
+    fn product<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = &'a Self>,
+    {
+        iter.fold(Self::ONE, |a, &b| Self::mul(a, b))
+    }
+}
+
+impl Neg for I64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn neg(self) -> Self {
+        Self {
+            x: self.x.neg(),
+            y: self.y.neg(),
+            z: self.z.neg(),
+        }
+    }
+}
+
+impl Not for I64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn not(self) -> Self::Output {
+        Self {
+            x: self.x.not(),
+            y: self.y.not(),
+            z: self.z.not(),
+        }
+    }
+}
+
+impl BitAnd for I64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn bitand(self, rhs: Self) -> Self::Output {
+        Self {
+            x: self.x.bitand(rhs.x),
+            y: self.y.bitand(rhs.y),
+            z: self.z.bitand(rhs.z),
+        }
+    }
+}
+
+impl BitOr for I64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn bitor(self, rhs: Self) -> Self::Output {
+        Self {
+            x: self.x.bitor(rhs.x),
+            y: self.y.bitor(rhs.y),
+            z: self.z.bitor(rhs.z),
+        }
+    }
+}
+
+impl BitXor for I64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn bitxor(self, rhs: Self) -> Self::Output {
+        Self {
+            x: self.x.bitxor(rhs.x),
+            y: self.y.bitxor(rhs.y),
+            z: self.z.bitxor(rhs.z),
+        }
+    }
+}
+
+impl BitAnd<i64> for I64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn bitand(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.bitand(rhs),
+            y: self.y.bitand(rhs),
+            z: self.z.bitand(rhs),
+        }
+    }
+}
+
+impl BitOr<i64> for I64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn bitor(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.bitor(rhs),
+            y: self.y.bitor(rhs),
+            z: self.z.bitor(rhs),
+        }
+    }
+}
+
+impl BitXor<i64> for I64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn bitxor(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.bitxor(rhs),
+            y: self.y.bitxor(rhs),
+            z: self.z.bitxor(rhs),
+        }
+    }
+}
+
+impl Shl<i8> for I64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i8) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i8> for I64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i8) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+        }
+    }
+}
+
+impl Shl<i16> for I64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i16) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i16> for I64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i16) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+        }
+    }
+}
+
+impl Shl<i32> for I64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i32) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i32> for I64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i32) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+        }
+    }
+}
+
+impl Shl<i64> for I64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i64> for I64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u8> for I64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u8) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u8> for I64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u8) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u16> for I64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u16) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u16> for I64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u16) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u32> for I64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u32) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u32> for I64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u32) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u64> for I64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u64> for I64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+        }
+    }
+}
+
+impl Shl<crate::IVec3> for I64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: crate::IVec3) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs.x),
+            y: self.y.shl(rhs.y),
+            z: self.z.shl(rhs.z),
+        }
+    }
+}
+
+impl Shr<crate::IVec3> for I64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: crate::IVec3) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs.x),
+            y: self.y.shr(rhs.y),
+            z: self.z.shr(rhs.z),
+        }
+    }
+}
+
+impl Shl<crate::UVec3> for I64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: crate::UVec3) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs.x),
+            y: self.y.shl(rhs.y),
+            z: self.z.shl(rhs.z),
+        }
+    }
+}
+
+impl Shr<crate::UVec3> for I64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: crate::UVec3) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs.x),
+            y: self.y.shr(rhs.y),
+            z: self.z.shr(rhs.z),
+        }
+    }
+}
+
+impl Index<usize> for I64Vec3 {
+    type Output = i64;
+    #[inline]
+    fn index(&self, index: usize) -> &Self::Output {
+        match index {
+            0 => &self.x,
+            1 => &self.y,
+            2 => &self.z,
+            _ => panic!("index out of bounds"),
+        }
+    }
+}
+
+impl IndexMut<usize> for I64Vec3 {
+    #[inline]
+    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
+        match index {
+            0 => &mut self.x,
+            1 => &mut self.y,
+            2 => &mut self.z,
+            _ => panic!("index out of bounds"),
+        }
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl fmt::Display for I64Vec3 {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "[{}, {}, {}]", self.x, self.y, self.z)
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl fmt::Debug for I64Vec3 {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt.debug_tuple(stringify!(I64Vec3))
+            .field(&self.x)
+            .field(&self.y)
+            .field(&self.z)
+            .finish()
+    }
+}
+
+impl From<[i64; 3]> for I64Vec3 {
+    #[inline]
+    fn from(a: [i64; 3]) -> Self {
+        Self::new(a[0], a[1], a[2])
+    }
+}
+
+impl From<I64Vec3> for [i64; 3] {
+    #[inline]
+    fn from(v: I64Vec3) -> Self {
+        [v.x, v.y, v.z]
+    }
+}
+
+impl From<(i64, i64, i64)> for I64Vec3 {
+    #[inline]
+    fn from(t: (i64, i64, i64)) -> Self {
+        Self::new(t.0, t.1, t.2)
+    }
+}
+
+impl From<I64Vec3> for (i64, i64, i64) {
+    #[inline]
+    fn from(v: I64Vec3) -> Self {
+        (v.x, v.y, v.z)
+    }
+}
+
+impl From<(I64Vec2, i64)> for I64Vec3 {
+    #[inline]
+    fn from((v, z): (I64Vec2, i64)) -> Self {
+        Self::new(v.x, v.y, z)
+    }
+}
+
+impl From<I16Vec3> for I64Vec3 {
+    #[inline]
+    fn from(v: I16Vec3) -> Self {
+        Self::new(i64::from(v.x), i64::from(v.y), i64::from(v.z))
+    }
+}
+
+impl From<U16Vec3> for I64Vec3 {
+    #[inline]
+    fn from(v: U16Vec3) -> Self {
+        Self::new(i64::from(v.x), i64::from(v.y), i64::from(v.z))
+    }
+}
+
+impl From<IVec3> for I64Vec3 {
+    #[inline]
+    fn from(v: IVec3) -> Self {
+        Self::new(i64::from(v.x), i64::from(v.y), i64::from(v.z))
+    }
+}
+
+impl From<UVec3> for I64Vec3 {
+    #[inline]
+    fn from(v: UVec3) -> Self {
+        Self::new(i64::from(v.x), i64::from(v.y), i64::from(v.z))
+    }
+}
+
+impl TryFrom<U64Vec3> for I64Vec3 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: U64Vec3) -> Result<Self, Self::Error> {
+        Ok(Self::new(
+            i64::try_from(v.x)?,
+            i64::try_from(v.y)?,
+            i64::try_from(v.z)?,
+        ))
+    }
+}
diff --git a/src/i64/i64vec4.rs b/src/i64/i64vec4.rs
new file mode 100644
index 0000000..bd4c0c1
--- /dev/null
+++ b/src/i64/i64vec4.rs
@@ -0,0 +1,1463 @@
+// Generated from vec.rs.tera template. Edit the template, not the generated file.
+
+use crate::{BVec4, I16Vec4, I64Vec2, I64Vec3, IVec4, U16Vec4, U64Vec4, UVec4};
+
+#[cfg(not(target_arch = "spirv"))]
+use core::fmt;
+use core::iter::{Product, Sum};
+use core::{f32, ops::*};
+
+/// Creates a 4-dimensional vector.
+#[inline(always)]
+#[must_use]
+pub const fn i64vec4(x: i64, y: i64, z: i64, w: i64) -> I64Vec4 {
+    I64Vec4::new(x, y, z, w)
+}
+
+/// A 4-dimensional vector.
+#[cfg_attr(not(target_arch = "spirv"), derive(Hash))]
+#[derive(Clone, Copy, PartialEq, Eq)]
+#[cfg_attr(feature = "cuda", repr(align(16)))]
+#[cfg_attr(not(target_arch = "spirv"), repr(C))]
+#[cfg_attr(target_arch = "spirv", repr(simd))]
+pub struct I64Vec4 {
+    pub x: i64,
+    pub y: i64,
+    pub z: i64,
+    pub w: i64,
+}
+
+impl I64Vec4 {
+    /// All zeroes.
+    pub const ZERO: Self = Self::splat(0);
+
+    /// All ones.
+    pub const ONE: Self = Self::splat(1);
+
+    /// All negative ones.
+    pub const NEG_ONE: Self = Self::splat(-1);
+
+    /// All `i64::MIN`.
+    pub const MIN: Self = Self::splat(i64::MIN);
+
+    /// All `i64::MAX`.
+    pub const MAX: Self = Self::splat(i64::MAX);
+
+    /// A unit vector pointing along the positive X axis.
+    pub const X: Self = Self::new(1, 0, 0, 0);
+
+    /// A unit vector pointing along the positive Y axis.
+    pub const Y: Self = Self::new(0, 1, 0, 0);
+
+    /// A unit vector pointing along the positive Z axis.
+    pub const Z: Self = Self::new(0, 0, 1, 0);
+
+    /// A unit vector pointing along the positive W axis.
+    pub const W: Self = Self::new(0, 0, 0, 1);
+
+    /// A unit vector pointing along the negative X axis.
+    pub const NEG_X: Self = Self::new(-1, 0, 0, 0);
+
+    /// A unit vector pointing along the negative Y axis.
+    pub const NEG_Y: Self = Self::new(0, -1, 0, 0);
+
+    /// A unit vector pointing along the negative Z axis.
+    pub const NEG_Z: Self = Self::new(0, 0, -1, 0);
+
+    /// A unit vector pointing along the negative W axis.
+    pub const NEG_W: Self = Self::new(0, 0, 0, -1);
+
+    /// The unit axes.
+    pub const AXES: [Self; 4] = [Self::X, Self::Y, Self::Z, Self::W];
+
+    /// Creates a new vector.
+    #[inline(always)]
+    #[must_use]
+    pub const fn new(x: i64, y: i64, z: i64, w: i64) -> Self {
+        Self { x, y, z, w }
+    }
+
+    /// Creates a vector with all elements set to `v`.
+    #[inline]
+    #[must_use]
+    pub const fn splat(v: i64) -> Self {
+        Self {
+            x: v,
+
+            y: v,
+
+            z: v,
+
+            w: v,
+        }
+    }
+
+    /// Creates a vector from the elements in `if_true` and `if_false`, selecting which to use
+    /// for each element of `self`.
+    ///
+    /// A true element in the mask uses the corresponding element from `if_true`, and false
+    /// uses the element from `if_false`.
+    #[inline]
+    #[must_use]
+    pub fn select(mask: BVec4, if_true: Self, if_false: Self) -> Self {
+        Self {
+            x: if mask.test(0) { if_true.x } else { if_false.x },
+            y: if mask.test(1) { if_true.y } else { if_false.y },
+            z: if mask.test(2) { if_true.z } else { if_false.z },
+            w: if mask.test(3) { if_true.w } else { if_false.w },
+        }
+    }
+
+    /// Creates a new vector from an array.
+    #[inline]
+    #[must_use]
+    pub const fn from_array(a: [i64; 4]) -> Self {
+        Self::new(a[0], a[1], a[2], a[3])
+    }
+
+    /// `[x, y, z, w]`
+    #[inline]
+    #[must_use]
+    pub const fn to_array(&self) -> [i64; 4] {
+        [self.x, self.y, self.z, self.w]
+    }
+
+    /// Creates a vector from the first 4 values in `slice`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `slice` is less than 4 elements long.
+    #[inline]
+    #[must_use]
+    pub const fn from_slice(slice: &[i64]) -> Self {
+        Self::new(slice[0], slice[1], slice[2], slice[3])
+    }
+
+    /// Writes the elements of `self` to the first 4 elements in `slice`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `slice` is less than 4 elements long.
+    #[inline]
+    pub fn write_to_slice(self, slice: &mut [i64]) {
+        slice[0] = self.x;
+        slice[1] = self.y;
+        slice[2] = self.z;
+        slice[3] = self.w;
+    }
+
+    /// Creates a 3D vector from the `x`, `y` and `z` elements of `self`, discarding `w`.
+    ///
+    /// Truncation to [`I64Vec3`] may also be performed by using [`self.xyz()`][crate::swizzles::Vec4Swizzles::xyz()].
+    #[inline]
+    #[must_use]
+    pub fn truncate(self) -> I64Vec3 {
+        use crate::swizzles::Vec4Swizzles;
+        self.xyz()
+    }
+
+    /// Computes the dot product of `self` and `rhs`.
+    #[inline]
+    #[must_use]
+    pub fn dot(self, rhs: Self) -> i64 {
+        (self.x * rhs.x) + (self.y * rhs.y) + (self.z * rhs.z) + (self.w * rhs.w)
+    }
+
+    /// Returns a vector where every component is the dot product of `self` and `rhs`.
+    #[inline]
+    #[must_use]
+    pub fn dot_into_vec(self, rhs: Self) -> Self {
+        Self::splat(self.dot(rhs))
+    }
+
+    /// Returns a vector containing the minimum values for each element of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.min(rhs.x), self.y.min(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub fn min(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.min(rhs.x),
+            y: self.y.min(rhs.y),
+            z: self.z.min(rhs.z),
+            w: self.w.min(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the maximum values for each element of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.max(rhs.x), self.y.max(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub fn max(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.max(rhs.x),
+            y: self.y.max(rhs.y),
+            z: self.z.max(rhs.z),
+            w: self.w.max(rhs.w),
+        }
+    }
+
+    /// Component-wise clamping of values, similar to [`i64::clamp`].
+    ///
+    /// Each element in `min` must be less-or-equal to the corresponding element in `max`.
+    ///
+    /// # Panics
+    ///
+    /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
+    #[inline]
+    #[must_use]
+    pub fn clamp(self, min: Self, max: Self) -> Self {
+        glam_assert!(min.cmple(max).all(), "clamp: expected min <= max");
+        self.max(min).min(max)
+    }
+
+    /// Returns the horizontal minimum of `self`.
+    ///
+    /// In other words this computes `min(x, y, ..)`.
+    #[inline]
+    #[must_use]
+    pub fn min_element(self) -> i64 {
+        self.x.min(self.y.min(self.z.min(self.w)))
+    }
+
+    /// Returns the horizontal maximum of `self`.
+    ///
+    /// In other words this computes `max(x, y, ..)`.
+    #[inline]
+    #[must_use]
+    pub fn max_element(self) -> i64 {
+        self.x.max(self.y.max(self.z.max(self.w)))
+    }
+
+    /// Returns a vector mask containing the result of a `==` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words, this computes `[self.x == rhs.x, self.y == rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpeq(self, rhs: Self) -> BVec4 {
+        BVec4::new(
+            self.x.eq(&rhs.x),
+            self.y.eq(&rhs.y),
+            self.z.eq(&rhs.z),
+            self.w.eq(&rhs.w),
+        )
+    }
+
+    /// Returns a vector mask containing the result of a `!=` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x != rhs.x, self.y != rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpne(self, rhs: Self) -> BVec4 {
+        BVec4::new(
+            self.x.ne(&rhs.x),
+            self.y.ne(&rhs.y),
+            self.z.ne(&rhs.z),
+            self.w.ne(&rhs.w),
+        )
+    }
+
+    /// Returns a vector mask containing the result of a `>=` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x >= rhs.x, self.y >= rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpge(self, rhs: Self) -> BVec4 {
+        BVec4::new(
+            self.x.ge(&rhs.x),
+            self.y.ge(&rhs.y),
+            self.z.ge(&rhs.z),
+            self.w.ge(&rhs.w),
+        )
+    }
+
+    /// Returns a vector mask containing the result of a `>` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x > rhs.x, self.y > rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpgt(self, rhs: Self) -> BVec4 {
+        BVec4::new(
+            self.x.gt(&rhs.x),
+            self.y.gt(&rhs.y),
+            self.z.gt(&rhs.z),
+            self.w.gt(&rhs.w),
+        )
+    }
+
+    /// Returns a vector mask containing the result of a `<=` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x <= rhs.x, self.y <= rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmple(self, rhs: Self) -> BVec4 {
+        BVec4::new(
+            self.x.le(&rhs.x),
+            self.y.le(&rhs.y),
+            self.z.le(&rhs.z),
+            self.w.le(&rhs.w),
+        )
+    }
+
+    /// Returns a vector mask containing the result of a `<` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x < rhs.x, self.y < rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmplt(self, rhs: Self) -> BVec4 {
+        BVec4::new(
+            self.x.lt(&rhs.x),
+            self.y.lt(&rhs.y),
+            self.z.lt(&rhs.z),
+            self.w.lt(&rhs.w),
+        )
+    }
+
+    /// Returns a vector containing the absolute value of each element of `self`.
+    #[inline]
+    #[must_use]
+    pub fn abs(self) -> Self {
+        Self {
+            x: self.x.abs(),
+            y: self.y.abs(),
+            z: self.z.abs(),
+            w: self.w.abs(),
+        }
+    }
+
+    /// Returns a vector with elements representing the sign of `self`.
+    ///
+    ///  - `0` if the number is zero
+    ///  - `1` if the number is positive
+    ///  - `-1` if the number is negative
+    #[inline]
+    #[must_use]
+    pub fn signum(self) -> Self {
+        Self {
+            x: self.x.signum(),
+            y: self.y.signum(),
+            z: self.z.signum(),
+            w: self.w.signum(),
+        }
+    }
+
+    /// Returns a bitmask with the lowest 4 bits set to the sign bits from the elements of `self`.
+    ///
+    /// A negative element results in a `1` bit and a positive element in a `0` bit.  Element `x` goes
+    /// into the first lowest bit, element `y` into the second, etc.
+    #[inline]
+    #[must_use]
+    pub fn is_negative_bitmask(self) -> u32 {
+        (self.x.is_negative() as u32)
+            | (self.y.is_negative() as u32) << 1
+            | (self.z.is_negative() as u32) << 2
+            | (self.w.is_negative() as u32) << 3
+    }
+
+    /// Computes the squared length of `self`.
+    #[doc(alias = "magnitude2")]
+    #[inline]
+    #[must_use]
+    pub fn length_squared(self) -> i64 {
+        self.dot(self)
+    }
+
+    /// Compute the squared euclidean distance between two points in space.
+    #[inline]
+    #[must_use]
+    pub fn distance_squared(self, rhs: Self) -> i64 {
+        (self - rhs).length_squared()
+    }
+
+    /// Returns the element-wise quotient of [Euclidean division] of `self` by `rhs`.
+    ///
+    /// # Panics
+    /// This function will panic if any `rhs` element is 0 or the division results in overflow.
+    #[inline]
+    #[must_use]
+    pub fn div_euclid(self, rhs: Self) -> Self {
+        Self::new(
+            self.x.div_euclid(rhs.x),
+            self.y.div_euclid(rhs.y),
+            self.z.div_euclid(rhs.z),
+            self.w.div_euclid(rhs.w),
+        )
+    }
+
+    /// Returns the element-wise remainder of [Euclidean division] of `self` by `rhs`.
+    ///
+    /// # Panics
+    /// This function will panic if any `rhs` element is 0 or the division results in overflow.
+    ///
+    /// [Euclidean division]: i64::rem_euclid
+    #[inline]
+    #[must_use]
+    pub fn rem_euclid(self, rhs: Self) -> Self {
+        Self::new(
+            self.x.rem_euclid(rhs.x),
+            self.y.rem_euclid(rhs.y),
+            self.z.rem_euclid(rhs.z),
+            self.w.rem_euclid(rhs.w),
+        )
+    }
+
+    /// Casts all elements of `self` to `f32`.
+    #[inline]
+    #[must_use]
+    pub fn as_vec4(&self) -> crate::Vec4 {
+        crate::Vec4::new(self.x as f32, self.y as f32, self.z as f32, self.w as f32)
+    }
+
+    /// Casts all elements of `self` to `f64`.
+    #[inline]
+    #[must_use]
+    pub fn as_dvec4(&self) -> crate::DVec4 {
+        crate::DVec4::new(self.x as f64, self.y as f64, self.z as f64, self.w as f64)
+    }
+
+    /// Casts all elements of `self` to `i16`.
+    #[inline]
+    #[must_use]
+    pub fn as_i16vec4(&self) -> crate::I16Vec4 {
+        crate::I16Vec4::new(self.x as i16, self.y as i16, self.z as i16, self.w as i16)
+    }
+
+    /// Casts all elements of `self` to `u16`.
+    #[inline]
+    #[must_use]
+    pub fn as_u16vec4(&self) -> crate::U16Vec4 {
+        crate::U16Vec4::new(self.x as u16, self.y as u16, self.z as u16, self.w as u16)
+    }
+
+    /// Casts all elements of `self` to `i32`.
+    #[inline]
+    #[must_use]
+    pub fn as_ivec4(&self) -> crate::IVec4 {
+        crate::IVec4::new(self.x as i32, self.y as i32, self.z as i32, self.w as i32)
+    }
+
+    /// Casts all elements of `self` to `u32`.
+    #[inline]
+    #[must_use]
+    pub fn as_uvec4(&self) -> crate::UVec4 {
+        crate::UVec4::new(self.x as u32, self.y as u32, self.z as u32, self.w as u32)
+    }
+
+    /// Casts all elements of `self` to `u64`.
+    #[inline]
+    #[must_use]
+    pub fn as_u64vec4(&self) -> crate::U64Vec4 {
+        crate::U64Vec4::new(self.x as u64, self.y as u64, self.z as u64, self.w as u64)
+    }
+
+    /// Returns a vector containing the wrapping addition of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_add(rhs.x), self.y.wrapping_add(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_add(rhs.x),
+            y: self.y.wrapping_add(rhs.y),
+            z: self.z.wrapping_add(rhs.z),
+            w: self.w.wrapping_add(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the wrapping subtraction of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_sub(rhs.x), self.y.wrapping_sub(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_sub(rhs.x),
+            y: self.y.wrapping_sub(rhs.y),
+            z: self.z.wrapping_sub(rhs.z),
+            w: self.w.wrapping_sub(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the wrapping multiplication of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_mul(rhs.x), self.y.wrapping_mul(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_mul(rhs.x),
+            y: self.y.wrapping_mul(rhs.y),
+            z: self.z.wrapping_mul(rhs.z),
+            w: self.w.wrapping_mul(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the wrapping division of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_div(rhs.x), self.y.wrapping_div(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_div(rhs.x),
+            y: self.y.wrapping_div(rhs.y),
+            z: self.z.wrapping_div(rhs.z),
+            w: self.w.wrapping_div(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the saturating addition of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_add(rhs.x), self.y.saturating_add(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_add(rhs.x),
+            y: self.y.saturating_add(rhs.y),
+            z: self.z.saturating_add(rhs.z),
+            w: self.w.saturating_add(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the saturating subtraction of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_sub(rhs.x), self.y.saturating_sub(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_sub(rhs.x),
+            y: self.y.saturating_sub(rhs.y),
+            z: self.z.saturating_sub(rhs.z),
+            w: self.w.saturating_sub(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the saturating multiplication of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_mul(rhs.x), self.y.saturating_mul(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_mul(rhs.x),
+            y: self.y.saturating_mul(rhs.y),
+            z: self.z.saturating_mul(rhs.z),
+            w: self.w.saturating_mul(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the saturating division of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_div(rhs.x), self.y.saturating_div(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_div(rhs.x),
+            y: self.y.saturating_div(rhs.y),
+            z: self.z.saturating_div(rhs.z),
+            w: self.w.saturating_div(rhs.w),
+        }
+    }
+}
+
+impl Default for I64Vec4 {
+    #[inline(always)]
+    fn default() -> Self {
+        Self::ZERO
+    }
+}
+
+impl Div<I64Vec4> for I64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.div(rhs.x),
+            y: self.y.div(rhs.y),
+            z: self.z.div(rhs.z),
+            w: self.w.div(rhs.w),
+        }
+    }
+}
+
+impl DivAssign<I64Vec4> for I64Vec4 {
+    #[inline]
+    fn div_assign(&mut self, rhs: Self) {
+        self.x.div_assign(rhs.x);
+        self.y.div_assign(rhs.y);
+        self.z.div_assign(rhs.z);
+        self.w.div_assign(rhs.w);
+    }
+}
+
+impl Div<i64> for I64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn div(self, rhs: i64) -> Self {
+        Self {
+            x: self.x.div(rhs),
+            y: self.y.div(rhs),
+            z: self.z.div(rhs),
+            w: self.w.div(rhs),
+        }
+    }
+}
+
+impl DivAssign<i64> for I64Vec4 {
+    #[inline]
+    fn div_assign(&mut self, rhs: i64) {
+        self.x.div_assign(rhs);
+        self.y.div_assign(rhs);
+        self.z.div_assign(rhs);
+        self.w.div_assign(rhs);
+    }
+}
+
+impl Div<I64Vec4> for i64 {
+    type Output = I64Vec4;
+    #[inline]
+    fn div(self, rhs: I64Vec4) -> I64Vec4 {
+        I64Vec4 {
+            x: self.div(rhs.x),
+            y: self.div(rhs.y),
+            z: self.div(rhs.z),
+            w: self.div(rhs.w),
+        }
+    }
+}
+
+impl Mul<I64Vec4> for I64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.mul(rhs.x),
+            y: self.y.mul(rhs.y),
+            z: self.z.mul(rhs.z),
+            w: self.w.mul(rhs.w),
+        }
+    }
+}
+
+impl MulAssign<I64Vec4> for I64Vec4 {
+    #[inline]
+    fn mul_assign(&mut self, rhs: Self) {
+        self.x.mul_assign(rhs.x);
+        self.y.mul_assign(rhs.y);
+        self.z.mul_assign(rhs.z);
+        self.w.mul_assign(rhs.w);
+    }
+}
+
+impl Mul<i64> for I64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn mul(self, rhs: i64) -> Self {
+        Self {
+            x: self.x.mul(rhs),
+            y: self.y.mul(rhs),
+            z: self.z.mul(rhs),
+            w: self.w.mul(rhs),
+        }
+    }
+}
+
+impl MulAssign<i64> for I64Vec4 {
+    #[inline]
+    fn mul_assign(&mut self, rhs: i64) {
+        self.x.mul_assign(rhs);
+        self.y.mul_assign(rhs);
+        self.z.mul_assign(rhs);
+        self.w.mul_assign(rhs);
+    }
+}
+
+impl Mul<I64Vec4> for i64 {
+    type Output = I64Vec4;
+    #[inline]
+    fn mul(self, rhs: I64Vec4) -> I64Vec4 {
+        I64Vec4 {
+            x: self.mul(rhs.x),
+            y: self.mul(rhs.y),
+            z: self.mul(rhs.z),
+            w: self.mul(rhs.w),
+        }
+    }
+}
+
+impl Add<I64Vec4> for I64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.add(rhs.x),
+            y: self.y.add(rhs.y),
+            z: self.z.add(rhs.z),
+            w: self.w.add(rhs.w),
+        }
+    }
+}
+
+impl AddAssign<I64Vec4> for I64Vec4 {
+    #[inline]
+    fn add_assign(&mut self, rhs: Self) {
+        self.x.add_assign(rhs.x);
+        self.y.add_assign(rhs.y);
+        self.z.add_assign(rhs.z);
+        self.w.add_assign(rhs.w);
+    }
+}
+
+impl Add<i64> for I64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn add(self, rhs: i64) -> Self {
+        Self {
+            x: self.x.add(rhs),
+            y: self.y.add(rhs),
+            z: self.z.add(rhs),
+            w: self.w.add(rhs),
+        }
+    }
+}
+
+impl AddAssign<i64> for I64Vec4 {
+    #[inline]
+    fn add_assign(&mut self, rhs: i64) {
+        self.x.add_assign(rhs);
+        self.y.add_assign(rhs);
+        self.z.add_assign(rhs);
+        self.w.add_assign(rhs);
+    }
+}
+
+impl Add<I64Vec4> for i64 {
+    type Output = I64Vec4;
+    #[inline]
+    fn add(self, rhs: I64Vec4) -> I64Vec4 {
+        I64Vec4 {
+            x: self.add(rhs.x),
+            y: self.add(rhs.y),
+            z: self.add(rhs.z),
+            w: self.add(rhs.w),
+        }
+    }
+}
+
+impl Sub<I64Vec4> for I64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.sub(rhs.x),
+            y: self.y.sub(rhs.y),
+            z: self.z.sub(rhs.z),
+            w: self.w.sub(rhs.w),
+        }
+    }
+}
+
+impl SubAssign<I64Vec4> for I64Vec4 {
+    #[inline]
+    fn sub_assign(&mut self, rhs: I64Vec4) {
+        self.x.sub_assign(rhs.x);
+        self.y.sub_assign(rhs.y);
+        self.z.sub_assign(rhs.z);
+        self.w.sub_assign(rhs.w);
+    }
+}
+
+impl Sub<i64> for I64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn sub(self, rhs: i64) -> Self {
+        Self {
+            x: self.x.sub(rhs),
+            y: self.y.sub(rhs),
+            z: self.z.sub(rhs),
+            w: self.w.sub(rhs),
+        }
+    }
+}
+
+impl SubAssign<i64> for I64Vec4 {
+    #[inline]
+    fn sub_assign(&mut self, rhs: i64) {
+        self.x.sub_assign(rhs);
+        self.y.sub_assign(rhs);
+        self.z.sub_assign(rhs);
+        self.w.sub_assign(rhs);
+    }
+}
+
+impl Sub<I64Vec4> for i64 {
+    type Output = I64Vec4;
+    #[inline]
+    fn sub(self, rhs: I64Vec4) -> I64Vec4 {
+        I64Vec4 {
+            x: self.sub(rhs.x),
+            y: self.sub(rhs.y),
+            z: self.sub(rhs.z),
+            w: self.sub(rhs.w),
+        }
+    }
+}
+
+impl Rem<I64Vec4> for I64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn rem(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.rem(rhs.x),
+            y: self.y.rem(rhs.y),
+            z: self.z.rem(rhs.z),
+            w: self.w.rem(rhs.w),
+        }
+    }
+}
+
+impl RemAssign<I64Vec4> for I64Vec4 {
+    #[inline]
+    fn rem_assign(&mut self, rhs: Self) {
+        self.x.rem_assign(rhs.x);
+        self.y.rem_assign(rhs.y);
+        self.z.rem_assign(rhs.z);
+        self.w.rem_assign(rhs.w);
+    }
+}
+
+impl Rem<i64> for I64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn rem(self, rhs: i64) -> Self {
+        Self {
+            x: self.x.rem(rhs),
+            y: self.y.rem(rhs),
+            z: self.z.rem(rhs),
+            w: self.w.rem(rhs),
+        }
+    }
+}
+
+impl RemAssign<i64> for I64Vec4 {
+    #[inline]
+    fn rem_assign(&mut self, rhs: i64) {
+        self.x.rem_assign(rhs);
+        self.y.rem_assign(rhs);
+        self.z.rem_assign(rhs);
+        self.w.rem_assign(rhs);
+    }
+}
+
+impl Rem<I64Vec4> for i64 {
+    type Output = I64Vec4;
+    #[inline]
+    fn rem(self, rhs: I64Vec4) -> I64Vec4 {
+        I64Vec4 {
+            x: self.rem(rhs.x),
+            y: self.rem(rhs.y),
+            z: self.rem(rhs.z),
+            w: self.rem(rhs.w),
+        }
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl AsRef<[i64; 4]> for I64Vec4 {
+    #[inline]
+    fn as_ref(&self) -> &[i64; 4] {
+        unsafe { &*(self as *const I64Vec4 as *const [i64; 4]) }
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl AsMut<[i64; 4]> for I64Vec4 {
+    #[inline]
+    fn as_mut(&mut self) -> &mut [i64; 4] {
+        unsafe { &mut *(self as *mut I64Vec4 as *mut [i64; 4]) }
+    }
+}
+
+impl Sum for I64Vec4 {
+    #[inline]
+    fn sum<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = Self>,
+    {
+        iter.fold(Self::ZERO, Self::add)
+    }
+}
+
+impl<'a> Sum<&'a Self> for I64Vec4 {
+    #[inline]
+    fn sum<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = &'a Self>,
+    {
+        iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
+    }
+}
+
+impl Product for I64Vec4 {
+    #[inline]
+    fn product<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = Self>,
+    {
+        iter.fold(Self::ONE, Self::mul)
+    }
+}
+
+impl<'a> Product<&'a Self> for I64Vec4 {
+    #[inline]
+    fn product<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = &'a Self>,
+    {
+        iter.fold(Self::ONE, |a, &b| Self::mul(a, b))
+    }
+}
+
+impl Neg for I64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn neg(self) -> Self {
+        Self {
+            x: self.x.neg(),
+            y: self.y.neg(),
+            z: self.z.neg(),
+            w: self.w.neg(),
+        }
+    }
+}
+
+impl Not for I64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn not(self) -> Self::Output {
+        Self {
+            x: self.x.not(),
+            y: self.y.not(),
+            z: self.z.not(),
+            w: self.w.not(),
+        }
+    }
+}
+
+impl BitAnd for I64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn bitand(self, rhs: Self) -> Self::Output {
+        Self {
+            x: self.x.bitand(rhs.x),
+            y: self.y.bitand(rhs.y),
+            z: self.z.bitand(rhs.z),
+            w: self.w.bitand(rhs.w),
+        }
+    }
+}
+
+impl BitOr for I64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn bitor(self, rhs: Self) -> Self::Output {
+        Self {
+            x: self.x.bitor(rhs.x),
+            y: self.y.bitor(rhs.y),
+            z: self.z.bitor(rhs.z),
+            w: self.w.bitor(rhs.w),
+        }
+    }
+}
+
+impl BitXor for I64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn bitxor(self, rhs: Self) -> Self::Output {
+        Self {
+            x: self.x.bitxor(rhs.x),
+            y: self.y.bitxor(rhs.y),
+            z: self.z.bitxor(rhs.z),
+            w: self.w.bitxor(rhs.w),
+        }
+    }
+}
+
+impl BitAnd<i64> for I64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn bitand(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.bitand(rhs),
+            y: self.y.bitand(rhs),
+            z: self.z.bitand(rhs),
+            w: self.w.bitand(rhs),
+        }
+    }
+}
+
+impl BitOr<i64> for I64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn bitor(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.bitor(rhs),
+            y: self.y.bitor(rhs),
+            z: self.z.bitor(rhs),
+            w: self.w.bitor(rhs),
+        }
+    }
+}
+
+impl BitXor<i64> for I64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn bitxor(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.bitxor(rhs),
+            y: self.y.bitxor(rhs),
+            z: self.z.bitxor(rhs),
+            w: self.w.bitxor(rhs),
+        }
+    }
+}
+
+impl Shl<i8> for I64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i8) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+            w: self.w.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i8> for I64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i8) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+            w: self.w.shr(rhs),
+        }
+    }
+}
+
+impl Shl<i16> for I64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i16) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+            w: self.w.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i16> for I64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i16) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+            w: self.w.shr(rhs),
+        }
+    }
+}
+
+impl Shl<i32> for I64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i32) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+            w: self.w.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i32> for I64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i32) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+            w: self.w.shr(rhs),
+        }
+    }
+}
+
+impl Shl<i64> for I64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+            w: self.w.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i64> for I64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+            w: self.w.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u8> for I64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u8) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+            w: self.w.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u8> for I64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u8) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+            w: self.w.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u16> for I64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u16) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+            w: self.w.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u16> for I64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u16) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+            w: self.w.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u32> for I64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u32) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+            w: self.w.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u32> for I64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u32) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+            w: self.w.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u64> for I64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+            w: self.w.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u64> for I64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+            w: self.w.shr(rhs),
+        }
+    }
+}
+
+impl Shl<crate::IVec4> for I64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: crate::IVec4) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs.x),
+            y: self.y.shl(rhs.y),
+            z: self.z.shl(rhs.z),
+            w: self.w.shl(rhs.w),
+        }
+    }
+}
+
+impl Shr<crate::IVec4> for I64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: crate::IVec4) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs.x),
+            y: self.y.shr(rhs.y),
+            z: self.z.shr(rhs.z),
+            w: self.w.shr(rhs.w),
+        }
+    }
+}
+
+impl Shl<crate::UVec4> for I64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: crate::UVec4) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs.x),
+            y: self.y.shl(rhs.y),
+            z: self.z.shl(rhs.z),
+            w: self.w.shl(rhs.w),
+        }
+    }
+}
+
+impl Shr<crate::UVec4> for I64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: crate::UVec4) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs.x),
+            y: self.y.shr(rhs.y),
+            z: self.z.shr(rhs.z),
+            w: self.w.shr(rhs.w),
+        }
+    }
+}
+
+impl Index<usize> for I64Vec4 {
+    type Output = i64;
+    #[inline]
+    fn index(&self, index: usize) -> &Self::Output {
+        match index {
+            0 => &self.x,
+            1 => &self.y,
+            2 => &self.z,
+            3 => &self.w,
+            _ => panic!("index out of bounds"),
+        }
+    }
+}
+
+impl IndexMut<usize> for I64Vec4 {
+    #[inline]
+    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
+        match index {
+            0 => &mut self.x,
+            1 => &mut self.y,
+            2 => &mut self.z,
+            3 => &mut self.w,
+            _ => panic!("index out of bounds"),
+        }
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl fmt::Display for I64Vec4 {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w)
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl fmt::Debug for I64Vec4 {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt.debug_tuple(stringify!(I64Vec4))
+            .field(&self.x)
+            .field(&self.y)
+            .field(&self.z)
+            .field(&self.w)
+            .finish()
+    }
+}
+
+impl From<[i64; 4]> for I64Vec4 {
+    #[inline]
+    fn from(a: [i64; 4]) -> Self {
+        Self::new(a[0], a[1], a[2], a[3])
+    }
+}
+
+impl From<I64Vec4> for [i64; 4] {
+    #[inline]
+    fn from(v: I64Vec4) -> Self {
+        [v.x, v.y, v.z, v.w]
+    }
+}
+
+impl From<(i64, i64, i64, i64)> for I64Vec4 {
+    #[inline]
+    fn from(t: (i64, i64, i64, i64)) -> Self {
+        Self::new(t.0, t.1, t.2, t.3)
+    }
+}
+
+impl From<I64Vec4> for (i64, i64, i64, i64) {
+    #[inline]
+    fn from(v: I64Vec4) -> Self {
+        (v.x, v.y, v.z, v.w)
+    }
+}
+
+impl From<(I64Vec3, i64)> for I64Vec4 {
+    #[inline]
+    fn from((v, w): (I64Vec3, i64)) -> Self {
+        Self::new(v.x, v.y, v.z, w)
+    }
+}
+
+impl From<(i64, I64Vec3)> for I64Vec4 {
+    #[inline]
+    fn from((x, v): (i64, I64Vec3)) -> Self {
+        Self::new(x, v.x, v.y, v.z)
+    }
+}
+
+impl From<(I64Vec2, i64, i64)> for I64Vec4 {
+    #[inline]
+    fn from((v, z, w): (I64Vec2, i64, i64)) -> Self {
+        Self::new(v.x, v.y, z, w)
+    }
+}
+
+impl From<(I64Vec2, I64Vec2)> for I64Vec4 {
+    #[inline]
+    fn from((v, u): (I64Vec2, I64Vec2)) -> Self {
+        Self::new(v.x, v.y, u.x, u.y)
+    }
+}
+
+impl From<I16Vec4> for I64Vec4 {
+    #[inline]
+    fn from(v: I16Vec4) -> Self {
+        Self::new(
+            i64::from(v.x),
+            i64::from(v.y),
+            i64::from(v.z),
+            i64::from(v.w),
+        )
+    }
+}
+
+impl From<U16Vec4> for I64Vec4 {
+    #[inline]
+    fn from(v: U16Vec4) -> Self {
+        Self::new(
+            i64::from(v.x),
+            i64::from(v.y),
+            i64::from(v.z),
+            i64::from(v.w),
+        )
+    }
+}
+
+impl From<IVec4> for I64Vec4 {
+    #[inline]
+    fn from(v: IVec4) -> Self {
+        Self::new(
+            i64::from(v.x),
+            i64::from(v.y),
+            i64::from(v.z),
+            i64::from(v.w),
+        )
+    }
+}
+
+impl From<UVec4> for I64Vec4 {
+    #[inline]
+    fn from(v: UVec4) -> Self {
+        Self::new(
+            i64::from(v.x),
+            i64::from(v.y),
+            i64::from(v.z),
+            i64::from(v.w),
+        )
+    }
+}
+
+impl TryFrom<U64Vec4> for I64Vec4 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: U64Vec4) -> Result<Self, Self::Error> {
+        Ok(Self::new(
+            i64::try_from(v.x)?,
+            i64::try_from(v.y)?,
+            i64::try_from(v.z)?,
+            i64::try_from(v.w)?,
+        ))
+    }
+}
diff --git a/src/lib.rs b/src/lib.rs
index 3027ec2..1c466df 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -15,10 +15,18 @@
   * square matrices: [`DMat2`], [`DMat3`] and [`DMat4`]
   * a quaternion type: [`DQuat`]
   * affine transformation types: [`DAffine2`] and [`DAffine3`]
+* [`i16`](mod@i16) types
+  * vectors: [`I16Vec2`], [`I16Vec3`] and [`I16Vec4`]
+* [`u16`](mod@u16) types
+  * vectors: [`U16Vec2`], [`U16Vec3`] and [`U16Vec4`]
 * [`i32`](mod@i32) types
   * vectors: [`IVec2`], [`IVec3`] and [`IVec4`]
 * [`u32`](mod@u32) types
   * vectors: [`UVec2`], [`UVec3`] and [`UVec4`]
+* [`i64`](mod@i64) types
+  * vectors: [`I64Vec2`], [`I64Vec3`] and [`I64Vec4`]
+* [`u64`](mod@u64) types
+  * vectors: [`U64Vec2`], [`U64Vec3`] and [`U64Vec4`]
 * [`bool`](mod@bool) types
   * vectors: [`BVec2`], [`BVec3`] and [`BVec4`]
 
@@ -214,10 +222,8 @@
 * `std` - the default feature, has no dependencies.
 * `approx` - traits and macros for approximate float comparisons
 * `bytemuck` - for casting into slices of bytes
-* `libm` - required to compile with `no_std`
+* `libm` - uses `libm` math functions instead of `std`, required to compile with `no_std`
 * `mint` - for interoperating with other 3D math libraries
-* `num-traits` - required to compile `no_std`, will be included when enabling
-  the `libm` feature
 * `rand` - implementations of `Distribution` trait for all `glam` types.
 * `rkyv` - implementations of `Archive`, `Serialize` and `Deserialize` for all
   `glam` types. Note that serialization is not interoperable with and without the
@@ -245,7 +251,7 @@
 The minimum supported Rust version is `1.58.1`.
 
 */
-#![doc(html_root_url = "https://docs.rs/glam/0.23.0")]
+#![doc(html_root_url = "https://docs.rs/glam/0.25.0")]
 #![cfg_attr(not(feature = "std"), no_std)]
 #![cfg_attr(target_arch = "spirv", feature(repr_simd))]
 #![deny(
@@ -268,7 +274,6 @@
 mod deref;
 mod euler;
 mod features;
-mod float_ex;
 
 #[cfg(target_arch = "spirv")]
 mod spirv;
@@ -294,8 +299,6 @@
 ))]
 use align16::Align16;
 
-use float_ex::FloatEx;
-
 /** `bool` vector mask types. */
 pub mod bool;
 pub use self::bool::*;
@@ -308,6 +311,14 @@
 pub mod f64;
 pub use self::f64::*;
 
+/** `i16` vector types. */
+pub mod i16;
+pub use self::i16::*;
+
+/** `u16` vector types. */
+pub mod u16;
+pub use self::u16::*;
+
 /** `i32` vector types. */
 pub mod i32;
 pub use self::i32::*;
@@ -316,9 +327,21 @@
 pub mod u32;
 pub use self::u32::*;
 
+/** `i64` vector types. */
+pub mod i64;
+pub use self::i64::*;
+
+/** `u64` vector types. */
+pub mod u64;
+pub use self::u64::*;
+
 /** Traits adding swizzle methods to all vector types. */
 pub mod swizzles;
 pub use self::swizzles::{Vec2Swizzles, Vec3Swizzles, Vec4Swizzles};
 
 /** Rotation Helper */
 pub use euler::EulerRot;
+
+/** A trait for extending [`prim@f32`] and [`prim@f64`] with extra methods. */
+mod float;
+pub use float::FloatExt;
diff --git a/src/sse2.rs b/src/sse2.rs
index e1e6b74..e31675a 100644
--- a/src/sse2.rs
+++ b/src/sse2.rs
@@ -3,6 +3,7 @@
 #[cfg(target_arch = "x86_64")]
 use core::arch::x86_64::*;
 
+#[repr(C)]
 union UnionCast {
     u32x4: [u32; 4],
     f32x4: [f32; 4],
@@ -17,6 +18,7 @@
     unsafe { UnionCast { u32x4 }.m128 }
 }
 
+const PS_ABS_MASK: __m128 = m128_from_u32x4([0x7fffffff; 4]);
 const PS_INV_SIGN_MASK: __m128 = m128_from_u32x4([!0x8000_0000; 4]);
 const PS_SIGN_MASK: __m128 = m128_from_u32x4([0x8000_0000; 4]);
 const PS_NO_FRACTION: __m128 = m128_from_f32x4([8388608.0; 4]);
@@ -156,6 +158,25 @@
     _mm_xor_ps(r1, r2)
 }
 
+#[inline]
+pub(crate) unsafe fn m128_trunc(v: __m128) -> __m128 {
+    // Based on https://github.com/microsoft/DirectXMath `XMVectorTruncate`
+    // To handle NAN, INF and numbers greater than 8388608, use masking
+    // Get the abs value
+    let mut vtest = _mm_and_si128(_mm_castps_si128(v), _mm_castps_si128(PS_ABS_MASK));
+    // Test for greater than 8388608 (All floats with NO fractionals, NAN and INF
+    vtest = _mm_cmplt_epi32(vtest, _mm_castps_si128(PS_NO_FRACTION));
+    // Convert to int and back to float for rounding with truncation
+    let vint = _mm_cvttps_epi32(v);
+    // Convert back to floats
+    let mut vresult = _mm_cvtepi32_ps(vint);
+    // All numbers less than 8388608 will use the round to int
+    vresult = _mm_and_ps(vresult, _mm_castsi128_ps(vtest));
+    // All others, use the ORIGINAL value
+    vtest = _mm_andnot_si128(vtest, _mm_castps_si128(v));
+    _mm_or_ps(vresult, _mm_castsi128_ps(vtest))
+}
+
 /// Returns a vector whose components are the corresponding components of Angles modulo 2PI.
 #[inline]
 pub(crate) unsafe fn m128_mod_angles(angles: __m128) -> __m128 {
diff --git a/src/swizzles.rs b/src/swizzles.rs
index 61a3391..683a574 100644
--- a/src/swizzles.rs
+++ b/src/swizzles.rs
@@ -6,6 +6,22 @@
 mod ivec3_impl;
 mod ivec4_impl;
 
+mod i16vec2_impl;
+mod i16vec3_impl;
+mod i16vec4_impl;
+
+mod u16vec2_impl;
+mod u16vec3_impl;
+mod u16vec4_impl;
+
+mod i64vec2_impl;
+mod i64vec3_impl;
+mod i64vec4_impl;
+
+mod u64vec2_impl;
+mod u64vec3_impl;
+mod u64vec4_impl;
+
 mod uvec2_impl;
 mod uvec3_impl;
 mod uvec4_impl;
diff --git a/src/swizzles/coresimd/vec3a_impl.rs b/src/swizzles/coresimd/vec3a_impl.rs
index 5ea3a8d..36cb9ae 100644
--- a/src/swizzles/coresimd/vec3a_impl.rs
+++ b/src/swizzles/coresimd/vec3a_impl.rs
@@ -12,6 +12,7 @@
     type Vec4 = Vec4;
 
     #[inline]
+    #[must_use]
     fn xx(self) -> Vec2 {
         Vec2 {
             x: self.x,
@@ -20,6 +21,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xy(self) -> Vec2 {
         Vec2 {
             x: self.x,
@@ -28,6 +30,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xz(self) -> Vec2 {
         Vec2 {
             x: self.x,
@@ -36,6 +39,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yx(self) -> Vec2 {
         Vec2 {
             x: self.y,
@@ -44,6 +48,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yy(self) -> Vec2 {
         Vec2 {
             x: self.y,
@@ -52,6 +57,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yz(self) -> Vec2 {
         Vec2 {
             x: self.y,
@@ -60,6 +66,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zx(self) -> Vec2 {
         Vec2 {
             x: self.z,
@@ -68,6 +75,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zy(self) -> Vec2 {
         Vec2 {
             x: self.z,
@@ -76,6 +84,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zz(self) -> Vec2 {
         Vec2 {
             x: self.z,
@@ -84,541 +93,649 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxx(self) -> Vec3A {
         Vec3A(simd_swizzle!(self.0, [0, 0, 0, 0]).into())
     }
 
     #[inline]
+    #[must_use]
     fn xxy(self) -> Vec3A {
         Vec3A(simd_swizzle!(self.0, [0, 0, 1, 0]).into())
     }
 
     #[inline]
+    #[must_use]
     fn xxz(self) -> Vec3A {
         Vec3A(simd_swizzle!(self.0, [0, 0, 2, 0]).into())
     }
 
     #[inline]
+    #[must_use]
     fn xyx(self) -> Vec3A {
         Vec3A(simd_swizzle!(self.0, [0, 1, 0, 0]).into())
     }
 
     #[inline]
+    #[must_use]
     fn xyy(self) -> Vec3A {
         Vec3A(simd_swizzle!(self.0, [0, 1, 1, 0]).into())
     }
 
     #[inline]
+    #[must_use]
     fn xyz(self) -> Vec3A {
         Vec3A(simd_swizzle!(self.0, [0, 1, 2, 0]).into())
     }
 
     #[inline]
+    #[must_use]
     fn xzx(self) -> Vec3A {
         Vec3A(simd_swizzle!(self.0, [0, 2, 0, 0]).into())
     }
 
     #[inline]
+    #[must_use]
     fn xzy(self) -> Vec3A {
         Vec3A(simd_swizzle!(self.0, [0, 2, 1, 0]).into())
     }
 
     #[inline]
+    #[must_use]
     fn xzz(self) -> Vec3A {
         Vec3A(simd_swizzle!(self.0, [0, 2, 2, 0]).into())
     }
 
     #[inline]
+    #[must_use]
     fn yxx(self) -> Vec3A {
         Vec3A(simd_swizzle!(self.0, [1, 0, 0, 0]).into())
     }
 
     #[inline]
+    #[must_use]
     fn yxy(self) -> Vec3A {
         Vec3A(simd_swizzle!(self.0, [1, 0, 1, 0]).into())
     }
 
     #[inline]
+    #[must_use]
     fn yxz(self) -> Vec3A {
         Vec3A(simd_swizzle!(self.0, [1, 0, 2, 0]).into())
     }
 
     #[inline]
+    #[must_use]
     fn yyx(self) -> Vec3A {
         Vec3A(simd_swizzle!(self.0, [1, 1, 0, 0]).into())
     }
 
     #[inline]
+    #[must_use]
     fn yyy(self) -> Vec3A {
         Vec3A(simd_swizzle!(self.0, [1, 1, 1, 0]).into())
     }
 
     #[inline]
+    #[must_use]
     fn yyz(self) -> Vec3A {
         Vec3A(simd_swizzle!(self.0, [1, 1, 2, 0]).into())
     }
 
     #[inline]
+    #[must_use]
     fn yzx(self) -> Vec3A {
         Vec3A(simd_swizzle!(self.0, [1, 2, 0, 0]).into())
     }
 
     #[inline]
+    #[must_use]
     fn yzy(self) -> Vec3A {
         Vec3A(simd_swizzle!(self.0, [1, 2, 1, 0]).into())
     }
 
     #[inline]
+    #[must_use]
     fn yzz(self) -> Vec3A {
         Vec3A(simd_swizzle!(self.0, [1, 2, 2, 0]).into())
     }
 
     #[inline]
+    #[must_use]
     fn zxx(self) -> Vec3A {
         Vec3A(simd_swizzle!(self.0, [2, 0, 0, 0]).into())
     }
 
     #[inline]
+    #[must_use]
     fn zxy(self) -> Vec3A {
         Vec3A(simd_swizzle!(self.0, [2, 0, 1, 0]).into())
     }
 
     #[inline]
+    #[must_use]
     fn zxz(self) -> Vec3A {
         Vec3A(simd_swizzle!(self.0, [2, 0, 2, 0]).into())
     }
 
     #[inline]
+    #[must_use]
     fn zyx(self) -> Vec3A {
         Vec3A(simd_swizzle!(self.0, [2, 1, 0, 0]).into())
     }
 
     #[inline]
+    #[must_use]
     fn zyy(self) -> Vec3A {
         Vec3A(simd_swizzle!(self.0, [2, 1, 1, 0]).into())
     }
 
     #[inline]
+    #[must_use]
     fn zyz(self) -> Vec3A {
         Vec3A(simd_swizzle!(self.0, [2, 1, 2, 0]).into())
     }
 
     #[inline]
+    #[must_use]
     fn zzx(self) -> Vec3A {
         Vec3A(simd_swizzle!(self.0, [2, 2, 0, 0]).into())
     }
 
     #[inline]
+    #[must_use]
     fn zzy(self) -> Vec3A {
         Vec3A(simd_swizzle!(self.0, [2, 2, 1, 0]).into())
     }
 
     #[inline]
+    #[must_use]
     fn zzz(self) -> Vec3A {
         Vec3A(simd_swizzle!(self.0, [2, 2, 2, 0]).into())
     }
 
     #[inline]
+    #[must_use]
     fn xxxx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 0, 0, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn xxxy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 0, 0, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn xxxz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 0, 0, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn xxyx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 0, 1, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn xxyy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 0, 1, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn xxyz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 0, 1, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn xxzx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 0, 2, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn xxzy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 0, 2, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn xxzz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 0, 2, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn xyxx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 1, 0, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn xyxy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 1, 0, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn xyxz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 1, 0, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn xyyx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 1, 1, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn xyyy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 1, 1, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn xyyz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 1, 1, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn xyzx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 1, 2, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn xyzy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 1, 2, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn xyzz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 1, 2, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn xzxx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 2, 0, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn xzxy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 2, 0, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn xzxz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 2, 0, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn xzyx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 2, 1, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn xzyy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 2, 1, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn xzyz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 2, 1, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn xzzx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 2, 2, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn xzzy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 2, 2, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn xzzz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 2, 2, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn yxxx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 0, 0, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn yxxy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 0, 0, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn yxxz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 0, 0, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn yxyx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 0, 1, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn yxyy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 0, 1, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn yxyz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 0, 1, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn yxzx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 0, 2, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn yxzy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 0, 2, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn yxzz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 0, 2, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn yyxx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 1, 0, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn yyxy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 1, 0, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn yyxz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 1, 0, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn yyyx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 1, 1, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn yyyy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 1, 1, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn yyyz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 1, 1, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn yyzx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 1, 2, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn yyzy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 1, 2, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn yyzz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 1, 2, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn yzxx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 2, 0, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn yzxy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 2, 0, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn yzxz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 2, 0, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn yzyx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 2, 1, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn yzyy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 2, 1, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn yzyz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 2, 1, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn yzzx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 2, 2, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn yzzy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 2, 2, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn yzzz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 2, 2, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn zxxx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 0, 0, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn zxxy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 0, 0, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn zxxz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 0, 0, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn zxyx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 0, 1, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn zxyy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 0, 1, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn zxyz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 0, 1, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn zxzx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 0, 2, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn zxzy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 0, 2, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn zxzz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 0, 2, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn zyxx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 1, 0, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn zyxy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 1, 0, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn zyxz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 1, 0, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn zyyx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 1, 1, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn zyyy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 1, 1, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn zyyz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 1, 1, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn zyzx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 1, 2, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn zyzy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 1, 2, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn zyzz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 1, 2, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn zzxx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 2, 0, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn zzxy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 2, 0, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn zzxz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 2, 0, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn zzyx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 2, 1, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn zzyy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 2, 1, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn zzyz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 2, 1, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn zzzx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 2, 2, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn zzzy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 2, 2, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn zzzz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 2, 2, 2]))
     }
diff --git a/src/swizzles/coresimd/vec4_impl.rs b/src/swizzles/coresimd/vec4_impl.rs
index 0c8649d..19eba73 100644
--- a/src/swizzles/coresimd/vec4_impl.rs
+++ b/src/swizzles/coresimd/vec4_impl.rs
@@ -12,6 +12,7 @@
     type Vec3 = Vec3;
 
     #[inline]
+    #[must_use]
     fn xx(self) -> Vec2 {
         Vec2 {
             x: self.x,
@@ -20,6 +21,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xy(self) -> Vec2 {
         Vec2 {
             x: self.x,
@@ -28,6 +30,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xz(self) -> Vec2 {
         Vec2 {
             x: self.x,
@@ -36,6 +39,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xw(self) -> Vec2 {
         Vec2 {
             x: self.x,
@@ -44,6 +48,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yx(self) -> Vec2 {
         Vec2 {
             x: self.y,
@@ -52,6 +57,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yy(self) -> Vec2 {
         Vec2 {
             x: self.y,
@@ -60,6 +66,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yz(self) -> Vec2 {
         Vec2 {
             x: self.y,
@@ -68,6 +75,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yw(self) -> Vec2 {
         Vec2 {
             x: self.y,
@@ -76,6 +84,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zx(self) -> Vec2 {
         Vec2 {
             x: self.z,
@@ -84,6 +93,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zy(self) -> Vec2 {
         Vec2 {
             x: self.z,
@@ -92,6 +102,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zz(self) -> Vec2 {
         Vec2 {
             x: self.z,
@@ -100,6 +111,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zw(self) -> Vec2 {
         Vec2 {
             x: self.z,
@@ -108,6 +120,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wx(self) -> Vec2 {
         Vec2 {
             x: self.w,
@@ -116,6 +129,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wy(self) -> Vec2 {
         Vec2 {
             x: self.w,
@@ -124,6 +138,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wz(self) -> Vec2 {
         Vec2 {
             x: self.w,
@@ -132,6 +147,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn ww(self) -> Vec2 {
         Vec2 {
             x: self.w,
@@ -140,6 +156,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxx(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -149,6 +166,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxy(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -158,6 +176,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxz(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -167,6 +186,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxw(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -176,6 +196,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyx(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -185,6 +206,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyy(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -194,6 +216,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyz(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -203,6 +226,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyw(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -212,6 +236,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzx(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -221,6 +246,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzy(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -230,6 +256,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzz(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -239,6 +266,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzw(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -248,6 +276,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xwx(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -257,6 +286,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xwy(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -266,6 +296,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xwz(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -275,6 +306,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xww(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -284,6 +316,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxx(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -293,6 +326,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxy(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -302,6 +336,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxz(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -311,6 +346,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxw(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -320,6 +356,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyx(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -329,6 +366,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyy(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -338,6 +376,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyz(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -347,6 +386,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyw(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -356,6 +396,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzx(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -365,6 +406,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzy(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -374,6 +416,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzz(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -383,6 +426,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzw(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -392,6 +436,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn ywx(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -401,6 +446,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn ywy(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -410,6 +456,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn ywz(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -419,6 +466,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yww(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -428,6 +476,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxx(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -437,6 +486,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxy(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -446,6 +496,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxz(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -455,6 +506,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxw(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -464,6 +516,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyx(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -473,6 +526,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyy(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -482,6 +536,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyz(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -491,6 +546,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyw(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -500,6 +556,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzx(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -509,6 +566,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzy(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -518,6 +576,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzz(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -527,6 +586,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzw(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -536,6 +596,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zwx(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -545,6 +606,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zwy(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -554,6 +616,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zwz(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -563,6 +626,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zww(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -572,6 +636,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wxx(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -581,6 +646,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wxy(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -590,6 +656,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wxz(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -599,6 +666,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wxw(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -608,6 +676,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wyx(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -617,6 +686,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wyy(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -626,6 +696,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wyz(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -635,6 +706,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wyw(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -644,6 +716,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wzx(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -653,6 +726,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wzy(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -662,6 +736,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wzz(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -671,6 +746,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wzw(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -680,6 +756,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wwx(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -689,6 +766,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wwy(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -698,6 +776,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wwz(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -707,6 +786,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn www(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -716,1281 +796,1537 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxxx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 0, 0, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn xxxy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 0, 0, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn xxxz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 0, 0, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn xxxw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 0, 0, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn xxyx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 0, 1, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn xxyy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 0, 1, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn xxyz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 0, 1, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn xxyw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 0, 1, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn xxzx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 0, 2, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn xxzy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 0, 2, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn xxzz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 0, 2, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn xxzw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 0, 2, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn xxwx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 0, 3, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn xxwy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 0, 3, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn xxwz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 0, 3, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn xxww(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 0, 3, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn xyxx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 1, 0, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn xyxy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 1, 0, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn xyxz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 1, 0, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn xyxw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 1, 0, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn xyyx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 1, 1, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn xyyy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 1, 1, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn xyyz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 1, 1, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn xyyw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 1, 1, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn xyzx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 1, 2, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn xyzy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 1, 2, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn xyzz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 1, 2, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn xyzw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 1, 2, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn xywx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 1, 3, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn xywy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 1, 3, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn xywz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 1, 3, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn xyww(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 1, 3, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn xzxx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 2, 0, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn xzxy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 2, 0, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn xzxz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 2, 0, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn xzxw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 2, 0, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn xzyx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 2, 1, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn xzyy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 2, 1, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn xzyz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 2, 1, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn xzyw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 2, 1, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn xzzx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 2, 2, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn xzzy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 2, 2, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn xzzz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 2, 2, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn xzzw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 2, 2, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn xzwx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 2, 3, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn xzwy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 2, 3, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn xzwz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 2, 3, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn xzww(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 2, 3, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn xwxx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 3, 0, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn xwxy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 3, 0, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn xwxz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 3, 0, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn xwxw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 3, 0, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn xwyx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 3, 1, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn xwyy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 3, 1, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn xwyz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 3, 1, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn xwyw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 3, 1, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn xwzx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 3, 2, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn xwzy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 3, 2, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn xwzz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 3, 2, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn xwzw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 3, 2, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn xwwx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 3, 3, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn xwwy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 3, 3, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn xwwz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 3, 3, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn xwww(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [0, 3, 3, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn yxxx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 0, 0, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn yxxy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 0, 0, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn yxxz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 0, 0, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn yxxw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 0, 0, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn yxyx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 0, 1, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn yxyy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 0, 1, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn yxyz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 0, 1, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn yxyw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 0, 1, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn yxzx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 0, 2, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn yxzy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 0, 2, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn yxzz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 0, 2, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn yxzw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 0, 2, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn yxwx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 0, 3, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn yxwy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 0, 3, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn yxwz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 0, 3, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn yxww(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 0, 3, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn yyxx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 1, 0, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn yyxy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 1, 0, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn yyxz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 1, 0, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn yyxw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 1, 0, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn yyyx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 1, 1, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn yyyy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 1, 1, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn yyyz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 1, 1, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn yyyw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 1, 1, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn yyzx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 1, 2, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn yyzy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 1, 2, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn yyzz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 1, 2, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn yyzw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 1, 2, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn yywx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 1, 3, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn yywy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 1, 3, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn yywz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 1, 3, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn yyww(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 1, 3, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn yzxx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 2, 0, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn yzxy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 2, 0, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn yzxz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 2, 0, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn yzxw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 2, 0, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn yzyx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 2, 1, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn yzyy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 2, 1, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn yzyz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 2, 1, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn yzyw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 2, 1, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn yzzx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 2, 2, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn yzzy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 2, 2, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn yzzz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 2, 2, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn yzzw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 2, 2, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn yzwx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 2, 3, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn yzwy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 2, 3, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn yzwz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 2, 3, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn yzww(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 2, 3, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn ywxx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 3, 0, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn ywxy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 3, 0, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn ywxz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 3, 0, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn ywxw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 3, 0, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn ywyx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 3, 1, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn ywyy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 3, 1, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn ywyz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 3, 1, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn ywyw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 3, 1, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn ywzx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 3, 2, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn ywzy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 3, 2, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn ywzz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 3, 2, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn ywzw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 3, 2, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn ywwx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 3, 3, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn ywwy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 3, 3, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn ywwz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 3, 3, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn ywww(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [1, 3, 3, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn zxxx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 0, 0, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn zxxy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 0, 0, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn zxxz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 0, 0, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn zxxw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 0, 0, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn zxyx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 0, 1, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn zxyy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 0, 1, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn zxyz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 0, 1, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn zxyw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 0, 1, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn zxzx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 0, 2, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn zxzy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 0, 2, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn zxzz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 0, 2, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn zxzw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 0, 2, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn zxwx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 0, 3, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn zxwy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 0, 3, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn zxwz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 0, 3, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn zxww(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 0, 3, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn zyxx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 1, 0, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn zyxy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 1, 0, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn zyxz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 1, 0, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn zyxw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 1, 0, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn zyyx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 1, 1, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn zyyy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 1, 1, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn zyyz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 1, 1, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn zyyw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 1, 1, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn zyzx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 1, 2, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn zyzy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 1, 2, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn zyzz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 1, 2, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn zyzw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 1, 2, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn zywx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 1, 3, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn zywy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 1, 3, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn zywz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 1, 3, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn zyww(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 1, 3, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn zzxx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 2, 0, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn zzxy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 2, 0, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn zzxz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 2, 0, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn zzxw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 2, 0, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn zzyx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 2, 1, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn zzyy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 2, 1, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn zzyz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 2, 1, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn zzyw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 2, 1, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn zzzx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 2, 2, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn zzzy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 2, 2, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn zzzz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 2, 2, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn zzzw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 2, 2, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn zzwx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 2, 3, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn zzwy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 2, 3, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn zzwz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 2, 3, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn zzww(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 2, 3, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn zwxx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 3, 0, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn zwxy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 3, 0, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn zwxz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 3, 0, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn zwxw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 3, 0, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn zwyx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 3, 1, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn zwyy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 3, 1, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn zwyz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 3, 1, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn zwyw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 3, 1, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn zwzx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 3, 2, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn zwzy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 3, 2, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn zwzz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 3, 2, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn zwzw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 3, 2, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn zwwx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 3, 3, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn zwwy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 3, 3, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn zwwz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 3, 3, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn zwww(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [2, 3, 3, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn wxxx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 0, 0, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn wxxy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 0, 0, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn wxxz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 0, 0, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn wxxw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 0, 0, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn wxyx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 0, 1, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn wxyy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 0, 1, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn wxyz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 0, 1, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn wxyw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 0, 1, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn wxzx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 0, 2, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn wxzy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 0, 2, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn wxzz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 0, 2, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn wxzw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 0, 2, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn wxwx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 0, 3, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn wxwy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 0, 3, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn wxwz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 0, 3, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn wxww(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 0, 3, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn wyxx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 1, 0, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn wyxy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 1, 0, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn wyxz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 1, 0, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn wyxw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 1, 0, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn wyyx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 1, 1, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn wyyy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 1, 1, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn wyyz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 1, 1, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn wyyw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 1, 1, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn wyzx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 1, 2, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn wyzy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 1, 2, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn wyzz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 1, 2, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn wyzw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 1, 2, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn wywx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 1, 3, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn wywy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 1, 3, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn wywz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 1, 3, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn wyww(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 1, 3, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn wzxx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 2, 0, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn wzxy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 2, 0, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn wzxz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 2, 0, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn wzxw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 2, 0, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn wzyx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 2, 1, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn wzyy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 2, 1, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn wzyz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 2, 1, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn wzyw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 2, 1, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn wzzx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 2, 2, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn wzzy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 2, 2, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn wzzz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 2, 2, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn wzzw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 2, 2, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn wzwx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 2, 3, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn wzwy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 2, 3, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn wzwz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 2, 3, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn wzww(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 2, 3, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn wwxx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 3, 0, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn wwxy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 3, 0, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn wwxz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 3, 0, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn wwxw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 3, 0, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn wwyx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 3, 1, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn wwyy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 3, 1, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn wwyz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 3, 1, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn wwyw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 3, 1, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn wwzx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 3, 2, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn wwzy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 3, 2, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn wwzz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 3, 2, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn wwzw(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 3, 2, 3]))
     }
 
     #[inline]
+    #[must_use]
     fn wwwx(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 3, 3, 0]))
     }
 
     #[inline]
+    #[must_use]
     fn wwwy(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 3, 3, 1]))
     }
 
     #[inline]
+    #[must_use]
     fn wwwz(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 3, 3, 2]))
     }
 
     #[inline]
+    #[must_use]
     fn wwww(self) -> Vec4 {
         Vec4(simd_swizzle!(self.0, [3, 3, 3, 3]))
     }
diff --git a/src/swizzles/dvec2_impl.rs b/src/swizzles/dvec2_impl.rs
index dbf6dc3..f8c4748 100644
--- a/src/swizzles/dvec2_impl.rs
+++ b/src/swizzles/dvec2_impl.rs
@@ -8,6 +8,7 @@
     type Vec4 = DVec4;
 
     #[inline]
+    #[must_use]
     fn xx(self) -> DVec2 {
         DVec2 {
             x: self.x,
@@ -16,6 +17,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xy(self) -> DVec2 {
         DVec2 {
             x: self.x,
@@ -24,6 +26,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yx(self) -> DVec2 {
         DVec2 {
             x: self.y,
@@ -32,6 +35,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yy(self) -> DVec2 {
         DVec2 {
             x: self.y,
@@ -40,6 +44,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxx(self) -> DVec3 {
         DVec3 {
             x: self.x,
@@ -49,6 +54,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxy(self) -> DVec3 {
         DVec3 {
             x: self.x,
@@ -58,6 +64,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyx(self) -> DVec3 {
         DVec3 {
             x: self.x,
@@ -67,6 +74,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyy(self) -> DVec3 {
         DVec3 {
             x: self.x,
@@ -76,6 +84,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxx(self) -> DVec3 {
         DVec3 {
             x: self.y,
@@ -85,6 +94,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxy(self) -> DVec3 {
         DVec3 {
             x: self.y,
@@ -94,6 +104,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyx(self) -> DVec3 {
         DVec3 {
             x: self.y,
@@ -103,6 +114,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyy(self) -> DVec3 {
         DVec3 {
             x: self.y,
@@ -112,81 +124,97 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxxx(self) -> DVec4 {
         DVec4::new(self.x, self.x, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xxxy(self) -> DVec4 {
         DVec4::new(self.x, self.x, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xxyx(self) -> DVec4 {
         DVec4::new(self.x, self.x, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xxyy(self) -> DVec4 {
         DVec4::new(self.x, self.x, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xyxx(self) -> DVec4 {
         DVec4::new(self.x, self.y, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xyxy(self) -> DVec4 {
         DVec4::new(self.x, self.y, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xyyx(self) -> DVec4 {
         DVec4::new(self.x, self.y, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xyyy(self) -> DVec4 {
         DVec4::new(self.x, self.y, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yxxx(self) -> DVec4 {
         DVec4::new(self.y, self.x, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yxxy(self) -> DVec4 {
         DVec4::new(self.y, self.x, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yxyx(self) -> DVec4 {
         DVec4::new(self.y, self.x, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yxyy(self) -> DVec4 {
         DVec4::new(self.y, self.x, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yyxx(self) -> DVec4 {
         DVec4::new(self.y, self.y, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yyxy(self) -> DVec4 {
         DVec4::new(self.y, self.y, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yyyx(self) -> DVec4 {
         DVec4::new(self.y, self.y, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yyyy(self) -> DVec4 {
         DVec4::new(self.y, self.y, self.y, self.y)
     }
diff --git a/src/swizzles/dvec3_impl.rs b/src/swizzles/dvec3_impl.rs
index 0ea0cd4..235ae54 100644
--- a/src/swizzles/dvec3_impl.rs
+++ b/src/swizzles/dvec3_impl.rs
@@ -8,6 +8,7 @@
     type Vec4 = DVec4;
 
     #[inline]
+    #[must_use]
     fn xx(self) -> DVec2 {
         DVec2 {
             x: self.x,
@@ -16,6 +17,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xy(self) -> DVec2 {
         DVec2 {
             x: self.x,
@@ -24,6 +26,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xz(self) -> DVec2 {
         DVec2 {
             x: self.x,
@@ -32,6 +35,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yx(self) -> DVec2 {
         DVec2 {
             x: self.y,
@@ -40,6 +44,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yy(self) -> DVec2 {
         DVec2 {
             x: self.y,
@@ -48,6 +53,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yz(self) -> DVec2 {
         DVec2 {
             x: self.y,
@@ -56,6 +62,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zx(self) -> DVec2 {
         DVec2 {
             x: self.z,
@@ -64,6 +71,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zy(self) -> DVec2 {
         DVec2 {
             x: self.z,
@@ -72,6 +80,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zz(self) -> DVec2 {
         DVec2 {
             x: self.z,
@@ -80,6 +89,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxx(self) -> DVec3 {
         DVec3 {
             x: self.x,
@@ -89,6 +99,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxy(self) -> DVec3 {
         DVec3 {
             x: self.x,
@@ -98,6 +109,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxz(self) -> DVec3 {
         DVec3 {
             x: self.x,
@@ -107,6 +119,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyx(self) -> DVec3 {
         DVec3 {
             x: self.x,
@@ -116,6 +129,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyy(self) -> DVec3 {
         DVec3 {
             x: self.x,
@@ -125,6 +139,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyz(self) -> DVec3 {
         DVec3 {
             x: self.x,
@@ -134,6 +149,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzx(self) -> DVec3 {
         DVec3 {
             x: self.x,
@@ -143,6 +159,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzy(self) -> DVec3 {
         DVec3 {
             x: self.x,
@@ -152,6 +169,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzz(self) -> DVec3 {
         DVec3 {
             x: self.x,
@@ -161,6 +179,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxx(self) -> DVec3 {
         DVec3 {
             x: self.y,
@@ -170,6 +189,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxy(self) -> DVec3 {
         DVec3 {
             x: self.y,
@@ -179,6 +199,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxz(self) -> DVec3 {
         DVec3 {
             x: self.y,
@@ -188,6 +209,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyx(self) -> DVec3 {
         DVec3 {
             x: self.y,
@@ -197,6 +219,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyy(self) -> DVec3 {
         DVec3 {
             x: self.y,
@@ -206,6 +229,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyz(self) -> DVec3 {
         DVec3 {
             x: self.y,
@@ -215,6 +239,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzx(self) -> DVec3 {
         DVec3 {
             x: self.y,
@@ -224,6 +249,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzy(self) -> DVec3 {
         DVec3 {
             x: self.y,
@@ -233,6 +259,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzz(self) -> DVec3 {
         DVec3 {
             x: self.y,
@@ -242,6 +269,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxx(self) -> DVec3 {
         DVec3 {
             x: self.z,
@@ -251,6 +279,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxy(self) -> DVec3 {
         DVec3 {
             x: self.z,
@@ -260,6 +289,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxz(self) -> DVec3 {
         DVec3 {
             x: self.z,
@@ -269,6 +299,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyx(self) -> DVec3 {
         DVec3 {
             x: self.z,
@@ -278,6 +309,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyy(self) -> DVec3 {
         DVec3 {
             x: self.z,
@@ -287,6 +319,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyz(self) -> DVec3 {
         DVec3 {
             x: self.z,
@@ -296,6 +329,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzx(self) -> DVec3 {
         DVec3 {
             x: self.z,
@@ -305,6 +339,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzy(self) -> DVec3 {
         DVec3 {
             x: self.z,
@@ -314,6 +349,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzz(self) -> DVec3 {
         DVec3 {
             x: self.z,
@@ -323,406 +359,487 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxxx(self) -> DVec4 {
         DVec4::new(self.x, self.x, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xxxy(self) -> DVec4 {
         DVec4::new(self.x, self.x, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xxxz(self) -> DVec4 {
         DVec4::new(self.x, self.x, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xxyx(self) -> DVec4 {
         DVec4::new(self.x, self.x, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xxyy(self) -> DVec4 {
         DVec4::new(self.x, self.x, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xxyz(self) -> DVec4 {
         DVec4::new(self.x, self.x, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xxzx(self) -> DVec4 {
         DVec4::new(self.x, self.x, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xxzy(self) -> DVec4 {
         DVec4::new(self.x, self.x, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xxzz(self) -> DVec4 {
         DVec4::new(self.x, self.x, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xyxx(self) -> DVec4 {
         DVec4::new(self.x, self.y, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xyxy(self) -> DVec4 {
         DVec4::new(self.x, self.y, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xyxz(self) -> DVec4 {
         DVec4::new(self.x, self.y, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xyyx(self) -> DVec4 {
         DVec4::new(self.x, self.y, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xyyy(self) -> DVec4 {
         DVec4::new(self.x, self.y, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xyyz(self) -> DVec4 {
         DVec4::new(self.x, self.y, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xyzx(self) -> DVec4 {
         DVec4::new(self.x, self.y, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xyzy(self) -> DVec4 {
         DVec4::new(self.x, self.y, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xyzz(self) -> DVec4 {
         DVec4::new(self.x, self.y, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xzxx(self) -> DVec4 {
         DVec4::new(self.x, self.z, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xzxy(self) -> DVec4 {
         DVec4::new(self.x, self.z, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xzxz(self) -> DVec4 {
         DVec4::new(self.x, self.z, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xzyx(self) -> DVec4 {
         DVec4::new(self.x, self.z, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xzyy(self) -> DVec4 {
         DVec4::new(self.x, self.z, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xzyz(self) -> DVec4 {
         DVec4::new(self.x, self.z, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xzzx(self) -> DVec4 {
         DVec4::new(self.x, self.z, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xzzy(self) -> DVec4 {
         DVec4::new(self.x, self.z, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xzzz(self) -> DVec4 {
         DVec4::new(self.x, self.z, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yxxx(self) -> DVec4 {
         DVec4::new(self.y, self.x, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yxxy(self) -> DVec4 {
         DVec4::new(self.y, self.x, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yxxz(self) -> DVec4 {
         DVec4::new(self.y, self.x, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yxyx(self) -> DVec4 {
         DVec4::new(self.y, self.x, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yxyy(self) -> DVec4 {
         DVec4::new(self.y, self.x, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yxyz(self) -> DVec4 {
         DVec4::new(self.y, self.x, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yxzx(self) -> DVec4 {
         DVec4::new(self.y, self.x, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yxzy(self) -> DVec4 {
         DVec4::new(self.y, self.x, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yxzz(self) -> DVec4 {
         DVec4::new(self.y, self.x, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yyxx(self) -> DVec4 {
         DVec4::new(self.y, self.y, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yyxy(self) -> DVec4 {
         DVec4::new(self.y, self.y, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yyxz(self) -> DVec4 {
         DVec4::new(self.y, self.y, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yyyx(self) -> DVec4 {
         DVec4::new(self.y, self.y, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yyyy(self) -> DVec4 {
         DVec4::new(self.y, self.y, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yyyz(self) -> DVec4 {
         DVec4::new(self.y, self.y, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yyzx(self) -> DVec4 {
         DVec4::new(self.y, self.y, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yyzy(self) -> DVec4 {
         DVec4::new(self.y, self.y, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yyzz(self) -> DVec4 {
         DVec4::new(self.y, self.y, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yzxx(self) -> DVec4 {
         DVec4::new(self.y, self.z, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yzxy(self) -> DVec4 {
         DVec4::new(self.y, self.z, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yzxz(self) -> DVec4 {
         DVec4::new(self.y, self.z, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yzyx(self) -> DVec4 {
         DVec4::new(self.y, self.z, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yzyy(self) -> DVec4 {
         DVec4::new(self.y, self.z, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yzyz(self) -> DVec4 {
         DVec4::new(self.y, self.z, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yzzx(self) -> DVec4 {
         DVec4::new(self.y, self.z, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yzzy(self) -> DVec4 {
         DVec4::new(self.y, self.z, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yzzz(self) -> DVec4 {
         DVec4::new(self.y, self.z, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zxxx(self) -> DVec4 {
         DVec4::new(self.z, self.x, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zxxy(self) -> DVec4 {
         DVec4::new(self.z, self.x, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zxxz(self) -> DVec4 {
         DVec4::new(self.z, self.x, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zxyx(self) -> DVec4 {
         DVec4::new(self.z, self.x, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zxyy(self) -> DVec4 {
         DVec4::new(self.z, self.x, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zxyz(self) -> DVec4 {
         DVec4::new(self.z, self.x, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zxzx(self) -> DVec4 {
         DVec4::new(self.z, self.x, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zxzy(self) -> DVec4 {
         DVec4::new(self.z, self.x, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zxzz(self) -> DVec4 {
         DVec4::new(self.z, self.x, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zyxx(self) -> DVec4 {
         DVec4::new(self.z, self.y, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zyxy(self) -> DVec4 {
         DVec4::new(self.z, self.y, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zyxz(self) -> DVec4 {
         DVec4::new(self.z, self.y, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zyyx(self) -> DVec4 {
         DVec4::new(self.z, self.y, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zyyy(self) -> DVec4 {
         DVec4::new(self.z, self.y, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zyyz(self) -> DVec4 {
         DVec4::new(self.z, self.y, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zyzx(self) -> DVec4 {
         DVec4::new(self.z, self.y, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zyzy(self) -> DVec4 {
         DVec4::new(self.z, self.y, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zyzz(self) -> DVec4 {
         DVec4::new(self.z, self.y, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zzxx(self) -> DVec4 {
         DVec4::new(self.z, self.z, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zzxy(self) -> DVec4 {
         DVec4::new(self.z, self.z, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zzxz(self) -> DVec4 {
         DVec4::new(self.z, self.z, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zzyx(self) -> DVec4 {
         DVec4::new(self.z, self.z, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zzyy(self) -> DVec4 {
         DVec4::new(self.z, self.z, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zzyz(self) -> DVec4 {
         DVec4::new(self.z, self.z, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zzzx(self) -> DVec4 {
         DVec4::new(self.z, self.z, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zzzy(self) -> DVec4 {
         DVec4::new(self.z, self.z, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zzzz(self) -> DVec4 {
         DVec4::new(self.z, self.z, self.z, self.z)
     }
diff --git a/src/swizzles/dvec4_impl.rs b/src/swizzles/dvec4_impl.rs
index b791ad5..8e23f97 100644
--- a/src/swizzles/dvec4_impl.rs
+++ b/src/swizzles/dvec4_impl.rs
@@ -8,6 +8,7 @@
     type Vec3 = DVec3;
 
     #[inline]
+    #[must_use]
     fn xx(self) -> DVec2 {
         DVec2 {
             x: self.x,
@@ -16,6 +17,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xy(self) -> DVec2 {
         DVec2 {
             x: self.x,
@@ -24,6 +26,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xz(self) -> DVec2 {
         DVec2 {
             x: self.x,
@@ -32,6 +35,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xw(self) -> DVec2 {
         DVec2 {
             x: self.x,
@@ -40,6 +44,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yx(self) -> DVec2 {
         DVec2 {
             x: self.y,
@@ -48,6 +53,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yy(self) -> DVec2 {
         DVec2 {
             x: self.y,
@@ -56,6 +62,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yz(self) -> DVec2 {
         DVec2 {
             x: self.y,
@@ -64,6 +71,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yw(self) -> DVec2 {
         DVec2 {
             x: self.y,
@@ -72,6 +80,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zx(self) -> DVec2 {
         DVec2 {
             x: self.z,
@@ -80,6 +89,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zy(self) -> DVec2 {
         DVec2 {
             x: self.z,
@@ -88,6 +98,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zz(self) -> DVec2 {
         DVec2 {
             x: self.z,
@@ -96,6 +107,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zw(self) -> DVec2 {
         DVec2 {
             x: self.z,
@@ -104,6 +116,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wx(self) -> DVec2 {
         DVec2 {
             x: self.w,
@@ -112,6 +125,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wy(self) -> DVec2 {
         DVec2 {
             x: self.w,
@@ -120,6 +134,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wz(self) -> DVec2 {
         DVec2 {
             x: self.w,
@@ -128,6 +143,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn ww(self) -> DVec2 {
         DVec2 {
             x: self.w,
@@ -136,6 +152,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxx(self) -> DVec3 {
         DVec3 {
             x: self.x,
@@ -145,6 +162,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxy(self) -> DVec3 {
         DVec3 {
             x: self.x,
@@ -154,6 +172,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxz(self) -> DVec3 {
         DVec3 {
             x: self.x,
@@ -163,6 +182,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxw(self) -> DVec3 {
         DVec3 {
             x: self.x,
@@ -172,6 +192,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyx(self) -> DVec3 {
         DVec3 {
             x: self.x,
@@ -181,6 +202,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyy(self) -> DVec3 {
         DVec3 {
             x: self.x,
@@ -190,6 +212,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyz(self) -> DVec3 {
         DVec3 {
             x: self.x,
@@ -199,6 +222,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyw(self) -> DVec3 {
         DVec3 {
             x: self.x,
@@ -208,6 +232,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzx(self) -> DVec3 {
         DVec3 {
             x: self.x,
@@ -217,6 +242,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzy(self) -> DVec3 {
         DVec3 {
             x: self.x,
@@ -226,6 +252,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzz(self) -> DVec3 {
         DVec3 {
             x: self.x,
@@ -235,6 +262,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzw(self) -> DVec3 {
         DVec3 {
             x: self.x,
@@ -244,6 +272,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xwx(self) -> DVec3 {
         DVec3 {
             x: self.x,
@@ -253,6 +282,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xwy(self) -> DVec3 {
         DVec3 {
             x: self.x,
@@ -262,6 +292,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xwz(self) -> DVec3 {
         DVec3 {
             x: self.x,
@@ -271,6 +302,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xww(self) -> DVec3 {
         DVec3 {
             x: self.x,
@@ -280,6 +312,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxx(self) -> DVec3 {
         DVec3 {
             x: self.y,
@@ -289,6 +322,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxy(self) -> DVec3 {
         DVec3 {
             x: self.y,
@@ -298,6 +332,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxz(self) -> DVec3 {
         DVec3 {
             x: self.y,
@@ -307,6 +342,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxw(self) -> DVec3 {
         DVec3 {
             x: self.y,
@@ -316,6 +352,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyx(self) -> DVec3 {
         DVec3 {
             x: self.y,
@@ -325,6 +362,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyy(self) -> DVec3 {
         DVec3 {
             x: self.y,
@@ -334,6 +372,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyz(self) -> DVec3 {
         DVec3 {
             x: self.y,
@@ -343,6 +382,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyw(self) -> DVec3 {
         DVec3 {
             x: self.y,
@@ -352,6 +392,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzx(self) -> DVec3 {
         DVec3 {
             x: self.y,
@@ -361,6 +402,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzy(self) -> DVec3 {
         DVec3 {
             x: self.y,
@@ -370,6 +412,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzz(self) -> DVec3 {
         DVec3 {
             x: self.y,
@@ -379,6 +422,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzw(self) -> DVec3 {
         DVec3 {
             x: self.y,
@@ -388,6 +432,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn ywx(self) -> DVec3 {
         DVec3 {
             x: self.y,
@@ -397,6 +442,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn ywy(self) -> DVec3 {
         DVec3 {
             x: self.y,
@@ -406,6 +452,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn ywz(self) -> DVec3 {
         DVec3 {
             x: self.y,
@@ -415,6 +462,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yww(self) -> DVec3 {
         DVec3 {
             x: self.y,
@@ -424,6 +472,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxx(self) -> DVec3 {
         DVec3 {
             x: self.z,
@@ -433,6 +482,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxy(self) -> DVec3 {
         DVec3 {
             x: self.z,
@@ -442,6 +492,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxz(self) -> DVec3 {
         DVec3 {
             x: self.z,
@@ -451,6 +502,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxw(self) -> DVec3 {
         DVec3 {
             x: self.z,
@@ -460,6 +512,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyx(self) -> DVec3 {
         DVec3 {
             x: self.z,
@@ -469,6 +522,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyy(self) -> DVec3 {
         DVec3 {
             x: self.z,
@@ -478,6 +532,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyz(self) -> DVec3 {
         DVec3 {
             x: self.z,
@@ -487,6 +542,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyw(self) -> DVec3 {
         DVec3 {
             x: self.z,
@@ -496,6 +552,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzx(self) -> DVec3 {
         DVec3 {
             x: self.z,
@@ -505,6 +562,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzy(self) -> DVec3 {
         DVec3 {
             x: self.z,
@@ -514,6 +572,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzz(self) -> DVec3 {
         DVec3 {
             x: self.z,
@@ -523,6 +582,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzw(self) -> DVec3 {
         DVec3 {
             x: self.z,
@@ -532,6 +592,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zwx(self) -> DVec3 {
         DVec3 {
             x: self.z,
@@ -541,6 +602,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zwy(self) -> DVec3 {
         DVec3 {
             x: self.z,
@@ -550,6 +612,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zwz(self) -> DVec3 {
         DVec3 {
             x: self.z,
@@ -559,6 +622,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zww(self) -> DVec3 {
         DVec3 {
             x: self.z,
@@ -568,6 +632,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wxx(self) -> DVec3 {
         DVec3 {
             x: self.w,
@@ -577,6 +642,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wxy(self) -> DVec3 {
         DVec3 {
             x: self.w,
@@ -586,6 +652,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wxz(self) -> DVec3 {
         DVec3 {
             x: self.w,
@@ -595,6 +662,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wxw(self) -> DVec3 {
         DVec3 {
             x: self.w,
@@ -604,6 +672,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wyx(self) -> DVec3 {
         DVec3 {
             x: self.w,
@@ -613,6 +682,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wyy(self) -> DVec3 {
         DVec3 {
             x: self.w,
@@ -622,6 +692,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wyz(self) -> DVec3 {
         DVec3 {
             x: self.w,
@@ -631,6 +702,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wyw(self) -> DVec3 {
         DVec3 {
             x: self.w,
@@ -640,6 +712,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wzx(self) -> DVec3 {
         DVec3 {
             x: self.w,
@@ -649,6 +722,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wzy(self) -> DVec3 {
         DVec3 {
             x: self.w,
@@ -658,6 +732,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wzz(self) -> DVec3 {
         DVec3 {
             x: self.w,
@@ -667,6 +742,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wzw(self) -> DVec3 {
         DVec3 {
             x: self.w,
@@ -676,6 +752,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wwx(self) -> DVec3 {
         DVec3 {
             x: self.w,
@@ -685,6 +762,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wwy(self) -> DVec3 {
         DVec3 {
             x: self.w,
@@ -694,6 +772,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wwz(self) -> DVec3 {
         DVec3 {
             x: self.w,
@@ -703,6 +782,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn www(self) -> DVec3 {
         DVec3 {
             x: self.w,
@@ -712,1281 +792,1537 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxxx(self) -> DVec4 {
         DVec4::new(self.x, self.x, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xxxy(self) -> DVec4 {
         DVec4::new(self.x, self.x, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xxxz(self) -> DVec4 {
         DVec4::new(self.x, self.x, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xxxw(self) -> DVec4 {
         DVec4::new(self.x, self.x, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xxyx(self) -> DVec4 {
         DVec4::new(self.x, self.x, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xxyy(self) -> DVec4 {
         DVec4::new(self.x, self.x, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xxyz(self) -> DVec4 {
         DVec4::new(self.x, self.x, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xxyw(self) -> DVec4 {
         DVec4::new(self.x, self.x, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xxzx(self) -> DVec4 {
         DVec4::new(self.x, self.x, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xxzy(self) -> DVec4 {
         DVec4::new(self.x, self.x, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xxzz(self) -> DVec4 {
         DVec4::new(self.x, self.x, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xxzw(self) -> DVec4 {
         DVec4::new(self.x, self.x, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xxwx(self) -> DVec4 {
         DVec4::new(self.x, self.x, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xxwy(self) -> DVec4 {
         DVec4::new(self.x, self.x, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xxwz(self) -> DVec4 {
         DVec4::new(self.x, self.x, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xxww(self) -> DVec4 {
         DVec4::new(self.x, self.x, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xyxx(self) -> DVec4 {
         DVec4::new(self.x, self.y, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xyxy(self) -> DVec4 {
         DVec4::new(self.x, self.y, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xyxz(self) -> DVec4 {
         DVec4::new(self.x, self.y, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xyxw(self) -> DVec4 {
         DVec4::new(self.x, self.y, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xyyx(self) -> DVec4 {
         DVec4::new(self.x, self.y, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xyyy(self) -> DVec4 {
         DVec4::new(self.x, self.y, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xyyz(self) -> DVec4 {
         DVec4::new(self.x, self.y, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xyyw(self) -> DVec4 {
         DVec4::new(self.x, self.y, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xyzx(self) -> DVec4 {
         DVec4::new(self.x, self.y, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xyzy(self) -> DVec4 {
         DVec4::new(self.x, self.y, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xyzz(self) -> DVec4 {
         DVec4::new(self.x, self.y, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xyzw(self) -> DVec4 {
         DVec4::new(self.x, self.y, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xywx(self) -> DVec4 {
         DVec4::new(self.x, self.y, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xywy(self) -> DVec4 {
         DVec4::new(self.x, self.y, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xywz(self) -> DVec4 {
         DVec4::new(self.x, self.y, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xyww(self) -> DVec4 {
         DVec4::new(self.x, self.y, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xzxx(self) -> DVec4 {
         DVec4::new(self.x, self.z, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xzxy(self) -> DVec4 {
         DVec4::new(self.x, self.z, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xzxz(self) -> DVec4 {
         DVec4::new(self.x, self.z, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xzxw(self) -> DVec4 {
         DVec4::new(self.x, self.z, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xzyx(self) -> DVec4 {
         DVec4::new(self.x, self.z, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xzyy(self) -> DVec4 {
         DVec4::new(self.x, self.z, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xzyz(self) -> DVec4 {
         DVec4::new(self.x, self.z, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xzyw(self) -> DVec4 {
         DVec4::new(self.x, self.z, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xzzx(self) -> DVec4 {
         DVec4::new(self.x, self.z, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xzzy(self) -> DVec4 {
         DVec4::new(self.x, self.z, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xzzz(self) -> DVec4 {
         DVec4::new(self.x, self.z, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xzzw(self) -> DVec4 {
         DVec4::new(self.x, self.z, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xzwx(self) -> DVec4 {
         DVec4::new(self.x, self.z, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xzwy(self) -> DVec4 {
         DVec4::new(self.x, self.z, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xzwz(self) -> DVec4 {
         DVec4::new(self.x, self.z, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xzww(self) -> DVec4 {
         DVec4::new(self.x, self.z, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xwxx(self) -> DVec4 {
         DVec4::new(self.x, self.w, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xwxy(self) -> DVec4 {
         DVec4::new(self.x, self.w, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xwxz(self) -> DVec4 {
         DVec4::new(self.x, self.w, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xwxw(self) -> DVec4 {
         DVec4::new(self.x, self.w, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xwyx(self) -> DVec4 {
         DVec4::new(self.x, self.w, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xwyy(self) -> DVec4 {
         DVec4::new(self.x, self.w, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xwyz(self) -> DVec4 {
         DVec4::new(self.x, self.w, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xwyw(self) -> DVec4 {
         DVec4::new(self.x, self.w, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xwzx(self) -> DVec4 {
         DVec4::new(self.x, self.w, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xwzy(self) -> DVec4 {
         DVec4::new(self.x, self.w, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xwzz(self) -> DVec4 {
         DVec4::new(self.x, self.w, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xwzw(self) -> DVec4 {
         DVec4::new(self.x, self.w, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xwwx(self) -> DVec4 {
         DVec4::new(self.x, self.w, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xwwy(self) -> DVec4 {
         DVec4::new(self.x, self.w, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xwwz(self) -> DVec4 {
         DVec4::new(self.x, self.w, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xwww(self) -> DVec4 {
         DVec4::new(self.x, self.w, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yxxx(self) -> DVec4 {
         DVec4::new(self.y, self.x, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yxxy(self) -> DVec4 {
         DVec4::new(self.y, self.x, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yxxz(self) -> DVec4 {
         DVec4::new(self.y, self.x, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yxxw(self) -> DVec4 {
         DVec4::new(self.y, self.x, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yxyx(self) -> DVec4 {
         DVec4::new(self.y, self.x, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yxyy(self) -> DVec4 {
         DVec4::new(self.y, self.x, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yxyz(self) -> DVec4 {
         DVec4::new(self.y, self.x, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yxyw(self) -> DVec4 {
         DVec4::new(self.y, self.x, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yxzx(self) -> DVec4 {
         DVec4::new(self.y, self.x, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yxzy(self) -> DVec4 {
         DVec4::new(self.y, self.x, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yxzz(self) -> DVec4 {
         DVec4::new(self.y, self.x, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yxzw(self) -> DVec4 {
         DVec4::new(self.y, self.x, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yxwx(self) -> DVec4 {
         DVec4::new(self.y, self.x, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yxwy(self) -> DVec4 {
         DVec4::new(self.y, self.x, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yxwz(self) -> DVec4 {
         DVec4::new(self.y, self.x, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yxww(self) -> DVec4 {
         DVec4::new(self.y, self.x, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yyxx(self) -> DVec4 {
         DVec4::new(self.y, self.y, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yyxy(self) -> DVec4 {
         DVec4::new(self.y, self.y, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yyxz(self) -> DVec4 {
         DVec4::new(self.y, self.y, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yyxw(self) -> DVec4 {
         DVec4::new(self.y, self.y, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yyyx(self) -> DVec4 {
         DVec4::new(self.y, self.y, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yyyy(self) -> DVec4 {
         DVec4::new(self.y, self.y, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yyyz(self) -> DVec4 {
         DVec4::new(self.y, self.y, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yyyw(self) -> DVec4 {
         DVec4::new(self.y, self.y, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yyzx(self) -> DVec4 {
         DVec4::new(self.y, self.y, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yyzy(self) -> DVec4 {
         DVec4::new(self.y, self.y, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yyzz(self) -> DVec4 {
         DVec4::new(self.y, self.y, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yyzw(self) -> DVec4 {
         DVec4::new(self.y, self.y, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yywx(self) -> DVec4 {
         DVec4::new(self.y, self.y, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yywy(self) -> DVec4 {
         DVec4::new(self.y, self.y, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yywz(self) -> DVec4 {
         DVec4::new(self.y, self.y, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yyww(self) -> DVec4 {
         DVec4::new(self.y, self.y, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yzxx(self) -> DVec4 {
         DVec4::new(self.y, self.z, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yzxy(self) -> DVec4 {
         DVec4::new(self.y, self.z, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yzxz(self) -> DVec4 {
         DVec4::new(self.y, self.z, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yzxw(self) -> DVec4 {
         DVec4::new(self.y, self.z, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yzyx(self) -> DVec4 {
         DVec4::new(self.y, self.z, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yzyy(self) -> DVec4 {
         DVec4::new(self.y, self.z, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yzyz(self) -> DVec4 {
         DVec4::new(self.y, self.z, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yzyw(self) -> DVec4 {
         DVec4::new(self.y, self.z, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yzzx(self) -> DVec4 {
         DVec4::new(self.y, self.z, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yzzy(self) -> DVec4 {
         DVec4::new(self.y, self.z, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yzzz(self) -> DVec4 {
         DVec4::new(self.y, self.z, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yzzw(self) -> DVec4 {
         DVec4::new(self.y, self.z, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yzwx(self) -> DVec4 {
         DVec4::new(self.y, self.z, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yzwy(self) -> DVec4 {
         DVec4::new(self.y, self.z, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yzwz(self) -> DVec4 {
         DVec4::new(self.y, self.z, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yzww(self) -> DVec4 {
         DVec4::new(self.y, self.z, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn ywxx(self) -> DVec4 {
         DVec4::new(self.y, self.w, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn ywxy(self) -> DVec4 {
         DVec4::new(self.y, self.w, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn ywxz(self) -> DVec4 {
         DVec4::new(self.y, self.w, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn ywxw(self) -> DVec4 {
         DVec4::new(self.y, self.w, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn ywyx(self) -> DVec4 {
         DVec4::new(self.y, self.w, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn ywyy(self) -> DVec4 {
         DVec4::new(self.y, self.w, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn ywyz(self) -> DVec4 {
         DVec4::new(self.y, self.w, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn ywyw(self) -> DVec4 {
         DVec4::new(self.y, self.w, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn ywzx(self) -> DVec4 {
         DVec4::new(self.y, self.w, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn ywzy(self) -> DVec4 {
         DVec4::new(self.y, self.w, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn ywzz(self) -> DVec4 {
         DVec4::new(self.y, self.w, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn ywzw(self) -> DVec4 {
         DVec4::new(self.y, self.w, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn ywwx(self) -> DVec4 {
         DVec4::new(self.y, self.w, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn ywwy(self) -> DVec4 {
         DVec4::new(self.y, self.w, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn ywwz(self) -> DVec4 {
         DVec4::new(self.y, self.w, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn ywww(self) -> DVec4 {
         DVec4::new(self.y, self.w, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zxxx(self) -> DVec4 {
         DVec4::new(self.z, self.x, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zxxy(self) -> DVec4 {
         DVec4::new(self.z, self.x, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zxxz(self) -> DVec4 {
         DVec4::new(self.z, self.x, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zxxw(self) -> DVec4 {
         DVec4::new(self.z, self.x, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zxyx(self) -> DVec4 {
         DVec4::new(self.z, self.x, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zxyy(self) -> DVec4 {
         DVec4::new(self.z, self.x, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zxyz(self) -> DVec4 {
         DVec4::new(self.z, self.x, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zxyw(self) -> DVec4 {
         DVec4::new(self.z, self.x, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zxzx(self) -> DVec4 {
         DVec4::new(self.z, self.x, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zxzy(self) -> DVec4 {
         DVec4::new(self.z, self.x, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zxzz(self) -> DVec4 {
         DVec4::new(self.z, self.x, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zxzw(self) -> DVec4 {
         DVec4::new(self.z, self.x, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zxwx(self) -> DVec4 {
         DVec4::new(self.z, self.x, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zxwy(self) -> DVec4 {
         DVec4::new(self.z, self.x, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zxwz(self) -> DVec4 {
         DVec4::new(self.z, self.x, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zxww(self) -> DVec4 {
         DVec4::new(self.z, self.x, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zyxx(self) -> DVec4 {
         DVec4::new(self.z, self.y, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zyxy(self) -> DVec4 {
         DVec4::new(self.z, self.y, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zyxz(self) -> DVec4 {
         DVec4::new(self.z, self.y, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zyxw(self) -> DVec4 {
         DVec4::new(self.z, self.y, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zyyx(self) -> DVec4 {
         DVec4::new(self.z, self.y, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zyyy(self) -> DVec4 {
         DVec4::new(self.z, self.y, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zyyz(self) -> DVec4 {
         DVec4::new(self.z, self.y, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zyyw(self) -> DVec4 {
         DVec4::new(self.z, self.y, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zyzx(self) -> DVec4 {
         DVec4::new(self.z, self.y, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zyzy(self) -> DVec4 {
         DVec4::new(self.z, self.y, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zyzz(self) -> DVec4 {
         DVec4::new(self.z, self.y, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zyzw(self) -> DVec4 {
         DVec4::new(self.z, self.y, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zywx(self) -> DVec4 {
         DVec4::new(self.z, self.y, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zywy(self) -> DVec4 {
         DVec4::new(self.z, self.y, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zywz(self) -> DVec4 {
         DVec4::new(self.z, self.y, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zyww(self) -> DVec4 {
         DVec4::new(self.z, self.y, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zzxx(self) -> DVec4 {
         DVec4::new(self.z, self.z, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zzxy(self) -> DVec4 {
         DVec4::new(self.z, self.z, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zzxz(self) -> DVec4 {
         DVec4::new(self.z, self.z, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zzxw(self) -> DVec4 {
         DVec4::new(self.z, self.z, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zzyx(self) -> DVec4 {
         DVec4::new(self.z, self.z, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zzyy(self) -> DVec4 {
         DVec4::new(self.z, self.z, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zzyz(self) -> DVec4 {
         DVec4::new(self.z, self.z, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zzyw(self) -> DVec4 {
         DVec4::new(self.z, self.z, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zzzx(self) -> DVec4 {
         DVec4::new(self.z, self.z, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zzzy(self) -> DVec4 {
         DVec4::new(self.z, self.z, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zzzz(self) -> DVec4 {
         DVec4::new(self.z, self.z, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zzzw(self) -> DVec4 {
         DVec4::new(self.z, self.z, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zzwx(self) -> DVec4 {
         DVec4::new(self.z, self.z, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zzwy(self) -> DVec4 {
         DVec4::new(self.z, self.z, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zzwz(self) -> DVec4 {
         DVec4::new(self.z, self.z, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zzww(self) -> DVec4 {
         DVec4::new(self.z, self.z, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zwxx(self) -> DVec4 {
         DVec4::new(self.z, self.w, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zwxy(self) -> DVec4 {
         DVec4::new(self.z, self.w, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zwxz(self) -> DVec4 {
         DVec4::new(self.z, self.w, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zwxw(self) -> DVec4 {
         DVec4::new(self.z, self.w, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zwyx(self) -> DVec4 {
         DVec4::new(self.z, self.w, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zwyy(self) -> DVec4 {
         DVec4::new(self.z, self.w, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zwyz(self) -> DVec4 {
         DVec4::new(self.z, self.w, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zwyw(self) -> DVec4 {
         DVec4::new(self.z, self.w, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zwzx(self) -> DVec4 {
         DVec4::new(self.z, self.w, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zwzy(self) -> DVec4 {
         DVec4::new(self.z, self.w, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zwzz(self) -> DVec4 {
         DVec4::new(self.z, self.w, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zwzw(self) -> DVec4 {
         DVec4::new(self.z, self.w, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zwwx(self) -> DVec4 {
         DVec4::new(self.z, self.w, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zwwy(self) -> DVec4 {
         DVec4::new(self.z, self.w, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zwwz(self) -> DVec4 {
         DVec4::new(self.z, self.w, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zwww(self) -> DVec4 {
         DVec4::new(self.z, self.w, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wxxx(self) -> DVec4 {
         DVec4::new(self.w, self.x, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wxxy(self) -> DVec4 {
         DVec4::new(self.w, self.x, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wxxz(self) -> DVec4 {
         DVec4::new(self.w, self.x, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wxxw(self) -> DVec4 {
         DVec4::new(self.w, self.x, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wxyx(self) -> DVec4 {
         DVec4::new(self.w, self.x, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wxyy(self) -> DVec4 {
         DVec4::new(self.w, self.x, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wxyz(self) -> DVec4 {
         DVec4::new(self.w, self.x, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wxyw(self) -> DVec4 {
         DVec4::new(self.w, self.x, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wxzx(self) -> DVec4 {
         DVec4::new(self.w, self.x, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wxzy(self) -> DVec4 {
         DVec4::new(self.w, self.x, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wxzz(self) -> DVec4 {
         DVec4::new(self.w, self.x, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wxzw(self) -> DVec4 {
         DVec4::new(self.w, self.x, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wxwx(self) -> DVec4 {
         DVec4::new(self.w, self.x, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wxwy(self) -> DVec4 {
         DVec4::new(self.w, self.x, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wxwz(self) -> DVec4 {
         DVec4::new(self.w, self.x, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wxww(self) -> DVec4 {
         DVec4::new(self.w, self.x, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wyxx(self) -> DVec4 {
         DVec4::new(self.w, self.y, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wyxy(self) -> DVec4 {
         DVec4::new(self.w, self.y, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wyxz(self) -> DVec4 {
         DVec4::new(self.w, self.y, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wyxw(self) -> DVec4 {
         DVec4::new(self.w, self.y, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wyyx(self) -> DVec4 {
         DVec4::new(self.w, self.y, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wyyy(self) -> DVec4 {
         DVec4::new(self.w, self.y, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wyyz(self) -> DVec4 {
         DVec4::new(self.w, self.y, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wyyw(self) -> DVec4 {
         DVec4::new(self.w, self.y, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wyzx(self) -> DVec4 {
         DVec4::new(self.w, self.y, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wyzy(self) -> DVec4 {
         DVec4::new(self.w, self.y, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wyzz(self) -> DVec4 {
         DVec4::new(self.w, self.y, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wyzw(self) -> DVec4 {
         DVec4::new(self.w, self.y, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wywx(self) -> DVec4 {
         DVec4::new(self.w, self.y, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wywy(self) -> DVec4 {
         DVec4::new(self.w, self.y, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wywz(self) -> DVec4 {
         DVec4::new(self.w, self.y, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wyww(self) -> DVec4 {
         DVec4::new(self.w, self.y, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wzxx(self) -> DVec4 {
         DVec4::new(self.w, self.z, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wzxy(self) -> DVec4 {
         DVec4::new(self.w, self.z, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wzxz(self) -> DVec4 {
         DVec4::new(self.w, self.z, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wzxw(self) -> DVec4 {
         DVec4::new(self.w, self.z, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wzyx(self) -> DVec4 {
         DVec4::new(self.w, self.z, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wzyy(self) -> DVec4 {
         DVec4::new(self.w, self.z, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wzyz(self) -> DVec4 {
         DVec4::new(self.w, self.z, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wzyw(self) -> DVec4 {
         DVec4::new(self.w, self.z, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wzzx(self) -> DVec4 {
         DVec4::new(self.w, self.z, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wzzy(self) -> DVec4 {
         DVec4::new(self.w, self.z, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wzzz(self) -> DVec4 {
         DVec4::new(self.w, self.z, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wzzw(self) -> DVec4 {
         DVec4::new(self.w, self.z, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wzwx(self) -> DVec4 {
         DVec4::new(self.w, self.z, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wzwy(self) -> DVec4 {
         DVec4::new(self.w, self.z, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wzwz(self) -> DVec4 {
         DVec4::new(self.w, self.z, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wzww(self) -> DVec4 {
         DVec4::new(self.w, self.z, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wwxx(self) -> DVec4 {
         DVec4::new(self.w, self.w, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wwxy(self) -> DVec4 {
         DVec4::new(self.w, self.w, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wwxz(self) -> DVec4 {
         DVec4::new(self.w, self.w, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wwxw(self) -> DVec4 {
         DVec4::new(self.w, self.w, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wwyx(self) -> DVec4 {
         DVec4::new(self.w, self.w, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wwyy(self) -> DVec4 {
         DVec4::new(self.w, self.w, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wwyz(self) -> DVec4 {
         DVec4::new(self.w, self.w, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wwyw(self) -> DVec4 {
         DVec4::new(self.w, self.w, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wwzx(self) -> DVec4 {
         DVec4::new(self.w, self.w, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wwzy(self) -> DVec4 {
         DVec4::new(self.w, self.w, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wwzz(self) -> DVec4 {
         DVec4::new(self.w, self.w, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wwzw(self) -> DVec4 {
         DVec4::new(self.w, self.w, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wwwx(self) -> DVec4 {
         DVec4::new(self.w, self.w, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wwwy(self) -> DVec4 {
         DVec4::new(self.w, self.w, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wwwz(self) -> DVec4 {
         DVec4::new(self.w, self.w, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wwww(self) -> DVec4 {
         DVec4::new(self.w, self.w, self.w, self.w)
     }
diff --git a/src/swizzles/i16vec2_impl.rs b/src/swizzles/i16vec2_impl.rs
new file mode 100644
index 0000000..23445e5
--- /dev/null
+++ b/src/swizzles/i16vec2_impl.rs
@@ -0,0 +1,221 @@
+// Generated from swizzle_impl.rs.tera template. Edit the template, not the generated file.
+
+use crate::{I16Vec2, I16Vec3, I16Vec4, Vec2Swizzles};
+
+impl Vec2Swizzles for I16Vec2 {
+    type Vec3 = I16Vec3;
+
+    type Vec4 = I16Vec4;
+
+    #[inline]
+    #[must_use]
+    fn xx(self) -> I16Vec2 {
+        I16Vec2 {
+            x: self.x,
+            y: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xy(self) -> I16Vec2 {
+        I16Vec2 {
+            x: self.x,
+            y: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yx(self) -> I16Vec2 {
+        I16Vec2 {
+            x: self.y,
+            y: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yy(self) -> I16Vec2 {
+        I16Vec2 {
+            x: self.y,
+            y: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxx(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.x,
+            y: self.x,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxy(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.x,
+            y: self.x,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyx(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.x,
+            y: self.y,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyy(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.x,
+            y: self.y,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxx(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.y,
+            y: self.x,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxy(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.y,
+            y: self.x,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyx(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.y,
+            y: self.y,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyy(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.y,
+            y: self.y,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxxx(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.x, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxxy(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.x, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxyx(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.x, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxyy(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.x, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyxx(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.y, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyxy(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.y, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyyx(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.y, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyyy(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.y, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxxx(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.x, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxxy(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.x, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxyx(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.x, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxyy(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.x, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyxx(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.y, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyxy(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.y, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyyx(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.y, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyyy(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.y, self.y, self.y)
+    }
+}
diff --git a/src/swizzles/i16vec3_impl.rs b/src/swizzles/i16vec3_impl.rs
new file mode 100644
index 0000000..9d33df0
--- /dev/null
+++ b/src/swizzles/i16vec3_impl.rs
@@ -0,0 +1,846 @@
+// Generated from swizzle_impl.rs.tera template. Edit the template, not the generated file.
+
+use crate::{I16Vec2, I16Vec3, I16Vec4, Vec3Swizzles};
+
+impl Vec3Swizzles for I16Vec3 {
+    type Vec2 = I16Vec2;
+
+    type Vec4 = I16Vec4;
+
+    #[inline]
+    #[must_use]
+    fn xx(self) -> I16Vec2 {
+        I16Vec2 {
+            x: self.x,
+            y: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xy(self) -> I16Vec2 {
+        I16Vec2 {
+            x: self.x,
+            y: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xz(self) -> I16Vec2 {
+        I16Vec2 {
+            x: self.x,
+            y: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yx(self) -> I16Vec2 {
+        I16Vec2 {
+            x: self.y,
+            y: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yy(self) -> I16Vec2 {
+        I16Vec2 {
+            x: self.y,
+            y: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yz(self) -> I16Vec2 {
+        I16Vec2 {
+            x: self.y,
+            y: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zx(self) -> I16Vec2 {
+        I16Vec2 {
+            x: self.z,
+            y: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zy(self) -> I16Vec2 {
+        I16Vec2 {
+            x: self.z,
+            y: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zz(self) -> I16Vec2 {
+        I16Vec2 {
+            x: self.z,
+            y: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxx(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.x,
+            y: self.x,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxy(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.x,
+            y: self.x,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxz(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.x,
+            y: self.x,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyx(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.x,
+            y: self.y,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyy(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.x,
+            y: self.y,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyz(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.x,
+            y: self.y,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzx(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.x,
+            y: self.z,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzy(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.x,
+            y: self.z,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzz(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.x,
+            y: self.z,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxx(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.y,
+            y: self.x,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxy(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.y,
+            y: self.x,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxz(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.y,
+            y: self.x,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyx(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.y,
+            y: self.y,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyy(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.y,
+            y: self.y,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyz(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.y,
+            y: self.y,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzx(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.y,
+            y: self.z,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzy(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.y,
+            y: self.z,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzz(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.y,
+            y: self.z,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxx(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.z,
+            y: self.x,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxy(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.z,
+            y: self.x,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxz(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.z,
+            y: self.x,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyx(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.z,
+            y: self.y,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyy(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.z,
+            y: self.y,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyz(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.z,
+            y: self.y,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzx(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.z,
+            y: self.z,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzy(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.z,
+            y: self.z,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzz(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.z,
+            y: self.z,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxxx(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.x, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxxy(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.x, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxxz(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.x, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxyx(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.x, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxyy(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.x, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxyz(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.x, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxzx(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.x, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxzy(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.x, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxzz(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.x, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyxx(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.y, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyxy(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.y, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyxz(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.y, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyyx(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.y, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyyy(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.y, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyyz(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.y, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyzx(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.y, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyzy(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.y, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyzz(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.y, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzxx(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.z, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzxy(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.z, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzxz(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.z, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzyx(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.z, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzyy(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.z, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzyz(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.z, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzzx(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.z, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzzy(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.z, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzzz(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.z, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxxx(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.x, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxxy(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.x, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxxz(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.x, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxyx(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.x, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxyy(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.x, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxyz(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.x, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxzx(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.x, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxzy(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.x, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxzz(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.x, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyxx(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.y, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyxy(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.y, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyxz(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.y, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyyx(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.y, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyyy(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.y, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyyz(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.y, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyzx(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.y, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyzy(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.y, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyzz(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.y, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzxx(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.z, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzxy(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.z, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzxz(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.z, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzyx(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.z, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzyy(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.z, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzyz(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.z, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzzx(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.z, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzzy(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.z, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzzz(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.z, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxxx(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.x, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxxy(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.x, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxxz(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.x, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxyx(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.x, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxyy(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.x, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxyz(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.x, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxzx(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.x, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxzy(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.x, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxzz(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.x, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyxx(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.y, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyxy(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.y, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyxz(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.y, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyyx(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.y, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyyy(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.y, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyyz(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.y, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyzx(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.y, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyzy(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.y, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyzz(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.y, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzxx(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.z, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzxy(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.z, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzxz(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.z, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzyx(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.z, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzyy(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.z, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzyz(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.z, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzzx(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.z, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzzy(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.z, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzzz(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.z, self.z, self.z)
+    }
+}
diff --git a/src/swizzles/i16vec4_impl.rs b/src/swizzles/i16vec4_impl.rs
new file mode 100644
index 0000000..6bf4246
--- /dev/null
+++ b/src/swizzles/i16vec4_impl.rs
@@ -0,0 +1,2329 @@
+// Generated from swizzle_impl.rs.tera template. Edit the template, not the generated file.
+
+use crate::{I16Vec2, I16Vec3, I16Vec4, Vec4Swizzles};
+
+impl Vec4Swizzles for I16Vec4 {
+    type Vec2 = I16Vec2;
+
+    type Vec3 = I16Vec3;
+
+    #[inline]
+    #[must_use]
+    fn xx(self) -> I16Vec2 {
+        I16Vec2 {
+            x: self.x,
+            y: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xy(self) -> I16Vec2 {
+        I16Vec2 {
+            x: self.x,
+            y: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xz(self) -> I16Vec2 {
+        I16Vec2 {
+            x: self.x,
+            y: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xw(self) -> I16Vec2 {
+        I16Vec2 {
+            x: self.x,
+            y: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yx(self) -> I16Vec2 {
+        I16Vec2 {
+            x: self.y,
+            y: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yy(self) -> I16Vec2 {
+        I16Vec2 {
+            x: self.y,
+            y: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yz(self) -> I16Vec2 {
+        I16Vec2 {
+            x: self.y,
+            y: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yw(self) -> I16Vec2 {
+        I16Vec2 {
+            x: self.y,
+            y: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zx(self) -> I16Vec2 {
+        I16Vec2 {
+            x: self.z,
+            y: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zy(self) -> I16Vec2 {
+        I16Vec2 {
+            x: self.z,
+            y: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zz(self) -> I16Vec2 {
+        I16Vec2 {
+            x: self.z,
+            y: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zw(self) -> I16Vec2 {
+        I16Vec2 {
+            x: self.z,
+            y: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wx(self) -> I16Vec2 {
+        I16Vec2 {
+            x: self.w,
+            y: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wy(self) -> I16Vec2 {
+        I16Vec2 {
+            x: self.w,
+            y: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wz(self) -> I16Vec2 {
+        I16Vec2 {
+            x: self.w,
+            y: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn ww(self) -> I16Vec2 {
+        I16Vec2 {
+            x: self.w,
+            y: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxx(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.x,
+            y: self.x,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxy(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.x,
+            y: self.x,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxz(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.x,
+            y: self.x,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxw(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.x,
+            y: self.x,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyx(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.x,
+            y: self.y,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyy(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.x,
+            y: self.y,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyz(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.x,
+            y: self.y,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyw(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.x,
+            y: self.y,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzx(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.x,
+            y: self.z,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzy(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.x,
+            y: self.z,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzz(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.x,
+            y: self.z,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzw(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.x,
+            y: self.z,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwx(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.x,
+            y: self.w,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwy(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.x,
+            y: self.w,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwz(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.x,
+            y: self.w,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xww(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.x,
+            y: self.w,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxx(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.y,
+            y: self.x,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxy(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.y,
+            y: self.x,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxz(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.y,
+            y: self.x,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxw(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.y,
+            y: self.x,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyx(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.y,
+            y: self.y,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyy(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.y,
+            y: self.y,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyz(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.y,
+            y: self.y,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyw(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.y,
+            y: self.y,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzx(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.y,
+            y: self.z,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzy(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.y,
+            y: self.z,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzz(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.y,
+            y: self.z,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzw(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.y,
+            y: self.z,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywx(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.y,
+            y: self.w,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywy(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.y,
+            y: self.w,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywz(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.y,
+            y: self.w,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yww(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.y,
+            y: self.w,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxx(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.z,
+            y: self.x,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxy(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.z,
+            y: self.x,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxz(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.z,
+            y: self.x,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxw(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.z,
+            y: self.x,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyx(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.z,
+            y: self.y,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyy(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.z,
+            y: self.y,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyz(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.z,
+            y: self.y,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyw(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.z,
+            y: self.y,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzx(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.z,
+            y: self.z,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzy(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.z,
+            y: self.z,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzz(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.z,
+            y: self.z,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzw(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.z,
+            y: self.z,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwx(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.z,
+            y: self.w,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwy(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.z,
+            y: self.w,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwz(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.z,
+            y: self.w,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zww(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.z,
+            y: self.w,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxx(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.w,
+            y: self.x,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxy(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.w,
+            y: self.x,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxz(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.w,
+            y: self.x,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxw(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.w,
+            y: self.x,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyx(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.w,
+            y: self.y,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyy(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.w,
+            y: self.y,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyz(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.w,
+            y: self.y,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyw(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.w,
+            y: self.y,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzx(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.w,
+            y: self.z,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzy(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.w,
+            y: self.z,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzz(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.w,
+            y: self.z,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzw(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.w,
+            y: self.z,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwx(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.w,
+            y: self.w,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwy(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.w,
+            y: self.w,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwz(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.w,
+            y: self.w,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn www(self) -> I16Vec3 {
+        I16Vec3 {
+            x: self.w,
+            y: self.w,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxxx(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.x, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxxy(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.x, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxxz(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.x, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxxw(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.x, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxyx(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.x, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxyy(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.x, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxyz(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.x, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxyw(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.x, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxzx(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.x, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxzy(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.x, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxzz(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.x, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxzw(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.x, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxwx(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.x, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxwy(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.x, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxwz(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.x, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxww(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.x, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyxx(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.y, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyxy(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.y, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyxz(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.y, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyxw(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.y, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyyx(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.y, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyyy(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.y, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyyz(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.y, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyyw(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.y, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyzx(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.y, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyzy(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.y, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyzz(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.y, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyzw(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.y, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xywx(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.y, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xywy(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.y, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xywz(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.y, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyww(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.y, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzxx(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.z, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzxy(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.z, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzxz(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.z, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzxw(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.z, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzyx(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.z, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzyy(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.z, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzyz(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.z, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzyw(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.z, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzzx(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.z, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzzy(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.z, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzzz(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.z, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzzw(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.z, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzwx(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.z, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzwy(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.z, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzwz(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.z, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzww(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.z, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwxx(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.w, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwxy(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.w, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwxz(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.w, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwxw(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.w, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwyx(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.w, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwyy(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.w, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwyz(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.w, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwyw(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.w, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwzx(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.w, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwzy(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.w, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwzz(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.w, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwzw(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.w, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwwx(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.w, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwwy(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.w, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwwz(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.w, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwww(self) -> I16Vec4 {
+        I16Vec4::new(self.x, self.w, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxxx(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.x, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxxy(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.x, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxxz(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.x, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxxw(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.x, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxyx(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.x, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxyy(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.x, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxyz(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.x, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxyw(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.x, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxzx(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.x, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxzy(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.x, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxzz(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.x, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxzw(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.x, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxwx(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.x, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxwy(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.x, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxwz(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.x, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxww(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.x, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyxx(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.y, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyxy(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.y, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyxz(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.y, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyxw(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.y, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyyx(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.y, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyyy(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.y, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyyz(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.y, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyyw(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.y, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyzx(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.y, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyzy(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.y, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyzz(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.y, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyzw(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.y, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yywx(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.y, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yywy(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.y, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yywz(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.y, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyww(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.y, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzxx(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.z, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzxy(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.z, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzxz(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.z, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzxw(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.z, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzyx(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.z, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzyy(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.z, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzyz(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.z, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzyw(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.z, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzzx(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.z, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzzy(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.z, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzzz(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.z, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzzw(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.z, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzwx(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.z, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzwy(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.z, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzwz(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.z, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzww(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.z, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywxx(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.w, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywxy(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.w, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywxz(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.w, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywxw(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.w, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywyx(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.w, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywyy(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.w, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywyz(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.w, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywyw(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.w, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywzx(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.w, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywzy(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.w, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywzz(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.w, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywzw(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.w, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywwx(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.w, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywwy(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.w, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywwz(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.w, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywww(self) -> I16Vec4 {
+        I16Vec4::new(self.y, self.w, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxxx(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.x, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxxy(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.x, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxxz(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.x, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxxw(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.x, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxyx(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.x, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxyy(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.x, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxyz(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.x, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxyw(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.x, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxzx(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.x, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxzy(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.x, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxzz(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.x, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxzw(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.x, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxwx(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.x, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxwy(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.x, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxwz(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.x, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxww(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.x, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyxx(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.y, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyxy(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.y, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyxz(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.y, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyxw(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.y, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyyx(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.y, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyyy(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.y, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyyz(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.y, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyyw(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.y, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyzx(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.y, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyzy(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.y, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyzz(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.y, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyzw(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.y, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zywx(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.y, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zywy(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.y, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zywz(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.y, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyww(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.y, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzxx(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.z, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzxy(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.z, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzxz(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.z, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzxw(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.z, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzyx(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.z, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzyy(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.z, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzyz(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.z, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzyw(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.z, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzzx(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.z, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzzy(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.z, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzzz(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.z, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzzw(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.z, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzwx(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.z, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzwy(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.z, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzwz(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.z, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzww(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.z, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwxx(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.w, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwxy(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.w, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwxz(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.w, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwxw(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.w, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwyx(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.w, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwyy(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.w, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwyz(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.w, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwyw(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.w, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwzx(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.w, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwzy(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.w, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwzz(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.w, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwzw(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.w, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwwx(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.w, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwwy(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.w, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwwz(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.w, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwww(self) -> I16Vec4 {
+        I16Vec4::new(self.z, self.w, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxxx(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.x, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxxy(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.x, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxxz(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.x, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxxw(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.x, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxyx(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.x, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxyy(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.x, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxyz(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.x, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxyw(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.x, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxzx(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.x, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxzy(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.x, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxzz(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.x, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxzw(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.x, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxwx(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.x, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxwy(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.x, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxwz(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.x, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxww(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.x, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyxx(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.y, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyxy(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.y, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyxz(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.y, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyxw(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.y, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyyx(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.y, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyyy(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.y, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyyz(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.y, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyyw(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.y, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyzx(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.y, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyzy(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.y, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyzz(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.y, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyzw(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.y, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wywx(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.y, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wywy(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.y, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wywz(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.y, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyww(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.y, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzxx(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.z, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzxy(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.z, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzxz(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.z, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzxw(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.z, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzyx(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.z, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzyy(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.z, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzyz(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.z, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzyw(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.z, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzzx(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.z, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzzy(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.z, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzzz(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.z, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzzw(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.z, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzwx(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.z, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzwy(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.z, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzwz(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.z, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzww(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.z, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwxx(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.w, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwxy(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.w, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwxz(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.w, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwxw(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.w, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwyx(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.w, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwyy(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.w, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwyz(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.w, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwyw(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.w, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwzx(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.w, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwzy(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.w, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwzz(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.w, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwzw(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.w, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwwx(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.w, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwwy(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.w, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwwz(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.w, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwww(self) -> I16Vec4 {
+        I16Vec4::new(self.w, self.w, self.w, self.w)
+    }
+}
diff --git a/src/swizzles/i64vec2_impl.rs b/src/swizzles/i64vec2_impl.rs
new file mode 100644
index 0000000..99c3e19
--- /dev/null
+++ b/src/swizzles/i64vec2_impl.rs
@@ -0,0 +1,221 @@
+// Generated from swizzle_impl.rs.tera template. Edit the template, not the generated file.
+
+use crate::{I64Vec2, I64Vec3, I64Vec4, Vec2Swizzles};
+
+impl Vec2Swizzles for I64Vec2 {
+    type Vec3 = I64Vec3;
+
+    type Vec4 = I64Vec4;
+
+    #[inline]
+    #[must_use]
+    fn xx(self) -> I64Vec2 {
+        I64Vec2 {
+            x: self.x,
+            y: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xy(self) -> I64Vec2 {
+        I64Vec2 {
+            x: self.x,
+            y: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yx(self) -> I64Vec2 {
+        I64Vec2 {
+            x: self.y,
+            y: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yy(self) -> I64Vec2 {
+        I64Vec2 {
+            x: self.y,
+            y: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxx(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.x,
+            y: self.x,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxy(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.x,
+            y: self.x,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyx(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.x,
+            y: self.y,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyy(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.x,
+            y: self.y,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxx(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.y,
+            y: self.x,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxy(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.y,
+            y: self.x,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyx(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.y,
+            y: self.y,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyy(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.y,
+            y: self.y,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxxx(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.x, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxxy(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.x, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxyx(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.x, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxyy(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.x, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyxx(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.y, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyxy(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.y, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyyx(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.y, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyyy(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.y, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxxx(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.x, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxxy(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.x, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxyx(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.x, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxyy(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.x, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyxx(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.y, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyxy(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.y, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyyx(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.y, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyyy(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.y, self.y, self.y)
+    }
+}
diff --git a/src/swizzles/i64vec3_impl.rs b/src/swizzles/i64vec3_impl.rs
new file mode 100644
index 0000000..30d8ccc
--- /dev/null
+++ b/src/swizzles/i64vec3_impl.rs
@@ -0,0 +1,846 @@
+// Generated from swizzle_impl.rs.tera template. Edit the template, not the generated file.
+
+use crate::{I64Vec2, I64Vec3, I64Vec4, Vec3Swizzles};
+
+impl Vec3Swizzles for I64Vec3 {
+    type Vec2 = I64Vec2;
+
+    type Vec4 = I64Vec4;
+
+    #[inline]
+    #[must_use]
+    fn xx(self) -> I64Vec2 {
+        I64Vec2 {
+            x: self.x,
+            y: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xy(self) -> I64Vec2 {
+        I64Vec2 {
+            x: self.x,
+            y: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xz(self) -> I64Vec2 {
+        I64Vec2 {
+            x: self.x,
+            y: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yx(self) -> I64Vec2 {
+        I64Vec2 {
+            x: self.y,
+            y: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yy(self) -> I64Vec2 {
+        I64Vec2 {
+            x: self.y,
+            y: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yz(self) -> I64Vec2 {
+        I64Vec2 {
+            x: self.y,
+            y: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zx(self) -> I64Vec2 {
+        I64Vec2 {
+            x: self.z,
+            y: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zy(self) -> I64Vec2 {
+        I64Vec2 {
+            x: self.z,
+            y: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zz(self) -> I64Vec2 {
+        I64Vec2 {
+            x: self.z,
+            y: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxx(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.x,
+            y: self.x,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxy(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.x,
+            y: self.x,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxz(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.x,
+            y: self.x,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyx(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.x,
+            y: self.y,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyy(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.x,
+            y: self.y,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyz(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.x,
+            y: self.y,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzx(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.x,
+            y: self.z,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzy(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.x,
+            y: self.z,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzz(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.x,
+            y: self.z,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxx(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.y,
+            y: self.x,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxy(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.y,
+            y: self.x,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxz(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.y,
+            y: self.x,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyx(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.y,
+            y: self.y,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyy(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.y,
+            y: self.y,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyz(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.y,
+            y: self.y,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzx(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.y,
+            y: self.z,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzy(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.y,
+            y: self.z,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzz(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.y,
+            y: self.z,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxx(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.z,
+            y: self.x,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxy(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.z,
+            y: self.x,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxz(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.z,
+            y: self.x,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyx(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.z,
+            y: self.y,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyy(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.z,
+            y: self.y,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyz(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.z,
+            y: self.y,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzx(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.z,
+            y: self.z,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzy(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.z,
+            y: self.z,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzz(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.z,
+            y: self.z,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxxx(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.x, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxxy(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.x, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxxz(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.x, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxyx(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.x, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxyy(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.x, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxyz(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.x, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxzx(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.x, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxzy(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.x, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxzz(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.x, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyxx(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.y, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyxy(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.y, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyxz(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.y, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyyx(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.y, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyyy(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.y, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyyz(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.y, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyzx(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.y, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyzy(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.y, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyzz(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.y, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzxx(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.z, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzxy(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.z, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzxz(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.z, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzyx(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.z, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzyy(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.z, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzyz(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.z, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzzx(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.z, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzzy(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.z, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzzz(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.z, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxxx(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.x, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxxy(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.x, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxxz(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.x, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxyx(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.x, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxyy(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.x, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxyz(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.x, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxzx(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.x, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxzy(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.x, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxzz(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.x, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyxx(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.y, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyxy(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.y, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyxz(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.y, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyyx(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.y, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyyy(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.y, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyyz(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.y, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyzx(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.y, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyzy(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.y, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyzz(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.y, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzxx(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.z, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzxy(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.z, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzxz(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.z, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzyx(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.z, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzyy(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.z, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzyz(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.z, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzzx(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.z, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzzy(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.z, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzzz(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.z, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxxx(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.x, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxxy(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.x, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxxz(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.x, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxyx(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.x, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxyy(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.x, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxyz(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.x, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxzx(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.x, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxzy(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.x, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxzz(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.x, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyxx(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.y, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyxy(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.y, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyxz(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.y, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyyx(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.y, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyyy(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.y, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyyz(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.y, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyzx(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.y, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyzy(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.y, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyzz(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.y, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzxx(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.z, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzxy(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.z, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzxz(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.z, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzyx(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.z, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzyy(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.z, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzyz(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.z, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzzx(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.z, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzzy(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.z, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzzz(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.z, self.z, self.z)
+    }
+}
diff --git a/src/swizzles/i64vec4_impl.rs b/src/swizzles/i64vec4_impl.rs
new file mode 100644
index 0000000..8dcbca9
--- /dev/null
+++ b/src/swizzles/i64vec4_impl.rs
@@ -0,0 +1,2329 @@
+// Generated from swizzle_impl.rs.tera template. Edit the template, not the generated file.
+
+use crate::{I64Vec2, I64Vec3, I64Vec4, Vec4Swizzles};
+
+impl Vec4Swizzles for I64Vec4 {
+    type Vec2 = I64Vec2;
+
+    type Vec3 = I64Vec3;
+
+    #[inline]
+    #[must_use]
+    fn xx(self) -> I64Vec2 {
+        I64Vec2 {
+            x: self.x,
+            y: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xy(self) -> I64Vec2 {
+        I64Vec2 {
+            x: self.x,
+            y: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xz(self) -> I64Vec2 {
+        I64Vec2 {
+            x: self.x,
+            y: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xw(self) -> I64Vec2 {
+        I64Vec2 {
+            x: self.x,
+            y: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yx(self) -> I64Vec2 {
+        I64Vec2 {
+            x: self.y,
+            y: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yy(self) -> I64Vec2 {
+        I64Vec2 {
+            x: self.y,
+            y: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yz(self) -> I64Vec2 {
+        I64Vec2 {
+            x: self.y,
+            y: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yw(self) -> I64Vec2 {
+        I64Vec2 {
+            x: self.y,
+            y: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zx(self) -> I64Vec2 {
+        I64Vec2 {
+            x: self.z,
+            y: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zy(self) -> I64Vec2 {
+        I64Vec2 {
+            x: self.z,
+            y: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zz(self) -> I64Vec2 {
+        I64Vec2 {
+            x: self.z,
+            y: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zw(self) -> I64Vec2 {
+        I64Vec2 {
+            x: self.z,
+            y: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wx(self) -> I64Vec2 {
+        I64Vec2 {
+            x: self.w,
+            y: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wy(self) -> I64Vec2 {
+        I64Vec2 {
+            x: self.w,
+            y: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wz(self) -> I64Vec2 {
+        I64Vec2 {
+            x: self.w,
+            y: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn ww(self) -> I64Vec2 {
+        I64Vec2 {
+            x: self.w,
+            y: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxx(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.x,
+            y: self.x,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxy(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.x,
+            y: self.x,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxz(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.x,
+            y: self.x,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxw(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.x,
+            y: self.x,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyx(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.x,
+            y: self.y,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyy(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.x,
+            y: self.y,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyz(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.x,
+            y: self.y,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyw(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.x,
+            y: self.y,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzx(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.x,
+            y: self.z,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzy(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.x,
+            y: self.z,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzz(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.x,
+            y: self.z,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzw(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.x,
+            y: self.z,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwx(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.x,
+            y: self.w,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwy(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.x,
+            y: self.w,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwz(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.x,
+            y: self.w,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xww(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.x,
+            y: self.w,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxx(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.y,
+            y: self.x,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxy(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.y,
+            y: self.x,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxz(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.y,
+            y: self.x,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxw(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.y,
+            y: self.x,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyx(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.y,
+            y: self.y,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyy(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.y,
+            y: self.y,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyz(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.y,
+            y: self.y,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyw(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.y,
+            y: self.y,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzx(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.y,
+            y: self.z,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzy(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.y,
+            y: self.z,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzz(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.y,
+            y: self.z,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzw(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.y,
+            y: self.z,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywx(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.y,
+            y: self.w,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywy(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.y,
+            y: self.w,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywz(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.y,
+            y: self.w,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yww(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.y,
+            y: self.w,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxx(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.z,
+            y: self.x,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxy(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.z,
+            y: self.x,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxz(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.z,
+            y: self.x,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxw(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.z,
+            y: self.x,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyx(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.z,
+            y: self.y,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyy(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.z,
+            y: self.y,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyz(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.z,
+            y: self.y,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyw(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.z,
+            y: self.y,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzx(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.z,
+            y: self.z,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzy(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.z,
+            y: self.z,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzz(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.z,
+            y: self.z,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzw(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.z,
+            y: self.z,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwx(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.z,
+            y: self.w,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwy(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.z,
+            y: self.w,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwz(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.z,
+            y: self.w,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zww(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.z,
+            y: self.w,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxx(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.w,
+            y: self.x,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxy(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.w,
+            y: self.x,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxz(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.w,
+            y: self.x,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxw(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.w,
+            y: self.x,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyx(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.w,
+            y: self.y,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyy(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.w,
+            y: self.y,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyz(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.w,
+            y: self.y,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyw(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.w,
+            y: self.y,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzx(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.w,
+            y: self.z,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzy(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.w,
+            y: self.z,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzz(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.w,
+            y: self.z,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzw(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.w,
+            y: self.z,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwx(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.w,
+            y: self.w,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwy(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.w,
+            y: self.w,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwz(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.w,
+            y: self.w,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn www(self) -> I64Vec3 {
+        I64Vec3 {
+            x: self.w,
+            y: self.w,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxxx(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.x, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxxy(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.x, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxxz(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.x, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxxw(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.x, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxyx(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.x, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxyy(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.x, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxyz(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.x, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxyw(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.x, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxzx(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.x, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxzy(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.x, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxzz(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.x, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxzw(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.x, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxwx(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.x, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxwy(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.x, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxwz(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.x, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxww(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.x, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyxx(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.y, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyxy(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.y, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyxz(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.y, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyxw(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.y, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyyx(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.y, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyyy(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.y, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyyz(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.y, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyyw(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.y, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyzx(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.y, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyzy(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.y, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyzz(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.y, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyzw(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.y, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xywx(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.y, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xywy(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.y, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xywz(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.y, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyww(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.y, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzxx(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.z, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzxy(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.z, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzxz(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.z, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzxw(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.z, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzyx(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.z, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzyy(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.z, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzyz(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.z, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzyw(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.z, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzzx(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.z, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzzy(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.z, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzzz(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.z, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzzw(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.z, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzwx(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.z, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzwy(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.z, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzwz(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.z, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzww(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.z, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwxx(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.w, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwxy(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.w, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwxz(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.w, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwxw(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.w, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwyx(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.w, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwyy(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.w, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwyz(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.w, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwyw(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.w, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwzx(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.w, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwzy(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.w, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwzz(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.w, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwzw(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.w, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwwx(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.w, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwwy(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.w, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwwz(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.w, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwww(self) -> I64Vec4 {
+        I64Vec4::new(self.x, self.w, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxxx(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.x, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxxy(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.x, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxxz(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.x, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxxw(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.x, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxyx(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.x, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxyy(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.x, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxyz(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.x, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxyw(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.x, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxzx(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.x, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxzy(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.x, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxzz(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.x, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxzw(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.x, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxwx(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.x, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxwy(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.x, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxwz(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.x, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxww(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.x, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyxx(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.y, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyxy(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.y, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyxz(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.y, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyxw(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.y, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyyx(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.y, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyyy(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.y, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyyz(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.y, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyyw(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.y, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyzx(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.y, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyzy(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.y, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyzz(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.y, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyzw(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.y, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yywx(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.y, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yywy(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.y, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yywz(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.y, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyww(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.y, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzxx(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.z, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzxy(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.z, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzxz(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.z, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzxw(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.z, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzyx(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.z, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzyy(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.z, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzyz(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.z, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzyw(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.z, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzzx(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.z, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzzy(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.z, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzzz(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.z, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzzw(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.z, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzwx(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.z, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzwy(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.z, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzwz(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.z, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzww(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.z, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywxx(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.w, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywxy(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.w, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywxz(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.w, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywxw(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.w, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywyx(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.w, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywyy(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.w, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywyz(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.w, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywyw(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.w, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywzx(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.w, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywzy(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.w, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywzz(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.w, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywzw(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.w, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywwx(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.w, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywwy(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.w, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywwz(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.w, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywww(self) -> I64Vec4 {
+        I64Vec4::new(self.y, self.w, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxxx(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.x, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxxy(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.x, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxxz(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.x, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxxw(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.x, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxyx(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.x, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxyy(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.x, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxyz(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.x, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxyw(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.x, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxzx(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.x, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxzy(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.x, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxzz(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.x, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxzw(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.x, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxwx(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.x, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxwy(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.x, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxwz(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.x, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxww(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.x, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyxx(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.y, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyxy(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.y, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyxz(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.y, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyxw(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.y, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyyx(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.y, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyyy(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.y, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyyz(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.y, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyyw(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.y, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyzx(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.y, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyzy(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.y, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyzz(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.y, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyzw(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.y, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zywx(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.y, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zywy(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.y, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zywz(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.y, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyww(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.y, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzxx(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.z, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzxy(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.z, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzxz(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.z, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzxw(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.z, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzyx(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.z, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzyy(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.z, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzyz(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.z, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzyw(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.z, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzzx(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.z, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzzy(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.z, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzzz(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.z, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzzw(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.z, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzwx(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.z, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzwy(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.z, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzwz(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.z, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzww(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.z, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwxx(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.w, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwxy(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.w, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwxz(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.w, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwxw(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.w, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwyx(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.w, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwyy(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.w, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwyz(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.w, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwyw(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.w, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwzx(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.w, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwzy(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.w, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwzz(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.w, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwzw(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.w, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwwx(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.w, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwwy(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.w, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwwz(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.w, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwww(self) -> I64Vec4 {
+        I64Vec4::new(self.z, self.w, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxxx(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.x, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxxy(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.x, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxxz(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.x, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxxw(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.x, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxyx(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.x, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxyy(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.x, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxyz(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.x, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxyw(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.x, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxzx(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.x, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxzy(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.x, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxzz(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.x, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxzw(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.x, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxwx(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.x, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxwy(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.x, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxwz(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.x, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxww(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.x, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyxx(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.y, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyxy(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.y, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyxz(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.y, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyxw(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.y, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyyx(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.y, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyyy(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.y, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyyz(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.y, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyyw(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.y, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyzx(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.y, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyzy(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.y, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyzz(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.y, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyzw(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.y, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wywx(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.y, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wywy(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.y, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wywz(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.y, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyww(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.y, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzxx(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.z, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzxy(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.z, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzxz(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.z, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzxw(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.z, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzyx(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.z, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzyy(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.z, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzyz(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.z, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzyw(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.z, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzzx(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.z, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzzy(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.z, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzzz(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.z, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzzw(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.z, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzwx(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.z, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzwy(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.z, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzwz(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.z, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzww(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.z, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwxx(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.w, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwxy(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.w, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwxz(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.w, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwxw(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.w, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwyx(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.w, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwyy(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.w, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwyz(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.w, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwyw(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.w, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwzx(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.w, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwzy(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.w, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwzz(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.w, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwzw(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.w, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwwx(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.w, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwwy(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.w, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwwz(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.w, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwww(self) -> I64Vec4 {
+        I64Vec4::new(self.w, self.w, self.w, self.w)
+    }
+}
diff --git a/src/swizzles/ivec2_impl.rs b/src/swizzles/ivec2_impl.rs
index 701b72c..916c132 100644
--- a/src/swizzles/ivec2_impl.rs
+++ b/src/swizzles/ivec2_impl.rs
@@ -8,6 +8,7 @@
     type Vec4 = IVec4;
 
     #[inline]
+    #[must_use]
     fn xx(self) -> IVec2 {
         IVec2 {
             x: self.x,
@@ -16,6 +17,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xy(self) -> IVec2 {
         IVec2 {
             x: self.x,
@@ -24,6 +26,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yx(self) -> IVec2 {
         IVec2 {
             x: self.y,
@@ -32,6 +35,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yy(self) -> IVec2 {
         IVec2 {
             x: self.y,
@@ -40,6 +44,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxx(self) -> IVec3 {
         IVec3 {
             x: self.x,
@@ -49,6 +54,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxy(self) -> IVec3 {
         IVec3 {
             x: self.x,
@@ -58,6 +64,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyx(self) -> IVec3 {
         IVec3 {
             x: self.x,
@@ -67,6 +74,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyy(self) -> IVec3 {
         IVec3 {
             x: self.x,
@@ -76,6 +84,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxx(self) -> IVec3 {
         IVec3 {
             x: self.y,
@@ -85,6 +94,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxy(self) -> IVec3 {
         IVec3 {
             x: self.y,
@@ -94,6 +104,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyx(self) -> IVec3 {
         IVec3 {
             x: self.y,
@@ -103,6 +114,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyy(self) -> IVec3 {
         IVec3 {
             x: self.y,
@@ -112,81 +124,97 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxxx(self) -> IVec4 {
         IVec4::new(self.x, self.x, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xxxy(self) -> IVec4 {
         IVec4::new(self.x, self.x, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xxyx(self) -> IVec4 {
         IVec4::new(self.x, self.x, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xxyy(self) -> IVec4 {
         IVec4::new(self.x, self.x, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xyxx(self) -> IVec4 {
         IVec4::new(self.x, self.y, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xyxy(self) -> IVec4 {
         IVec4::new(self.x, self.y, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xyyx(self) -> IVec4 {
         IVec4::new(self.x, self.y, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xyyy(self) -> IVec4 {
         IVec4::new(self.x, self.y, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yxxx(self) -> IVec4 {
         IVec4::new(self.y, self.x, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yxxy(self) -> IVec4 {
         IVec4::new(self.y, self.x, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yxyx(self) -> IVec4 {
         IVec4::new(self.y, self.x, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yxyy(self) -> IVec4 {
         IVec4::new(self.y, self.x, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yyxx(self) -> IVec4 {
         IVec4::new(self.y, self.y, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yyxy(self) -> IVec4 {
         IVec4::new(self.y, self.y, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yyyx(self) -> IVec4 {
         IVec4::new(self.y, self.y, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yyyy(self) -> IVec4 {
         IVec4::new(self.y, self.y, self.y, self.y)
     }
diff --git a/src/swizzles/ivec3_impl.rs b/src/swizzles/ivec3_impl.rs
index 03d5f43..1ef0a8b 100644
--- a/src/swizzles/ivec3_impl.rs
+++ b/src/swizzles/ivec3_impl.rs
@@ -8,6 +8,7 @@
     type Vec4 = IVec4;
 
     #[inline]
+    #[must_use]
     fn xx(self) -> IVec2 {
         IVec2 {
             x: self.x,
@@ -16,6 +17,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xy(self) -> IVec2 {
         IVec2 {
             x: self.x,
@@ -24,6 +26,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xz(self) -> IVec2 {
         IVec2 {
             x: self.x,
@@ -32,6 +35,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yx(self) -> IVec2 {
         IVec2 {
             x: self.y,
@@ -40,6 +44,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yy(self) -> IVec2 {
         IVec2 {
             x: self.y,
@@ -48,6 +53,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yz(self) -> IVec2 {
         IVec2 {
             x: self.y,
@@ -56,6 +62,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zx(self) -> IVec2 {
         IVec2 {
             x: self.z,
@@ -64,6 +71,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zy(self) -> IVec2 {
         IVec2 {
             x: self.z,
@@ -72,6 +80,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zz(self) -> IVec2 {
         IVec2 {
             x: self.z,
@@ -80,6 +89,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxx(self) -> IVec3 {
         IVec3 {
             x: self.x,
@@ -89,6 +99,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxy(self) -> IVec3 {
         IVec3 {
             x: self.x,
@@ -98,6 +109,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxz(self) -> IVec3 {
         IVec3 {
             x: self.x,
@@ -107,6 +119,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyx(self) -> IVec3 {
         IVec3 {
             x: self.x,
@@ -116,6 +129,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyy(self) -> IVec3 {
         IVec3 {
             x: self.x,
@@ -125,6 +139,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyz(self) -> IVec3 {
         IVec3 {
             x: self.x,
@@ -134,6 +149,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzx(self) -> IVec3 {
         IVec3 {
             x: self.x,
@@ -143,6 +159,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzy(self) -> IVec3 {
         IVec3 {
             x: self.x,
@@ -152,6 +169,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzz(self) -> IVec3 {
         IVec3 {
             x: self.x,
@@ -161,6 +179,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxx(self) -> IVec3 {
         IVec3 {
             x: self.y,
@@ -170,6 +189,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxy(self) -> IVec3 {
         IVec3 {
             x: self.y,
@@ -179,6 +199,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxz(self) -> IVec3 {
         IVec3 {
             x: self.y,
@@ -188,6 +209,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyx(self) -> IVec3 {
         IVec3 {
             x: self.y,
@@ -197,6 +219,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyy(self) -> IVec3 {
         IVec3 {
             x: self.y,
@@ -206,6 +229,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyz(self) -> IVec3 {
         IVec3 {
             x: self.y,
@@ -215,6 +239,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzx(self) -> IVec3 {
         IVec3 {
             x: self.y,
@@ -224,6 +249,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzy(self) -> IVec3 {
         IVec3 {
             x: self.y,
@@ -233,6 +259,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzz(self) -> IVec3 {
         IVec3 {
             x: self.y,
@@ -242,6 +269,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxx(self) -> IVec3 {
         IVec3 {
             x: self.z,
@@ -251,6 +279,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxy(self) -> IVec3 {
         IVec3 {
             x: self.z,
@@ -260,6 +289,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxz(self) -> IVec3 {
         IVec3 {
             x: self.z,
@@ -269,6 +299,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyx(self) -> IVec3 {
         IVec3 {
             x: self.z,
@@ -278,6 +309,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyy(self) -> IVec3 {
         IVec3 {
             x: self.z,
@@ -287,6 +319,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyz(self) -> IVec3 {
         IVec3 {
             x: self.z,
@@ -296,6 +329,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzx(self) -> IVec3 {
         IVec3 {
             x: self.z,
@@ -305,6 +339,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzy(self) -> IVec3 {
         IVec3 {
             x: self.z,
@@ -314,6 +349,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzz(self) -> IVec3 {
         IVec3 {
             x: self.z,
@@ -323,406 +359,487 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxxx(self) -> IVec4 {
         IVec4::new(self.x, self.x, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xxxy(self) -> IVec4 {
         IVec4::new(self.x, self.x, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xxxz(self) -> IVec4 {
         IVec4::new(self.x, self.x, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xxyx(self) -> IVec4 {
         IVec4::new(self.x, self.x, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xxyy(self) -> IVec4 {
         IVec4::new(self.x, self.x, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xxyz(self) -> IVec4 {
         IVec4::new(self.x, self.x, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xxzx(self) -> IVec4 {
         IVec4::new(self.x, self.x, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xxzy(self) -> IVec4 {
         IVec4::new(self.x, self.x, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xxzz(self) -> IVec4 {
         IVec4::new(self.x, self.x, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xyxx(self) -> IVec4 {
         IVec4::new(self.x, self.y, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xyxy(self) -> IVec4 {
         IVec4::new(self.x, self.y, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xyxz(self) -> IVec4 {
         IVec4::new(self.x, self.y, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xyyx(self) -> IVec4 {
         IVec4::new(self.x, self.y, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xyyy(self) -> IVec4 {
         IVec4::new(self.x, self.y, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xyyz(self) -> IVec4 {
         IVec4::new(self.x, self.y, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xyzx(self) -> IVec4 {
         IVec4::new(self.x, self.y, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xyzy(self) -> IVec4 {
         IVec4::new(self.x, self.y, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xyzz(self) -> IVec4 {
         IVec4::new(self.x, self.y, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xzxx(self) -> IVec4 {
         IVec4::new(self.x, self.z, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xzxy(self) -> IVec4 {
         IVec4::new(self.x, self.z, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xzxz(self) -> IVec4 {
         IVec4::new(self.x, self.z, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xzyx(self) -> IVec4 {
         IVec4::new(self.x, self.z, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xzyy(self) -> IVec4 {
         IVec4::new(self.x, self.z, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xzyz(self) -> IVec4 {
         IVec4::new(self.x, self.z, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xzzx(self) -> IVec4 {
         IVec4::new(self.x, self.z, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xzzy(self) -> IVec4 {
         IVec4::new(self.x, self.z, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xzzz(self) -> IVec4 {
         IVec4::new(self.x, self.z, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yxxx(self) -> IVec4 {
         IVec4::new(self.y, self.x, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yxxy(self) -> IVec4 {
         IVec4::new(self.y, self.x, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yxxz(self) -> IVec4 {
         IVec4::new(self.y, self.x, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yxyx(self) -> IVec4 {
         IVec4::new(self.y, self.x, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yxyy(self) -> IVec4 {
         IVec4::new(self.y, self.x, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yxyz(self) -> IVec4 {
         IVec4::new(self.y, self.x, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yxzx(self) -> IVec4 {
         IVec4::new(self.y, self.x, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yxzy(self) -> IVec4 {
         IVec4::new(self.y, self.x, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yxzz(self) -> IVec4 {
         IVec4::new(self.y, self.x, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yyxx(self) -> IVec4 {
         IVec4::new(self.y, self.y, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yyxy(self) -> IVec4 {
         IVec4::new(self.y, self.y, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yyxz(self) -> IVec4 {
         IVec4::new(self.y, self.y, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yyyx(self) -> IVec4 {
         IVec4::new(self.y, self.y, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yyyy(self) -> IVec4 {
         IVec4::new(self.y, self.y, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yyyz(self) -> IVec4 {
         IVec4::new(self.y, self.y, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yyzx(self) -> IVec4 {
         IVec4::new(self.y, self.y, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yyzy(self) -> IVec4 {
         IVec4::new(self.y, self.y, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yyzz(self) -> IVec4 {
         IVec4::new(self.y, self.y, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yzxx(self) -> IVec4 {
         IVec4::new(self.y, self.z, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yzxy(self) -> IVec4 {
         IVec4::new(self.y, self.z, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yzxz(self) -> IVec4 {
         IVec4::new(self.y, self.z, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yzyx(self) -> IVec4 {
         IVec4::new(self.y, self.z, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yzyy(self) -> IVec4 {
         IVec4::new(self.y, self.z, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yzyz(self) -> IVec4 {
         IVec4::new(self.y, self.z, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yzzx(self) -> IVec4 {
         IVec4::new(self.y, self.z, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yzzy(self) -> IVec4 {
         IVec4::new(self.y, self.z, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yzzz(self) -> IVec4 {
         IVec4::new(self.y, self.z, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zxxx(self) -> IVec4 {
         IVec4::new(self.z, self.x, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zxxy(self) -> IVec4 {
         IVec4::new(self.z, self.x, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zxxz(self) -> IVec4 {
         IVec4::new(self.z, self.x, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zxyx(self) -> IVec4 {
         IVec4::new(self.z, self.x, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zxyy(self) -> IVec4 {
         IVec4::new(self.z, self.x, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zxyz(self) -> IVec4 {
         IVec4::new(self.z, self.x, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zxzx(self) -> IVec4 {
         IVec4::new(self.z, self.x, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zxzy(self) -> IVec4 {
         IVec4::new(self.z, self.x, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zxzz(self) -> IVec4 {
         IVec4::new(self.z, self.x, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zyxx(self) -> IVec4 {
         IVec4::new(self.z, self.y, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zyxy(self) -> IVec4 {
         IVec4::new(self.z, self.y, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zyxz(self) -> IVec4 {
         IVec4::new(self.z, self.y, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zyyx(self) -> IVec4 {
         IVec4::new(self.z, self.y, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zyyy(self) -> IVec4 {
         IVec4::new(self.z, self.y, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zyyz(self) -> IVec4 {
         IVec4::new(self.z, self.y, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zyzx(self) -> IVec4 {
         IVec4::new(self.z, self.y, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zyzy(self) -> IVec4 {
         IVec4::new(self.z, self.y, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zyzz(self) -> IVec4 {
         IVec4::new(self.z, self.y, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zzxx(self) -> IVec4 {
         IVec4::new(self.z, self.z, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zzxy(self) -> IVec4 {
         IVec4::new(self.z, self.z, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zzxz(self) -> IVec4 {
         IVec4::new(self.z, self.z, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zzyx(self) -> IVec4 {
         IVec4::new(self.z, self.z, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zzyy(self) -> IVec4 {
         IVec4::new(self.z, self.z, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zzyz(self) -> IVec4 {
         IVec4::new(self.z, self.z, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zzzx(self) -> IVec4 {
         IVec4::new(self.z, self.z, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zzzy(self) -> IVec4 {
         IVec4::new(self.z, self.z, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zzzz(self) -> IVec4 {
         IVec4::new(self.z, self.z, self.z, self.z)
     }
diff --git a/src/swizzles/ivec4_impl.rs b/src/swizzles/ivec4_impl.rs
index c2845e8..a446486 100644
--- a/src/swizzles/ivec4_impl.rs
+++ b/src/swizzles/ivec4_impl.rs
@@ -8,6 +8,7 @@
     type Vec3 = IVec3;
 
     #[inline]
+    #[must_use]
     fn xx(self) -> IVec2 {
         IVec2 {
             x: self.x,
@@ -16,6 +17,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xy(self) -> IVec2 {
         IVec2 {
             x: self.x,
@@ -24,6 +26,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xz(self) -> IVec2 {
         IVec2 {
             x: self.x,
@@ -32,6 +35,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xw(self) -> IVec2 {
         IVec2 {
             x: self.x,
@@ -40,6 +44,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yx(self) -> IVec2 {
         IVec2 {
             x: self.y,
@@ -48,6 +53,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yy(self) -> IVec2 {
         IVec2 {
             x: self.y,
@@ -56,6 +62,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yz(self) -> IVec2 {
         IVec2 {
             x: self.y,
@@ -64,6 +71,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yw(self) -> IVec2 {
         IVec2 {
             x: self.y,
@@ -72,6 +80,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zx(self) -> IVec2 {
         IVec2 {
             x: self.z,
@@ -80,6 +89,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zy(self) -> IVec2 {
         IVec2 {
             x: self.z,
@@ -88,6 +98,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zz(self) -> IVec2 {
         IVec2 {
             x: self.z,
@@ -96,6 +107,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zw(self) -> IVec2 {
         IVec2 {
             x: self.z,
@@ -104,6 +116,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wx(self) -> IVec2 {
         IVec2 {
             x: self.w,
@@ -112,6 +125,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wy(self) -> IVec2 {
         IVec2 {
             x: self.w,
@@ -120,6 +134,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wz(self) -> IVec2 {
         IVec2 {
             x: self.w,
@@ -128,6 +143,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn ww(self) -> IVec2 {
         IVec2 {
             x: self.w,
@@ -136,6 +152,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxx(self) -> IVec3 {
         IVec3 {
             x: self.x,
@@ -145,6 +162,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxy(self) -> IVec3 {
         IVec3 {
             x: self.x,
@@ -154,6 +172,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxz(self) -> IVec3 {
         IVec3 {
             x: self.x,
@@ -163,6 +182,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxw(self) -> IVec3 {
         IVec3 {
             x: self.x,
@@ -172,6 +192,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyx(self) -> IVec3 {
         IVec3 {
             x: self.x,
@@ -181,6 +202,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyy(self) -> IVec3 {
         IVec3 {
             x: self.x,
@@ -190,6 +212,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyz(self) -> IVec3 {
         IVec3 {
             x: self.x,
@@ -199,6 +222,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyw(self) -> IVec3 {
         IVec3 {
             x: self.x,
@@ -208,6 +232,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzx(self) -> IVec3 {
         IVec3 {
             x: self.x,
@@ -217,6 +242,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzy(self) -> IVec3 {
         IVec3 {
             x: self.x,
@@ -226,6 +252,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzz(self) -> IVec3 {
         IVec3 {
             x: self.x,
@@ -235,6 +262,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzw(self) -> IVec3 {
         IVec3 {
             x: self.x,
@@ -244,6 +272,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xwx(self) -> IVec3 {
         IVec3 {
             x: self.x,
@@ -253,6 +282,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xwy(self) -> IVec3 {
         IVec3 {
             x: self.x,
@@ -262,6 +292,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xwz(self) -> IVec3 {
         IVec3 {
             x: self.x,
@@ -271,6 +302,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xww(self) -> IVec3 {
         IVec3 {
             x: self.x,
@@ -280,6 +312,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxx(self) -> IVec3 {
         IVec3 {
             x: self.y,
@@ -289,6 +322,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxy(self) -> IVec3 {
         IVec3 {
             x: self.y,
@@ -298,6 +332,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxz(self) -> IVec3 {
         IVec3 {
             x: self.y,
@@ -307,6 +342,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxw(self) -> IVec3 {
         IVec3 {
             x: self.y,
@@ -316,6 +352,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyx(self) -> IVec3 {
         IVec3 {
             x: self.y,
@@ -325,6 +362,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyy(self) -> IVec3 {
         IVec3 {
             x: self.y,
@@ -334,6 +372,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyz(self) -> IVec3 {
         IVec3 {
             x: self.y,
@@ -343,6 +382,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyw(self) -> IVec3 {
         IVec3 {
             x: self.y,
@@ -352,6 +392,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzx(self) -> IVec3 {
         IVec3 {
             x: self.y,
@@ -361,6 +402,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzy(self) -> IVec3 {
         IVec3 {
             x: self.y,
@@ -370,6 +412,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzz(self) -> IVec3 {
         IVec3 {
             x: self.y,
@@ -379,6 +422,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzw(self) -> IVec3 {
         IVec3 {
             x: self.y,
@@ -388,6 +432,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn ywx(self) -> IVec3 {
         IVec3 {
             x: self.y,
@@ -397,6 +442,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn ywy(self) -> IVec3 {
         IVec3 {
             x: self.y,
@@ -406,6 +452,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn ywz(self) -> IVec3 {
         IVec3 {
             x: self.y,
@@ -415,6 +462,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yww(self) -> IVec3 {
         IVec3 {
             x: self.y,
@@ -424,6 +472,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxx(self) -> IVec3 {
         IVec3 {
             x: self.z,
@@ -433,6 +482,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxy(self) -> IVec3 {
         IVec3 {
             x: self.z,
@@ -442,6 +492,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxz(self) -> IVec3 {
         IVec3 {
             x: self.z,
@@ -451,6 +502,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxw(self) -> IVec3 {
         IVec3 {
             x: self.z,
@@ -460,6 +512,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyx(self) -> IVec3 {
         IVec3 {
             x: self.z,
@@ -469,6 +522,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyy(self) -> IVec3 {
         IVec3 {
             x: self.z,
@@ -478,6 +532,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyz(self) -> IVec3 {
         IVec3 {
             x: self.z,
@@ -487,6 +542,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyw(self) -> IVec3 {
         IVec3 {
             x: self.z,
@@ -496,6 +552,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzx(self) -> IVec3 {
         IVec3 {
             x: self.z,
@@ -505,6 +562,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzy(self) -> IVec3 {
         IVec3 {
             x: self.z,
@@ -514,6 +572,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzz(self) -> IVec3 {
         IVec3 {
             x: self.z,
@@ -523,6 +582,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzw(self) -> IVec3 {
         IVec3 {
             x: self.z,
@@ -532,6 +592,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zwx(self) -> IVec3 {
         IVec3 {
             x: self.z,
@@ -541,6 +602,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zwy(self) -> IVec3 {
         IVec3 {
             x: self.z,
@@ -550,6 +612,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zwz(self) -> IVec3 {
         IVec3 {
             x: self.z,
@@ -559,6 +622,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zww(self) -> IVec3 {
         IVec3 {
             x: self.z,
@@ -568,6 +632,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wxx(self) -> IVec3 {
         IVec3 {
             x: self.w,
@@ -577,6 +642,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wxy(self) -> IVec3 {
         IVec3 {
             x: self.w,
@@ -586,6 +652,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wxz(self) -> IVec3 {
         IVec3 {
             x: self.w,
@@ -595,6 +662,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wxw(self) -> IVec3 {
         IVec3 {
             x: self.w,
@@ -604,6 +672,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wyx(self) -> IVec3 {
         IVec3 {
             x: self.w,
@@ -613,6 +682,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wyy(self) -> IVec3 {
         IVec3 {
             x: self.w,
@@ -622,6 +692,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wyz(self) -> IVec3 {
         IVec3 {
             x: self.w,
@@ -631,6 +702,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wyw(self) -> IVec3 {
         IVec3 {
             x: self.w,
@@ -640,6 +712,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wzx(self) -> IVec3 {
         IVec3 {
             x: self.w,
@@ -649,6 +722,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wzy(self) -> IVec3 {
         IVec3 {
             x: self.w,
@@ -658,6 +732,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wzz(self) -> IVec3 {
         IVec3 {
             x: self.w,
@@ -667,6 +742,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wzw(self) -> IVec3 {
         IVec3 {
             x: self.w,
@@ -676,6 +752,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wwx(self) -> IVec3 {
         IVec3 {
             x: self.w,
@@ -685,6 +762,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wwy(self) -> IVec3 {
         IVec3 {
             x: self.w,
@@ -694,6 +772,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wwz(self) -> IVec3 {
         IVec3 {
             x: self.w,
@@ -703,6 +782,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn www(self) -> IVec3 {
         IVec3 {
             x: self.w,
@@ -712,1281 +792,1537 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxxx(self) -> IVec4 {
         IVec4::new(self.x, self.x, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xxxy(self) -> IVec4 {
         IVec4::new(self.x, self.x, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xxxz(self) -> IVec4 {
         IVec4::new(self.x, self.x, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xxxw(self) -> IVec4 {
         IVec4::new(self.x, self.x, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xxyx(self) -> IVec4 {
         IVec4::new(self.x, self.x, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xxyy(self) -> IVec4 {
         IVec4::new(self.x, self.x, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xxyz(self) -> IVec4 {
         IVec4::new(self.x, self.x, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xxyw(self) -> IVec4 {
         IVec4::new(self.x, self.x, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xxzx(self) -> IVec4 {
         IVec4::new(self.x, self.x, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xxzy(self) -> IVec4 {
         IVec4::new(self.x, self.x, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xxzz(self) -> IVec4 {
         IVec4::new(self.x, self.x, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xxzw(self) -> IVec4 {
         IVec4::new(self.x, self.x, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xxwx(self) -> IVec4 {
         IVec4::new(self.x, self.x, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xxwy(self) -> IVec4 {
         IVec4::new(self.x, self.x, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xxwz(self) -> IVec4 {
         IVec4::new(self.x, self.x, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xxww(self) -> IVec4 {
         IVec4::new(self.x, self.x, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xyxx(self) -> IVec4 {
         IVec4::new(self.x, self.y, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xyxy(self) -> IVec4 {
         IVec4::new(self.x, self.y, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xyxz(self) -> IVec4 {
         IVec4::new(self.x, self.y, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xyxw(self) -> IVec4 {
         IVec4::new(self.x, self.y, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xyyx(self) -> IVec4 {
         IVec4::new(self.x, self.y, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xyyy(self) -> IVec4 {
         IVec4::new(self.x, self.y, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xyyz(self) -> IVec4 {
         IVec4::new(self.x, self.y, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xyyw(self) -> IVec4 {
         IVec4::new(self.x, self.y, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xyzx(self) -> IVec4 {
         IVec4::new(self.x, self.y, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xyzy(self) -> IVec4 {
         IVec4::new(self.x, self.y, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xyzz(self) -> IVec4 {
         IVec4::new(self.x, self.y, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xyzw(self) -> IVec4 {
         IVec4::new(self.x, self.y, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xywx(self) -> IVec4 {
         IVec4::new(self.x, self.y, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xywy(self) -> IVec4 {
         IVec4::new(self.x, self.y, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xywz(self) -> IVec4 {
         IVec4::new(self.x, self.y, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xyww(self) -> IVec4 {
         IVec4::new(self.x, self.y, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xzxx(self) -> IVec4 {
         IVec4::new(self.x, self.z, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xzxy(self) -> IVec4 {
         IVec4::new(self.x, self.z, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xzxz(self) -> IVec4 {
         IVec4::new(self.x, self.z, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xzxw(self) -> IVec4 {
         IVec4::new(self.x, self.z, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xzyx(self) -> IVec4 {
         IVec4::new(self.x, self.z, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xzyy(self) -> IVec4 {
         IVec4::new(self.x, self.z, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xzyz(self) -> IVec4 {
         IVec4::new(self.x, self.z, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xzyw(self) -> IVec4 {
         IVec4::new(self.x, self.z, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xzzx(self) -> IVec4 {
         IVec4::new(self.x, self.z, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xzzy(self) -> IVec4 {
         IVec4::new(self.x, self.z, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xzzz(self) -> IVec4 {
         IVec4::new(self.x, self.z, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xzzw(self) -> IVec4 {
         IVec4::new(self.x, self.z, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xzwx(self) -> IVec4 {
         IVec4::new(self.x, self.z, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xzwy(self) -> IVec4 {
         IVec4::new(self.x, self.z, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xzwz(self) -> IVec4 {
         IVec4::new(self.x, self.z, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xzww(self) -> IVec4 {
         IVec4::new(self.x, self.z, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xwxx(self) -> IVec4 {
         IVec4::new(self.x, self.w, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xwxy(self) -> IVec4 {
         IVec4::new(self.x, self.w, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xwxz(self) -> IVec4 {
         IVec4::new(self.x, self.w, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xwxw(self) -> IVec4 {
         IVec4::new(self.x, self.w, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xwyx(self) -> IVec4 {
         IVec4::new(self.x, self.w, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xwyy(self) -> IVec4 {
         IVec4::new(self.x, self.w, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xwyz(self) -> IVec4 {
         IVec4::new(self.x, self.w, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xwyw(self) -> IVec4 {
         IVec4::new(self.x, self.w, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xwzx(self) -> IVec4 {
         IVec4::new(self.x, self.w, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xwzy(self) -> IVec4 {
         IVec4::new(self.x, self.w, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xwzz(self) -> IVec4 {
         IVec4::new(self.x, self.w, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xwzw(self) -> IVec4 {
         IVec4::new(self.x, self.w, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xwwx(self) -> IVec4 {
         IVec4::new(self.x, self.w, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xwwy(self) -> IVec4 {
         IVec4::new(self.x, self.w, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xwwz(self) -> IVec4 {
         IVec4::new(self.x, self.w, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xwww(self) -> IVec4 {
         IVec4::new(self.x, self.w, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yxxx(self) -> IVec4 {
         IVec4::new(self.y, self.x, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yxxy(self) -> IVec4 {
         IVec4::new(self.y, self.x, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yxxz(self) -> IVec4 {
         IVec4::new(self.y, self.x, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yxxw(self) -> IVec4 {
         IVec4::new(self.y, self.x, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yxyx(self) -> IVec4 {
         IVec4::new(self.y, self.x, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yxyy(self) -> IVec4 {
         IVec4::new(self.y, self.x, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yxyz(self) -> IVec4 {
         IVec4::new(self.y, self.x, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yxyw(self) -> IVec4 {
         IVec4::new(self.y, self.x, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yxzx(self) -> IVec4 {
         IVec4::new(self.y, self.x, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yxzy(self) -> IVec4 {
         IVec4::new(self.y, self.x, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yxzz(self) -> IVec4 {
         IVec4::new(self.y, self.x, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yxzw(self) -> IVec4 {
         IVec4::new(self.y, self.x, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yxwx(self) -> IVec4 {
         IVec4::new(self.y, self.x, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yxwy(self) -> IVec4 {
         IVec4::new(self.y, self.x, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yxwz(self) -> IVec4 {
         IVec4::new(self.y, self.x, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yxww(self) -> IVec4 {
         IVec4::new(self.y, self.x, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yyxx(self) -> IVec4 {
         IVec4::new(self.y, self.y, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yyxy(self) -> IVec4 {
         IVec4::new(self.y, self.y, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yyxz(self) -> IVec4 {
         IVec4::new(self.y, self.y, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yyxw(self) -> IVec4 {
         IVec4::new(self.y, self.y, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yyyx(self) -> IVec4 {
         IVec4::new(self.y, self.y, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yyyy(self) -> IVec4 {
         IVec4::new(self.y, self.y, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yyyz(self) -> IVec4 {
         IVec4::new(self.y, self.y, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yyyw(self) -> IVec4 {
         IVec4::new(self.y, self.y, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yyzx(self) -> IVec4 {
         IVec4::new(self.y, self.y, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yyzy(self) -> IVec4 {
         IVec4::new(self.y, self.y, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yyzz(self) -> IVec4 {
         IVec4::new(self.y, self.y, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yyzw(self) -> IVec4 {
         IVec4::new(self.y, self.y, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yywx(self) -> IVec4 {
         IVec4::new(self.y, self.y, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yywy(self) -> IVec4 {
         IVec4::new(self.y, self.y, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yywz(self) -> IVec4 {
         IVec4::new(self.y, self.y, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yyww(self) -> IVec4 {
         IVec4::new(self.y, self.y, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yzxx(self) -> IVec4 {
         IVec4::new(self.y, self.z, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yzxy(self) -> IVec4 {
         IVec4::new(self.y, self.z, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yzxz(self) -> IVec4 {
         IVec4::new(self.y, self.z, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yzxw(self) -> IVec4 {
         IVec4::new(self.y, self.z, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yzyx(self) -> IVec4 {
         IVec4::new(self.y, self.z, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yzyy(self) -> IVec4 {
         IVec4::new(self.y, self.z, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yzyz(self) -> IVec4 {
         IVec4::new(self.y, self.z, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yzyw(self) -> IVec4 {
         IVec4::new(self.y, self.z, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yzzx(self) -> IVec4 {
         IVec4::new(self.y, self.z, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yzzy(self) -> IVec4 {
         IVec4::new(self.y, self.z, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yzzz(self) -> IVec4 {
         IVec4::new(self.y, self.z, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yzzw(self) -> IVec4 {
         IVec4::new(self.y, self.z, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yzwx(self) -> IVec4 {
         IVec4::new(self.y, self.z, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yzwy(self) -> IVec4 {
         IVec4::new(self.y, self.z, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yzwz(self) -> IVec4 {
         IVec4::new(self.y, self.z, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yzww(self) -> IVec4 {
         IVec4::new(self.y, self.z, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn ywxx(self) -> IVec4 {
         IVec4::new(self.y, self.w, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn ywxy(self) -> IVec4 {
         IVec4::new(self.y, self.w, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn ywxz(self) -> IVec4 {
         IVec4::new(self.y, self.w, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn ywxw(self) -> IVec4 {
         IVec4::new(self.y, self.w, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn ywyx(self) -> IVec4 {
         IVec4::new(self.y, self.w, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn ywyy(self) -> IVec4 {
         IVec4::new(self.y, self.w, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn ywyz(self) -> IVec4 {
         IVec4::new(self.y, self.w, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn ywyw(self) -> IVec4 {
         IVec4::new(self.y, self.w, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn ywzx(self) -> IVec4 {
         IVec4::new(self.y, self.w, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn ywzy(self) -> IVec4 {
         IVec4::new(self.y, self.w, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn ywzz(self) -> IVec4 {
         IVec4::new(self.y, self.w, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn ywzw(self) -> IVec4 {
         IVec4::new(self.y, self.w, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn ywwx(self) -> IVec4 {
         IVec4::new(self.y, self.w, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn ywwy(self) -> IVec4 {
         IVec4::new(self.y, self.w, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn ywwz(self) -> IVec4 {
         IVec4::new(self.y, self.w, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn ywww(self) -> IVec4 {
         IVec4::new(self.y, self.w, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zxxx(self) -> IVec4 {
         IVec4::new(self.z, self.x, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zxxy(self) -> IVec4 {
         IVec4::new(self.z, self.x, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zxxz(self) -> IVec4 {
         IVec4::new(self.z, self.x, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zxxw(self) -> IVec4 {
         IVec4::new(self.z, self.x, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zxyx(self) -> IVec4 {
         IVec4::new(self.z, self.x, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zxyy(self) -> IVec4 {
         IVec4::new(self.z, self.x, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zxyz(self) -> IVec4 {
         IVec4::new(self.z, self.x, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zxyw(self) -> IVec4 {
         IVec4::new(self.z, self.x, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zxzx(self) -> IVec4 {
         IVec4::new(self.z, self.x, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zxzy(self) -> IVec4 {
         IVec4::new(self.z, self.x, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zxzz(self) -> IVec4 {
         IVec4::new(self.z, self.x, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zxzw(self) -> IVec4 {
         IVec4::new(self.z, self.x, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zxwx(self) -> IVec4 {
         IVec4::new(self.z, self.x, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zxwy(self) -> IVec4 {
         IVec4::new(self.z, self.x, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zxwz(self) -> IVec4 {
         IVec4::new(self.z, self.x, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zxww(self) -> IVec4 {
         IVec4::new(self.z, self.x, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zyxx(self) -> IVec4 {
         IVec4::new(self.z, self.y, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zyxy(self) -> IVec4 {
         IVec4::new(self.z, self.y, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zyxz(self) -> IVec4 {
         IVec4::new(self.z, self.y, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zyxw(self) -> IVec4 {
         IVec4::new(self.z, self.y, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zyyx(self) -> IVec4 {
         IVec4::new(self.z, self.y, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zyyy(self) -> IVec4 {
         IVec4::new(self.z, self.y, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zyyz(self) -> IVec4 {
         IVec4::new(self.z, self.y, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zyyw(self) -> IVec4 {
         IVec4::new(self.z, self.y, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zyzx(self) -> IVec4 {
         IVec4::new(self.z, self.y, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zyzy(self) -> IVec4 {
         IVec4::new(self.z, self.y, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zyzz(self) -> IVec4 {
         IVec4::new(self.z, self.y, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zyzw(self) -> IVec4 {
         IVec4::new(self.z, self.y, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zywx(self) -> IVec4 {
         IVec4::new(self.z, self.y, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zywy(self) -> IVec4 {
         IVec4::new(self.z, self.y, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zywz(self) -> IVec4 {
         IVec4::new(self.z, self.y, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zyww(self) -> IVec4 {
         IVec4::new(self.z, self.y, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zzxx(self) -> IVec4 {
         IVec4::new(self.z, self.z, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zzxy(self) -> IVec4 {
         IVec4::new(self.z, self.z, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zzxz(self) -> IVec4 {
         IVec4::new(self.z, self.z, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zzxw(self) -> IVec4 {
         IVec4::new(self.z, self.z, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zzyx(self) -> IVec4 {
         IVec4::new(self.z, self.z, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zzyy(self) -> IVec4 {
         IVec4::new(self.z, self.z, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zzyz(self) -> IVec4 {
         IVec4::new(self.z, self.z, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zzyw(self) -> IVec4 {
         IVec4::new(self.z, self.z, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zzzx(self) -> IVec4 {
         IVec4::new(self.z, self.z, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zzzy(self) -> IVec4 {
         IVec4::new(self.z, self.z, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zzzz(self) -> IVec4 {
         IVec4::new(self.z, self.z, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zzzw(self) -> IVec4 {
         IVec4::new(self.z, self.z, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zzwx(self) -> IVec4 {
         IVec4::new(self.z, self.z, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zzwy(self) -> IVec4 {
         IVec4::new(self.z, self.z, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zzwz(self) -> IVec4 {
         IVec4::new(self.z, self.z, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zzww(self) -> IVec4 {
         IVec4::new(self.z, self.z, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zwxx(self) -> IVec4 {
         IVec4::new(self.z, self.w, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zwxy(self) -> IVec4 {
         IVec4::new(self.z, self.w, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zwxz(self) -> IVec4 {
         IVec4::new(self.z, self.w, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zwxw(self) -> IVec4 {
         IVec4::new(self.z, self.w, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zwyx(self) -> IVec4 {
         IVec4::new(self.z, self.w, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zwyy(self) -> IVec4 {
         IVec4::new(self.z, self.w, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zwyz(self) -> IVec4 {
         IVec4::new(self.z, self.w, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zwyw(self) -> IVec4 {
         IVec4::new(self.z, self.w, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zwzx(self) -> IVec4 {
         IVec4::new(self.z, self.w, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zwzy(self) -> IVec4 {
         IVec4::new(self.z, self.w, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zwzz(self) -> IVec4 {
         IVec4::new(self.z, self.w, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zwzw(self) -> IVec4 {
         IVec4::new(self.z, self.w, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zwwx(self) -> IVec4 {
         IVec4::new(self.z, self.w, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zwwy(self) -> IVec4 {
         IVec4::new(self.z, self.w, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zwwz(self) -> IVec4 {
         IVec4::new(self.z, self.w, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zwww(self) -> IVec4 {
         IVec4::new(self.z, self.w, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wxxx(self) -> IVec4 {
         IVec4::new(self.w, self.x, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wxxy(self) -> IVec4 {
         IVec4::new(self.w, self.x, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wxxz(self) -> IVec4 {
         IVec4::new(self.w, self.x, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wxxw(self) -> IVec4 {
         IVec4::new(self.w, self.x, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wxyx(self) -> IVec4 {
         IVec4::new(self.w, self.x, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wxyy(self) -> IVec4 {
         IVec4::new(self.w, self.x, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wxyz(self) -> IVec4 {
         IVec4::new(self.w, self.x, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wxyw(self) -> IVec4 {
         IVec4::new(self.w, self.x, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wxzx(self) -> IVec4 {
         IVec4::new(self.w, self.x, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wxzy(self) -> IVec4 {
         IVec4::new(self.w, self.x, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wxzz(self) -> IVec4 {
         IVec4::new(self.w, self.x, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wxzw(self) -> IVec4 {
         IVec4::new(self.w, self.x, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wxwx(self) -> IVec4 {
         IVec4::new(self.w, self.x, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wxwy(self) -> IVec4 {
         IVec4::new(self.w, self.x, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wxwz(self) -> IVec4 {
         IVec4::new(self.w, self.x, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wxww(self) -> IVec4 {
         IVec4::new(self.w, self.x, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wyxx(self) -> IVec4 {
         IVec4::new(self.w, self.y, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wyxy(self) -> IVec4 {
         IVec4::new(self.w, self.y, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wyxz(self) -> IVec4 {
         IVec4::new(self.w, self.y, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wyxw(self) -> IVec4 {
         IVec4::new(self.w, self.y, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wyyx(self) -> IVec4 {
         IVec4::new(self.w, self.y, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wyyy(self) -> IVec4 {
         IVec4::new(self.w, self.y, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wyyz(self) -> IVec4 {
         IVec4::new(self.w, self.y, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wyyw(self) -> IVec4 {
         IVec4::new(self.w, self.y, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wyzx(self) -> IVec4 {
         IVec4::new(self.w, self.y, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wyzy(self) -> IVec4 {
         IVec4::new(self.w, self.y, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wyzz(self) -> IVec4 {
         IVec4::new(self.w, self.y, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wyzw(self) -> IVec4 {
         IVec4::new(self.w, self.y, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wywx(self) -> IVec4 {
         IVec4::new(self.w, self.y, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wywy(self) -> IVec4 {
         IVec4::new(self.w, self.y, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wywz(self) -> IVec4 {
         IVec4::new(self.w, self.y, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wyww(self) -> IVec4 {
         IVec4::new(self.w, self.y, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wzxx(self) -> IVec4 {
         IVec4::new(self.w, self.z, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wzxy(self) -> IVec4 {
         IVec4::new(self.w, self.z, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wzxz(self) -> IVec4 {
         IVec4::new(self.w, self.z, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wzxw(self) -> IVec4 {
         IVec4::new(self.w, self.z, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wzyx(self) -> IVec4 {
         IVec4::new(self.w, self.z, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wzyy(self) -> IVec4 {
         IVec4::new(self.w, self.z, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wzyz(self) -> IVec4 {
         IVec4::new(self.w, self.z, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wzyw(self) -> IVec4 {
         IVec4::new(self.w, self.z, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wzzx(self) -> IVec4 {
         IVec4::new(self.w, self.z, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wzzy(self) -> IVec4 {
         IVec4::new(self.w, self.z, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wzzz(self) -> IVec4 {
         IVec4::new(self.w, self.z, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wzzw(self) -> IVec4 {
         IVec4::new(self.w, self.z, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wzwx(self) -> IVec4 {
         IVec4::new(self.w, self.z, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wzwy(self) -> IVec4 {
         IVec4::new(self.w, self.z, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wzwz(self) -> IVec4 {
         IVec4::new(self.w, self.z, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wzww(self) -> IVec4 {
         IVec4::new(self.w, self.z, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wwxx(self) -> IVec4 {
         IVec4::new(self.w, self.w, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wwxy(self) -> IVec4 {
         IVec4::new(self.w, self.w, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wwxz(self) -> IVec4 {
         IVec4::new(self.w, self.w, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wwxw(self) -> IVec4 {
         IVec4::new(self.w, self.w, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wwyx(self) -> IVec4 {
         IVec4::new(self.w, self.w, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wwyy(self) -> IVec4 {
         IVec4::new(self.w, self.w, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wwyz(self) -> IVec4 {
         IVec4::new(self.w, self.w, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wwyw(self) -> IVec4 {
         IVec4::new(self.w, self.w, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wwzx(self) -> IVec4 {
         IVec4::new(self.w, self.w, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wwzy(self) -> IVec4 {
         IVec4::new(self.w, self.w, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wwzz(self) -> IVec4 {
         IVec4::new(self.w, self.w, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wwzw(self) -> IVec4 {
         IVec4::new(self.w, self.w, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wwwx(self) -> IVec4 {
         IVec4::new(self.w, self.w, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wwwy(self) -> IVec4 {
         IVec4::new(self.w, self.w, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wwwz(self) -> IVec4 {
         IVec4::new(self.w, self.w, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wwww(self) -> IVec4 {
         IVec4::new(self.w, self.w, self.w, self.w)
     }
diff --git a/src/swizzles/scalar/vec3a_impl.rs b/src/swizzles/scalar/vec3a_impl.rs
index 8ac0a41..9b7d3bd 100644
--- a/src/swizzles/scalar/vec3a_impl.rs
+++ b/src/swizzles/scalar/vec3a_impl.rs
@@ -8,6 +8,7 @@
     type Vec4 = Vec4;
 
     #[inline]
+    #[must_use]
     fn xx(self) -> Vec2 {
         Vec2 {
             x: self.x,
@@ -16,6 +17,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xy(self) -> Vec2 {
         Vec2 {
             x: self.x,
@@ -24,6 +26,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xz(self) -> Vec2 {
         Vec2 {
             x: self.x,
@@ -32,6 +35,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yx(self) -> Vec2 {
         Vec2 {
             x: self.y,
@@ -40,6 +44,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yy(self) -> Vec2 {
         Vec2 {
             x: self.y,
@@ -48,6 +53,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yz(self) -> Vec2 {
         Vec2 {
             x: self.y,
@@ -56,6 +62,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zx(self) -> Vec2 {
         Vec2 {
             x: self.z,
@@ -64,6 +71,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zy(self) -> Vec2 {
         Vec2 {
             x: self.z,
@@ -72,6 +80,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zz(self) -> Vec2 {
         Vec2 {
             x: self.z,
@@ -80,6 +89,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxx(self) -> Vec3A {
         Vec3A {
             x: self.x,
@@ -89,6 +99,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxy(self) -> Vec3A {
         Vec3A {
             x: self.x,
@@ -98,6 +109,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxz(self) -> Vec3A {
         Vec3A {
             x: self.x,
@@ -107,6 +119,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyx(self) -> Vec3A {
         Vec3A {
             x: self.x,
@@ -116,6 +129,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyy(self) -> Vec3A {
         Vec3A {
             x: self.x,
@@ -125,6 +139,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyz(self) -> Vec3A {
         Vec3A {
             x: self.x,
@@ -134,6 +149,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzx(self) -> Vec3A {
         Vec3A {
             x: self.x,
@@ -143,6 +159,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzy(self) -> Vec3A {
         Vec3A {
             x: self.x,
@@ -152,6 +169,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzz(self) -> Vec3A {
         Vec3A {
             x: self.x,
@@ -161,6 +179,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxx(self) -> Vec3A {
         Vec3A {
             x: self.y,
@@ -170,6 +189,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxy(self) -> Vec3A {
         Vec3A {
             x: self.y,
@@ -179,6 +199,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxz(self) -> Vec3A {
         Vec3A {
             x: self.y,
@@ -188,6 +209,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyx(self) -> Vec3A {
         Vec3A {
             x: self.y,
@@ -197,6 +219,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyy(self) -> Vec3A {
         Vec3A {
             x: self.y,
@@ -206,6 +229,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyz(self) -> Vec3A {
         Vec3A {
             x: self.y,
@@ -215,6 +239,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzx(self) -> Vec3A {
         Vec3A {
             x: self.y,
@@ -224,6 +249,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzy(self) -> Vec3A {
         Vec3A {
             x: self.y,
@@ -233,6 +259,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzz(self) -> Vec3A {
         Vec3A {
             x: self.y,
@@ -242,6 +269,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxx(self) -> Vec3A {
         Vec3A {
             x: self.z,
@@ -251,6 +279,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxy(self) -> Vec3A {
         Vec3A {
             x: self.z,
@@ -260,6 +289,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxz(self) -> Vec3A {
         Vec3A {
             x: self.z,
@@ -269,6 +299,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyx(self) -> Vec3A {
         Vec3A {
             x: self.z,
@@ -278,6 +309,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyy(self) -> Vec3A {
         Vec3A {
             x: self.z,
@@ -287,6 +319,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyz(self) -> Vec3A {
         Vec3A {
             x: self.z,
@@ -296,6 +329,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzx(self) -> Vec3A {
         Vec3A {
             x: self.z,
@@ -305,6 +339,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzy(self) -> Vec3A {
         Vec3A {
             x: self.z,
@@ -314,6 +349,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzz(self) -> Vec3A {
         Vec3A {
             x: self.z,
@@ -323,406 +359,487 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxxx(self) -> Vec4 {
         Vec4::new(self.x, self.x, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xxxy(self) -> Vec4 {
         Vec4::new(self.x, self.x, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xxxz(self) -> Vec4 {
         Vec4::new(self.x, self.x, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xxyx(self) -> Vec4 {
         Vec4::new(self.x, self.x, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xxyy(self) -> Vec4 {
         Vec4::new(self.x, self.x, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xxyz(self) -> Vec4 {
         Vec4::new(self.x, self.x, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xxzx(self) -> Vec4 {
         Vec4::new(self.x, self.x, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xxzy(self) -> Vec4 {
         Vec4::new(self.x, self.x, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xxzz(self) -> Vec4 {
         Vec4::new(self.x, self.x, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xyxx(self) -> Vec4 {
         Vec4::new(self.x, self.y, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xyxy(self) -> Vec4 {
         Vec4::new(self.x, self.y, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xyxz(self) -> Vec4 {
         Vec4::new(self.x, self.y, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xyyx(self) -> Vec4 {
         Vec4::new(self.x, self.y, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xyyy(self) -> Vec4 {
         Vec4::new(self.x, self.y, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xyyz(self) -> Vec4 {
         Vec4::new(self.x, self.y, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xyzx(self) -> Vec4 {
         Vec4::new(self.x, self.y, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xyzy(self) -> Vec4 {
         Vec4::new(self.x, self.y, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xyzz(self) -> Vec4 {
         Vec4::new(self.x, self.y, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xzxx(self) -> Vec4 {
         Vec4::new(self.x, self.z, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xzxy(self) -> Vec4 {
         Vec4::new(self.x, self.z, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xzxz(self) -> Vec4 {
         Vec4::new(self.x, self.z, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xzyx(self) -> Vec4 {
         Vec4::new(self.x, self.z, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xzyy(self) -> Vec4 {
         Vec4::new(self.x, self.z, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xzyz(self) -> Vec4 {
         Vec4::new(self.x, self.z, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xzzx(self) -> Vec4 {
         Vec4::new(self.x, self.z, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xzzy(self) -> Vec4 {
         Vec4::new(self.x, self.z, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xzzz(self) -> Vec4 {
         Vec4::new(self.x, self.z, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yxxx(self) -> Vec4 {
         Vec4::new(self.y, self.x, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yxxy(self) -> Vec4 {
         Vec4::new(self.y, self.x, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yxxz(self) -> Vec4 {
         Vec4::new(self.y, self.x, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yxyx(self) -> Vec4 {
         Vec4::new(self.y, self.x, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yxyy(self) -> Vec4 {
         Vec4::new(self.y, self.x, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yxyz(self) -> Vec4 {
         Vec4::new(self.y, self.x, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yxzx(self) -> Vec4 {
         Vec4::new(self.y, self.x, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yxzy(self) -> Vec4 {
         Vec4::new(self.y, self.x, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yxzz(self) -> Vec4 {
         Vec4::new(self.y, self.x, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yyxx(self) -> Vec4 {
         Vec4::new(self.y, self.y, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yyxy(self) -> Vec4 {
         Vec4::new(self.y, self.y, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yyxz(self) -> Vec4 {
         Vec4::new(self.y, self.y, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yyyx(self) -> Vec4 {
         Vec4::new(self.y, self.y, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yyyy(self) -> Vec4 {
         Vec4::new(self.y, self.y, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yyyz(self) -> Vec4 {
         Vec4::new(self.y, self.y, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yyzx(self) -> Vec4 {
         Vec4::new(self.y, self.y, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yyzy(self) -> Vec4 {
         Vec4::new(self.y, self.y, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yyzz(self) -> Vec4 {
         Vec4::new(self.y, self.y, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yzxx(self) -> Vec4 {
         Vec4::new(self.y, self.z, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yzxy(self) -> Vec4 {
         Vec4::new(self.y, self.z, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yzxz(self) -> Vec4 {
         Vec4::new(self.y, self.z, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yzyx(self) -> Vec4 {
         Vec4::new(self.y, self.z, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yzyy(self) -> Vec4 {
         Vec4::new(self.y, self.z, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yzyz(self) -> Vec4 {
         Vec4::new(self.y, self.z, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yzzx(self) -> Vec4 {
         Vec4::new(self.y, self.z, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yzzy(self) -> Vec4 {
         Vec4::new(self.y, self.z, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yzzz(self) -> Vec4 {
         Vec4::new(self.y, self.z, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zxxx(self) -> Vec4 {
         Vec4::new(self.z, self.x, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zxxy(self) -> Vec4 {
         Vec4::new(self.z, self.x, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zxxz(self) -> Vec4 {
         Vec4::new(self.z, self.x, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zxyx(self) -> Vec4 {
         Vec4::new(self.z, self.x, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zxyy(self) -> Vec4 {
         Vec4::new(self.z, self.x, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zxyz(self) -> Vec4 {
         Vec4::new(self.z, self.x, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zxzx(self) -> Vec4 {
         Vec4::new(self.z, self.x, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zxzy(self) -> Vec4 {
         Vec4::new(self.z, self.x, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zxzz(self) -> Vec4 {
         Vec4::new(self.z, self.x, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zyxx(self) -> Vec4 {
         Vec4::new(self.z, self.y, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zyxy(self) -> Vec4 {
         Vec4::new(self.z, self.y, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zyxz(self) -> Vec4 {
         Vec4::new(self.z, self.y, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zyyx(self) -> Vec4 {
         Vec4::new(self.z, self.y, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zyyy(self) -> Vec4 {
         Vec4::new(self.z, self.y, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zyyz(self) -> Vec4 {
         Vec4::new(self.z, self.y, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zyzx(self) -> Vec4 {
         Vec4::new(self.z, self.y, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zyzy(self) -> Vec4 {
         Vec4::new(self.z, self.y, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zyzz(self) -> Vec4 {
         Vec4::new(self.z, self.y, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zzxx(self) -> Vec4 {
         Vec4::new(self.z, self.z, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zzxy(self) -> Vec4 {
         Vec4::new(self.z, self.z, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zzxz(self) -> Vec4 {
         Vec4::new(self.z, self.z, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zzyx(self) -> Vec4 {
         Vec4::new(self.z, self.z, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zzyy(self) -> Vec4 {
         Vec4::new(self.z, self.z, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zzyz(self) -> Vec4 {
         Vec4::new(self.z, self.z, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zzzx(self) -> Vec4 {
         Vec4::new(self.z, self.z, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zzzy(self) -> Vec4 {
         Vec4::new(self.z, self.z, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zzzz(self) -> Vec4 {
         Vec4::new(self.z, self.z, self.z, self.z)
     }
diff --git a/src/swizzles/scalar/vec4_impl.rs b/src/swizzles/scalar/vec4_impl.rs
index 03a8e6c..b18862a 100644
--- a/src/swizzles/scalar/vec4_impl.rs
+++ b/src/swizzles/scalar/vec4_impl.rs
@@ -8,6 +8,7 @@
     type Vec3 = Vec3;
 
     #[inline]
+    #[must_use]
     fn xx(self) -> Vec2 {
         Vec2 {
             x: self.x,
@@ -16,6 +17,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xy(self) -> Vec2 {
         Vec2 {
             x: self.x,
@@ -24,6 +26,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xz(self) -> Vec2 {
         Vec2 {
             x: self.x,
@@ -32,6 +35,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xw(self) -> Vec2 {
         Vec2 {
             x: self.x,
@@ -40,6 +44,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yx(self) -> Vec2 {
         Vec2 {
             x: self.y,
@@ -48,6 +53,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yy(self) -> Vec2 {
         Vec2 {
             x: self.y,
@@ -56,6 +62,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yz(self) -> Vec2 {
         Vec2 {
             x: self.y,
@@ -64,6 +71,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yw(self) -> Vec2 {
         Vec2 {
             x: self.y,
@@ -72,6 +80,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zx(self) -> Vec2 {
         Vec2 {
             x: self.z,
@@ -80,6 +89,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zy(self) -> Vec2 {
         Vec2 {
             x: self.z,
@@ -88,6 +98,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zz(self) -> Vec2 {
         Vec2 {
             x: self.z,
@@ -96,6 +107,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zw(self) -> Vec2 {
         Vec2 {
             x: self.z,
@@ -104,6 +116,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wx(self) -> Vec2 {
         Vec2 {
             x: self.w,
@@ -112,6 +125,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wy(self) -> Vec2 {
         Vec2 {
             x: self.w,
@@ -120,6 +134,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wz(self) -> Vec2 {
         Vec2 {
             x: self.w,
@@ -128,6 +143,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn ww(self) -> Vec2 {
         Vec2 {
             x: self.w,
@@ -136,6 +152,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxx(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -145,6 +162,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxy(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -154,6 +172,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxz(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -163,6 +182,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxw(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -172,6 +192,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyx(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -181,6 +202,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyy(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -190,6 +212,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyz(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -199,6 +222,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyw(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -208,6 +232,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzx(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -217,6 +242,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzy(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -226,6 +252,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzz(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -235,6 +262,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzw(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -244,6 +272,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xwx(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -253,6 +282,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xwy(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -262,6 +292,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xwz(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -271,6 +302,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xww(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -280,6 +312,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxx(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -289,6 +322,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxy(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -298,6 +332,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxz(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -307,6 +342,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxw(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -316,6 +352,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyx(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -325,6 +362,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyy(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -334,6 +372,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyz(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -343,6 +382,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyw(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -352,6 +392,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzx(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -361,6 +402,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzy(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -370,6 +412,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzz(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -379,6 +422,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzw(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -388,6 +432,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn ywx(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -397,6 +442,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn ywy(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -406,6 +452,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn ywz(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -415,6 +462,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yww(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -424,6 +472,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxx(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -433,6 +482,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxy(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -442,6 +492,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxz(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -451,6 +502,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxw(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -460,6 +512,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyx(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -469,6 +522,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyy(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -478,6 +532,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyz(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -487,6 +542,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyw(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -496,6 +552,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzx(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -505,6 +562,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzy(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -514,6 +572,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzz(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -523,6 +582,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzw(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -532,6 +592,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zwx(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -541,6 +602,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zwy(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -550,6 +612,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zwz(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -559,6 +622,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zww(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -568,6 +632,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wxx(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -577,6 +642,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wxy(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -586,6 +652,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wxz(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -595,6 +662,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wxw(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -604,6 +672,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wyx(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -613,6 +682,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wyy(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -622,6 +692,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wyz(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -631,6 +702,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wyw(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -640,6 +712,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wzx(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -649,6 +722,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wzy(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -658,6 +732,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wzz(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -667,6 +742,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wzw(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -676,6 +752,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wwx(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -685,6 +762,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wwy(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -694,6 +772,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wwz(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -703,6 +782,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn www(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -712,1281 +792,1537 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxxx(self) -> Vec4 {
         Vec4::new(self.x, self.x, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xxxy(self) -> Vec4 {
         Vec4::new(self.x, self.x, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xxxz(self) -> Vec4 {
         Vec4::new(self.x, self.x, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xxxw(self) -> Vec4 {
         Vec4::new(self.x, self.x, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xxyx(self) -> Vec4 {
         Vec4::new(self.x, self.x, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xxyy(self) -> Vec4 {
         Vec4::new(self.x, self.x, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xxyz(self) -> Vec4 {
         Vec4::new(self.x, self.x, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xxyw(self) -> Vec4 {
         Vec4::new(self.x, self.x, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xxzx(self) -> Vec4 {
         Vec4::new(self.x, self.x, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xxzy(self) -> Vec4 {
         Vec4::new(self.x, self.x, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xxzz(self) -> Vec4 {
         Vec4::new(self.x, self.x, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xxzw(self) -> Vec4 {
         Vec4::new(self.x, self.x, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xxwx(self) -> Vec4 {
         Vec4::new(self.x, self.x, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xxwy(self) -> Vec4 {
         Vec4::new(self.x, self.x, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xxwz(self) -> Vec4 {
         Vec4::new(self.x, self.x, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xxww(self) -> Vec4 {
         Vec4::new(self.x, self.x, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xyxx(self) -> Vec4 {
         Vec4::new(self.x, self.y, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xyxy(self) -> Vec4 {
         Vec4::new(self.x, self.y, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xyxz(self) -> Vec4 {
         Vec4::new(self.x, self.y, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xyxw(self) -> Vec4 {
         Vec4::new(self.x, self.y, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xyyx(self) -> Vec4 {
         Vec4::new(self.x, self.y, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xyyy(self) -> Vec4 {
         Vec4::new(self.x, self.y, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xyyz(self) -> Vec4 {
         Vec4::new(self.x, self.y, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xyyw(self) -> Vec4 {
         Vec4::new(self.x, self.y, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xyzx(self) -> Vec4 {
         Vec4::new(self.x, self.y, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xyzy(self) -> Vec4 {
         Vec4::new(self.x, self.y, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xyzz(self) -> Vec4 {
         Vec4::new(self.x, self.y, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xyzw(self) -> Vec4 {
         Vec4::new(self.x, self.y, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xywx(self) -> Vec4 {
         Vec4::new(self.x, self.y, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xywy(self) -> Vec4 {
         Vec4::new(self.x, self.y, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xywz(self) -> Vec4 {
         Vec4::new(self.x, self.y, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xyww(self) -> Vec4 {
         Vec4::new(self.x, self.y, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xzxx(self) -> Vec4 {
         Vec4::new(self.x, self.z, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xzxy(self) -> Vec4 {
         Vec4::new(self.x, self.z, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xzxz(self) -> Vec4 {
         Vec4::new(self.x, self.z, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xzxw(self) -> Vec4 {
         Vec4::new(self.x, self.z, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xzyx(self) -> Vec4 {
         Vec4::new(self.x, self.z, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xzyy(self) -> Vec4 {
         Vec4::new(self.x, self.z, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xzyz(self) -> Vec4 {
         Vec4::new(self.x, self.z, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xzyw(self) -> Vec4 {
         Vec4::new(self.x, self.z, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xzzx(self) -> Vec4 {
         Vec4::new(self.x, self.z, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xzzy(self) -> Vec4 {
         Vec4::new(self.x, self.z, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xzzz(self) -> Vec4 {
         Vec4::new(self.x, self.z, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xzzw(self) -> Vec4 {
         Vec4::new(self.x, self.z, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xzwx(self) -> Vec4 {
         Vec4::new(self.x, self.z, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xzwy(self) -> Vec4 {
         Vec4::new(self.x, self.z, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xzwz(self) -> Vec4 {
         Vec4::new(self.x, self.z, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xzww(self) -> Vec4 {
         Vec4::new(self.x, self.z, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xwxx(self) -> Vec4 {
         Vec4::new(self.x, self.w, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xwxy(self) -> Vec4 {
         Vec4::new(self.x, self.w, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xwxz(self) -> Vec4 {
         Vec4::new(self.x, self.w, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xwxw(self) -> Vec4 {
         Vec4::new(self.x, self.w, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xwyx(self) -> Vec4 {
         Vec4::new(self.x, self.w, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xwyy(self) -> Vec4 {
         Vec4::new(self.x, self.w, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xwyz(self) -> Vec4 {
         Vec4::new(self.x, self.w, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xwyw(self) -> Vec4 {
         Vec4::new(self.x, self.w, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xwzx(self) -> Vec4 {
         Vec4::new(self.x, self.w, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xwzy(self) -> Vec4 {
         Vec4::new(self.x, self.w, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xwzz(self) -> Vec4 {
         Vec4::new(self.x, self.w, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xwzw(self) -> Vec4 {
         Vec4::new(self.x, self.w, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xwwx(self) -> Vec4 {
         Vec4::new(self.x, self.w, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xwwy(self) -> Vec4 {
         Vec4::new(self.x, self.w, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xwwz(self) -> Vec4 {
         Vec4::new(self.x, self.w, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xwww(self) -> Vec4 {
         Vec4::new(self.x, self.w, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yxxx(self) -> Vec4 {
         Vec4::new(self.y, self.x, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yxxy(self) -> Vec4 {
         Vec4::new(self.y, self.x, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yxxz(self) -> Vec4 {
         Vec4::new(self.y, self.x, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yxxw(self) -> Vec4 {
         Vec4::new(self.y, self.x, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yxyx(self) -> Vec4 {
         Vec4::new(self.y, self.x, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yxyy(self) -> Vec4 {
         Vec4::new(self.y, self.x, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yxyz(self) -> Vec4 {
         Vec4::new(self.y, self.x, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yxyw(self) -> Vec4 {
         Vec4::new(self.y, self.x, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yxzx(self) -> Vec4 {
         Vec4::new(self.y, self.x, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yxzy(self) -> Vec4 {
         Vec4::new(self.y, self.x, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yxzz(self) -> Vec4 {
         Vec4::new(self.y, self.x, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yxzw(self) -> Vec4 {
         Vec4::new(self.y, self.x, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yxwx(self) -> Vec4 {
         Vec4::new(self.y, self.x, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yxwy(self) -> Vec4 {
         Vec4::new(self.y, self.x, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yxwz(self) -> Vec4 {
         Vec4::new(self.y, self.x, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yxww(self) -> Vec4 {
         Vec4::new(self.y, self.x, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yyxx(self) -> Vec4 {
         Vec4::new(self.y, self.y, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yyxy(self) -> Vec4 {
         Vec4::new(self.y, self.y, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yyxz(self) -> Vec4 {
         Vec4::new(self.y, self.y, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yyxw(self) -> Vec4 {
         Vec4::new(self.y, self.y, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yyyx(self) -> Vec4 {
         Vec4::new(self.y, self.y, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yyyy(self) -> Vec4 {
         Vec4::new(self.y, self.y, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yyyz(self) -> Vec4 {
         Vec4::new(self.y, self.y, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yyyw(self) -> Vec4 {
         Vec4::new(self.y, self.y, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yyzx(self) -> Vec4 {
         Vec4::new(self.y, self.y, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yyzy(self) -> Vec4 {
         Vec4::new(self.y, self.y, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yyzz(self) -> Vec4 {
         Vec4::new(self.y, self.y, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yyzw(self) -> Vec4 {
         Vec4::new(self.y, self.y, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yywx(self) -> Vec4 {
         Vec4::new(self.y, self.y, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yywy(self) -> Vec4 {
         Vec4::new(self.y, self.y, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yywz(self) -> Vec4 {
         Vec4::new(self.y, self.y, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yyww(self) -> Vec4 {
         Vec4::new(self.y, self.y, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yzxx(self) -> Vec4 {
         Vec4::new(self.y, self.z, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yzxy(self) -> Vec4 {
         Vec4::new(self.y, self.z, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yzxz(self) -> Vec4 {
         Vec4::new(self.y, self.z, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yzxw(self) -> Vec4 {
         Vec4::new(self.y, self.z, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yzyx(self) -> Vec4 {
         Vec4::new(self.y, self.z, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yzyy(self) -> Vec4 {
         Vec4::new(self.y, self.z, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yzyz(self) -> Vec4 {
         Vec4::new(self.y, self.z, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yzyw(self) -> Vec4 {
         Vec4::new(self.y, self.z, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yzzx(self) -> Vec4 {
         Vec4::new(self.y, self.z, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yzzy(self) -> Vec4 {
         Vec4::new(self.y, self.z, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yzzz(self) -> Vec4 {
         Vec4::new(self.y, self.z, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yzzw(self) -> Vec4 {
         Vec4::new(self.y, self.z, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yzwx(self) -> Vec4 {
         Vec4::new(self.y, self.z, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yzwy(self) -> Vec4 {
         Vec4::new(self.y, self.z, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yzwz(self) -> Vec4 {
         Vec4::new(self.y, self.z, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yzww(self) -> Vec4 {
         Vec4::new(self.y, self.z, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn ywxx(self) -> Vec4 {
         Vec4::new(self.y, self.w, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn ywxy(self) -> Vec4 {
         Vec4::new(self.y, self.w, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn ywxz(self) -> Vec4 {
         Vec4::new(self.y, self.w, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn ywxw(self) -> Vec4 {
         Vec4::new(self.y, self.w, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn ywyx(self) -> Vec4 {
         Vec4::new(self.y, self.w, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn ywyy(self) -> Vec4 {
         Vec4::new(self.y, self.w, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn ywyz(self) -> Vec4 {
         Vec4::new(self.y, self.w, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn ywyw(self) -> Vec4 {
         Vec4::new(self.y, self.w, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn ywzx(self) -> Vec4 {
         Vec4::new(self.y, self.w, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn ywzy(self) -> Vec4 {
         Vec4::new(self.y, self.w, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn ywzz(self) -> Vec4 {
         Vec4::new(self.y, self.w, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn ywzw(self) -> Vec4 {
         Vec4::new(self.y, self.w, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn ywwx(self) -> Vec4 {
         Vec4::new(self.y, self.w, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn ywwy(self) -> Vec4 {
         Vec4::new(self.y, self.w, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn ywwz(self) -> Vec4 {
         Vec4::new(self.y, self.w, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn ywww(self) -> Vec4 {
         Vec4::new(self.y, self.w, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zxxx(self) -> Vec4 {
         Vec4::new(self.z, self.x, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zxxy(self) -> Vec4 {
         Vec4::new(self.z, self.x, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zxxz(self) -> Vec4 {
         Vec4::new(self.z, self.x, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zxxw(self) -> Vec4 {
         Vec4::new(self.z, self.x, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zxyx(self) -> Vec4 {
         Vec4::new(self.z, self.x, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zxyy(self) -> Vec4 {
         Vec4::new(self.z, self.x, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zxyz(self) -> Vec4 {
         Vec4::new(self.z, self.x, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zxyw(self) -> Vec4 {
         Vec4::new(self.z, self.x, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zxzx(self) -> Vec4 {
         Vec4::new(self.z, self.x, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zxzy(self) -> Vec4 {
         Vec4::new(self.z, self.x, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zxzz(self) -> Vec4 {
         Vec4::new(self.z, self.x, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zxzw(self) -> Vec4 {
         Vec4::new(self.z, self.x, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zxwx(self) -> Vec4 {
         Vec4::new(self.z, self.x, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zxwy(self) -> Vec4 {
         Vec4::new(self.z, self.x, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zxwz(self) -> Vec4 {
         Vec4::new(self.z, self.x, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zxww(self) -> Vec4 {
         Vec4::new(self.z, self.x, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zyxx(self) -> Vec4 {
         Vec4::new(self.z, self.y, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zyxy(self) -> Vec4 {
         Vec4::new(self.z, self.y, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zyxz(self) -> Vec4 {
         Vec4::new(self.z, self.y, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zyxw(self) -> Vec4 {
         Vec4::new(self.z, self.y, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zyyx(self) -> Vec4 {
         Vec4::new(self.z, self.y, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zyyy(self) -> Vec4 {
         Vec4::new(self.z, self.y, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zyyz(self) -> Vec4 {
         Vec4::new(self.z, self.y, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zyyw(self) -> Vec4 {
         Vec4::new(self.z, self.y, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zyzx(self) -> Vec4 {
         Vec4::new(self.z, self.y, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zyzy(self) -> Vec4 {
         Vec4::new(self.z, self.y, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zyzz(self) -> Vec4 {
         Vec4::new(self.z, self.y, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zyzw(self) -> Vec4 {
         Vec4::new(self.z, self.y, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zywx(self) -> Vec4 {
         Vec4::new(self.z, self.y, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zywy(self) -> Vec4 {
         Vec4::new(self.z, self.y, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zywz(self) -> Vec4 {
         Vec4::new(self.z, self.y, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zyww(self) -> Vec4 {
         Vec4::new(self.z, self.y, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zzxx(self) -> Vec4 {
         Vec4::new(self.z, self.z, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zzxy(self) -> Vec4 {
         Vec4::new(self.z, self.z, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zzxz(self) -> Vec4 {
         Vec4::new(self.z, self.z, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zzxw(self) -> Vec4 {
         Vec4::new(self.z, self.z, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zzyx(self) -> Vec4 {
         Vec4::new(self.z, self.z, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zzyy(self) -> Vec4 {
         Vec4::new(self.z, self.z, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zzyz(self) -> Vec4 {
         Vec4::new(self.z, self.z, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zzyw(self) -> Vec4 {
         Vec4::new(self.z, self.z, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zzzx(self) -> Vec4 {
         Vec4::new(self.z, self.z, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zzzy(self) -> Vec4 {
         Vec4::new(self.z, self.z, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zzzz(self) -> Vec4 {
         Vec4::new(self.z, self.z, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zzzw(self) -> Vec4 {
         Vec4::new(self.z, self.z, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zzwx(self) -> Vec4 {
         Vec4::new(self.z, self.z, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zzwy(self) -> Vec4 {
         Vec4::new(self.z, self.z, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zzwz(self) -> Vec4 {
         Vec4::new(self.z, self.z, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zzww(self) -> Vec4 {
         Vec4::new(self.z, self.z, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zwxx(self) -> Vec4 {
         Vec4::new(self.z, self.w, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zwxy(self) -> Vec4 {
         Vec4::new(self.z, self.w, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zwxz(self) -> Vec4 {
         Vec4::new(self.z, self.w, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zwxw(self) -> Vec4 {
         Vec4::new(self.z, self.w, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zwyx(self) -> Vec4 {
         Vec4::new(self.z, self.w, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zwyy(self) -> Vec4 {
         Vec4::new(self.z, self.w, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zwyz(self) -> Vec4 {
         Vec4::new(self.z, self.w, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zwyw(self) -> Vec4 {
         Vec4::new(self.z, self.w, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zwzx(self) -> Vec4 {
         Vec4::new(self.z, self.w, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zwzy(self) -> Vec4 {
         Vec4::new(self.z, self.w, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zwzz(self) -> Vec4 {
         Vec4::new(self.z, self.w, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zwzw(self) -> Vec4 {
         Vec4::new(self.z, self.w, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zwwx(self) -> Vec4 {
         Vec4::new(self.z, self.w, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zwwy(self) -> Vec4 {
         Vec4::new(self.z, self.w, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zwwz(self) -> Vec4 {
         Vec4::new(self.z, self.w, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zwww(self) -> Vec4 {
         Vec4::new(self.z, self.w, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wxxx(self) -> Vec4 {
         Vec4::new(self.w, self.x, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wxxy(self) -> Vec4 {
         Vec4::new(self.w, self.x, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wxxz(self) -> Vec4 {
         Vec4::new(self.w, self.x, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wxxw(self) -> Vec4 {
         Vec4::new(self.w, self.x, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wxyx(self) -> Vec4 {
         Vec4::new(self.w, self.x, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wxyy(self) -> Vec4 {
         Vec4::new(self.w, self.x, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wxyz(self) -> Vec4 {
         Vec4::new(self.w, self.x, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wxyw(self) -> Vec4 {
         Vec4::new(self.w, self.x, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wxzx(self) -> Vec4 {
         Vec4::new(self.w, self.x, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wxzy(self) -> Vec4 {
         Vec4::new(self.w, self.x, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wxzz(self) -> Vec4 {
         Vec4::new(self.w, self.x, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wxzw(self) -> Vec4 {
         Vec4::new(self.w, self.x, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wxwx(self) -> Vec4 {
         Vec4::new(self.w, self.x, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wxwy(self) -> Vec4 {
         Vec4::new(self.w, self.x, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wxwz(self) -> Vec4 {
         Vec4::new(self.w, self.x, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wxww(self) -> Vec4 {
         Vec4::new(self.w, self.x, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wyxx(self) -> Vec4 {
         Vec4::new(self.w, self.y, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wyxy(self) -> Vec4 {
         Vec4::new(self.w, self.y, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wyxz(self) -> Vec4 {
         Vec4::new(self.w, self.y, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wyxw(self) -> Vec4 {
         Vec4::new(self.w, self.y, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wyyx(self) -> Vec4 {
         Vec4::new(self.w, self.y, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wyyy(self) -> Vec4 {
         Vec4::new(self.w, self.y, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wyyz(self) -> Vec4 {
         Vec4::new(self.w, self.y, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wyyw(self) -> Vec4 {
         Vec4::new(self.w, self.y, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wyzx(self) -> Vec4 {
         Vec4::new(self.w, self.y, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wyzy(self) -> Vec4 {
         Vec4::new(self.w, self.y, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wyzz(self) -> Vec4 {
         Vec4::new(self.w, self.y, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wyzw(self) -> Vec4 {
         Vec4::new(self.w, self.y, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wywx(self) -> Vec4 {
         Vec4::new(self.w, self.y, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wywy(self) -> Vec4 {
         Vec4::new(self.w, self.y, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wywz(self) -> Vec4 {
         Vec4::new(self.w, self.y, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wyww(self) -> Vec4 {
         Vec4::new(self.w, self.y, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wzxx(self) -> Vec4 {
         Vec4::new(self.w, self.z, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wzxy(self) -> Vec4 {
         Vec4::new(self.w, self.z, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wzxz(self) -> Vec4 {
         Vec4::new(self.w, self.z, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wzxw(self) -> Vec4 {
         Vec4::new(self.w, self.z, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wzyx(self) -> Vec4 {
         Vec4::new(self.w, self.z, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wzyy(self) -> Vec4 {
         Vec4::new(self.w, self.z, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wzyz(self) -> Vec4 {
         Vec4::new(self.w, self.z, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wzyw(self) -> Vec4 {
         Vec4::new(self.w, self.z, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wzzx(self) -> Vec4 {
         Vec4::new(self.w, self.z, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wzzy(self) -> Vec4 {
         Vec4::new(self.w, self.z, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wzzz(self) -> Vec4 {
         Vec4::new(self.w, self.z, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wzzw(self) -> Vec4 {
         Vec4::new(self.w, self.z, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wzwx(self) -> Vec4 {
         Vec4::new(self.w, self.z, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wzwy(self) -> Vec4 {
         Vec4::new(self.w, self.z, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wzwz(self) -> Vec4 {
         Vec4::new(self.w, self.z, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wzww(self) -> Vec4 {
         Vec4::new(self.w, self.z, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wwxx(self) -> Vec4 {
         Vec4::new(self.w, self.w, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wwxy(self) -> Vec4 {
         Vec4::new(self.w, self.w, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wwxz(self) -> Vec4 {
         Vec4::new(self.w, self.w, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wwxw(self) -> Vec4 {
         Vec4::new(self.w, self.w, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wwyx(self) -> Vec4 {
         Vec4::new(self.w, self.w, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wwyy(self) -> Vec4 {
         Vec4::new(self.w, self.w, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wwyz(self) -> Vec4 {
         Vec4::new(self.w, self.w, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wwyw(self) -> Vec4 {
         Vec4::new(self.w, self.w, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wwzx(self) -> Vec4 {
         Vec4::new(self.w, self.w, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wwzy(self) -> Vec4 {
         Vec4::new(self.w, self.w, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wwzz(self) -> Vec4 {
         Vec4::new(self.w, self.w, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wwzw(self) -> Vec4 {
         Vec4::new(self.w, self.w, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wwwx(self) -> Vec4 {
         Vec4::new(self.w, self.w, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wwwy(self) -> Vec4 {
         Vec4::new(self.w, self.w, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wwwz(self) -> Vec4 {
         Vec4::new(self.w, self.w, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wwww(self) -> Vec4 {
         Vec4::new(self.w, self.w, self.w, self.w)
     }
diff --git a/src/swizzles/sse2/vec3a_impl.rs b/src/swizzles/sse2/vec3a_impl.rs
index da70b6f..7ae6379 100644
--- a/src/swizzles/sse2/vec3a_impl.rs
+++ b/src/swizzles/sse2/vec3a_impl.rs
@@ -15,6 +15,7 @@
     type Vec4 = Vec4;
 
     #[inline]
+    #[must_use]
     fn xx(self) -> Vec2 {
         Vec2 {
             x: self.x,
@@ -23,6 +24,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xy(self) -> Vec2 {
         Vec2 {
             x: self.x,
@@ -31,6 +33,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xz(self) -> Vec2 {
         Vec2 {
             x: self.x,
@@ -39,6 +42,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yx(self) -> Vec2 {
         Vec2 {
             x: self.y,
@@ -47,6 +51,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yy(self) -> Vec2 {
         Vec2 {
             x: self.y,
@@ -55,6 +60,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yz(self) -> Vec2 {
         Vec2 {
             x: self.y,
@@ -63,6 +69,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zx(self) -> Vec2 {
         Vec2 {
             x: self.z,
@@ -71,6 +78,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zy(self) -> Vec2 {
         Vec2 {
             x: self.z,
@@ -79,6 +87,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zz(self) -> Vec2 {
         Vec2 {
             x: self.z,
@@ -87,541 +96,649 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxx(self) -> Vec3A {
         Vec3A((unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_00_00_00) }).into())
     }
 
     #[inline]
+    #[must_use]
     fn xxy(self) -> Vec3A {
         Vec3A((unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_01_00_00) }).into())
     }
 
     #[inline]
+    #[must_use]
     fn xxz(self) -> Vec3A {
         Vec3A((unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_10_00_00) }).into())
     }
 
     #[inline]
+    #[must_use]
     fn xyx(self) -> Vec3A {
         Vec3A((unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_00_01_00) }).into())
     }
 
     #[inline]
+    #[must_use]
     fn xyy(self) -> Vec3A {
         Vec3A((unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_01_01_00) }).into())
     }
 
     #[inline]
+    #[must_use]
     fn xyz(self) -> Vec3A {
         Vec3A((unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_10_01_00) }).into())
     }
 
     #[inline]
+    #[must_use]
     fn xzx(self) -> Vec3A {
         Vec3A((unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_00_10_00) }).into())
     }
 
     #[inline]
+    #[must_use]
     fn xzy(self) -> Vec3A {
         Vec3A((unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_01_10_00) }).into())
     }
 
     #[inline]
+    #[must_use]
     fn xzz(self) -> Vec3A {
         Vec3A((unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_10_10_00) }).into())
     }
 
     #[inline]
+    #[must_use]
     fn yxx(self) -> Vec3A {
         Vec3A((unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_00_00_01) }).into())
     }
 
     #[inline]
+    #[must_use]
     fn yxy(self) -> Vec3A {
         Vec3A((unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_01_00_01) }).into())
     }
 
     #[inline]
+    #[must_use]
     fn yxz(self) -> Vec3A {
         Vec3A((unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_10_00_01) }).into())
     }
 
     #[inline]
+    #[must_use]
     fn yyx(self) -> Vec3A {
         Vec3A((unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_00_01_01) }).into())
     }
 
     #[inline]
+    #[must_use]
     fn yyy(self) -> Vec3A {
         Vec3A((unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_01_01_01) }).into())
     }
 
     #[inline]
+    #[must_use]
     fn yyz(self) -> Vec3A {
         Vec3A((unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_10_01_01) }).into())
     }
 
     #[inline]
+    #[must_use]
     fn yzx(self) -> Vec3A {
         Vec3A((unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_00_10_01) }).into())
     }
 
     #[inline]
+    #[must_use]
     fn yzy(self) -> Vec3A {
         Vec3A((unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_01_10_01) }).into())
     }
 
     #[inline]
+    #[must_use]
     fn yzz(self) -> Vec3A {
         Vec3A((unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_10_10_01) }).into())
     }
 
     #[inline]
+    #[must_use]
     fn zxx(self) -> Vec3A {
         Vec3A((unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_00_00_10) }).into())
     }
 
     #[inline]
+    #[must_use]
     fn zxy(self) -> Vec3A {
         Vec3A((unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_01_00_10) }).into())
     }
 
     #[inline]
+    #[must_use]
     fn zxz(self) -> Vec3A {
         Vec3A((unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_10_00_10) }).into())
     }
 
     #[inline]
+    #[must_use]
     fn zyx(self) -> Vec3A {
         Vec3A((unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_00_01_10) }).into())
     }
 
     #[inline]
+    #[must_use]
     fn zyy(self) -> Vec3A {
         Vec3A((unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_01_01_10) }).into())
     }
 
     #[inline]
+    #[must_use]
     fn zyz(self) -> Vec3A {
         Vec3A((unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_10_01_10) }).into())
     }
 
     #[inline]
+    #[must_use]
     fn zzx(self) -> Vec3A {
         Vec3A((unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_00_10_10) }).into())
     }
 
     #[inline]
+    #[must_use]
     fn zzy(self) -> Vec3A {
         Vec3A((unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_01_10_10) }).into())
     }
 
     #[inline]
+    #[must_use]
     fn zzz(self) -> Vec3A {
         Vec3A((unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_10_10_10) }).into())
     }
 
     #[inline]
+    #[must_use]
     fn xxxx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_00_00_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xxxy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_00_00_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xxxz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_00_00_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xxyx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_01_00_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xxyy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_01_00_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xxyz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_01_00_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xxzx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_10_00_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xxzy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_10_00_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xxzz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_10_00_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xyxx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_00_01_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xyxy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_00_01_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xyxz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_00_01_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xyyx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_01_01_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xyyy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_01_01_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xyyz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_01_01_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xyzx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_10_01_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xyzy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_10_01_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xyzz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_10_01_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xzxx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_00_10_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xzxy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_00_10_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xzxz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_00_10_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xzyx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_01_10_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xzyy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_01_10_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xzyz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_01_10_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xzzx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_10_10_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xzzy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_10_10_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xzzz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_10_10_00) })
     }
 
     #[inline]
+    #[must_use]
     fn yxxx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_00_00_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yxxy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_00_00_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yxxz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_00_00_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yxyx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_01_00_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yxyy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_01_00_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yxyz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_01_00_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yxzx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_10_00_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yxzy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_10_00_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yxzz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_10_00_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yyxx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_00_01_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yyxy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_00_01_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yyxz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_00_01_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yyyx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_01_01_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yyyy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_01_01_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yyyz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_01_01_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yyzx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_10_01_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yyzy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_10_01_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yyzz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_10_01_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yzxx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_00_10_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yzxy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_00_10_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yzxz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_00_10_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yzyx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_01_10_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yzyy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_01_10_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yzyz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_01_10_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yzzx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_10_10_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yzzy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_10_10_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yzzz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_10_10_01) })
     }
 
     #[inline]
+    #[must_use]
     fn zxxx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_00_00_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zxxy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_00_00_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zxxz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_00_00_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zxyx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_01_00_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zxyy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_01_00_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zxyz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_01_00_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zxzx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_10_00_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zxzy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_10_00_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zxzz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_10_00_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zyxx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_00_01_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zyxy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_00_01_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zyxz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_00_01_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zyyx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_01_01_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zyyy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_01_01_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zyyz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_01_01_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zyzx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_10_01_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zyzy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_10_01_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zyzz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_10_01_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zzxx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_00_10_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zzxy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_00_10_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zzxz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_00_10_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zzyx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_01_10_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zzyy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_01_10_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zzyz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_01_10_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zzzx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_10_10_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zzzy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_10_10_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zzzz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_10_10_10) })
     }
diff --git a/src/swizzles/sse2/vec4_impl.rs b/src/swizzles/sse2/vec4_impl.rs
index 9ca3a3d..9220990 100644
--- a/src/swizzles/sse2/vec4_impl.rs
+++ b/src/swizzles/sse2/vec4_impl.rs
@@ -15,6 +15,7 @@
     type Vec3 = Vec3;
 
     #[inline]
+    #[must_use]
     fn xx(self) -> Vec2 {
         Vec2 {
             x: self.x,
@@ -23,6 +24,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xy(self) -> Vec2 {
         Vec2 {
             x: self.x,
@@ -31,6 +33,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xz(self) -> Vec2 {
         Vec2 {
             x: self.x,
@@ -39,6 +42,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xw(self) -> Vec2 {
         Vec2 {
             x: self.x,
@@ -47,6 +51,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yx(self) -> Vec2 {
         Vec2 {
             x: self.y,
@@ -55,6 +60,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yy(self) -> Vec2 {
         Vec2 {
             x: self.y,
@@ -63,6 +69,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yz(self) -> Vec2 {
         Vec2 {
             x: self.y,
@@ -71,6 +78,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yw(self) -> Vec2 {
         Vec2 {
             x: self.y,
@@ -79,6 +87,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zx(self) -> Vec2 {
         Vec2 {
             x: self.z,
@@ -87,6 +96,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zy(self) -> Vec2 {
         Vec2 {
             x: self.z,
@@ -95,6 +105,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zz(self) -> Vec2 {
         Vec2 {
             x: self.z,
@@ -103,6 +114,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zw(self) -> Vec2 {
         Vec2 {
             x: self.z,
@@ -111,6 +123,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wx(self) -> Vec2 {
         Vec2 {
             x: self.w,
@@ -119,6 +132,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wy(self) -> Vec2 {
         Vec2 {
             x: self.w,
@@ -127,6 +141,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wz(self) -> Vec2 {
         Vec2 {
             x: self.w,
@@ -135,6 +150,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn ww(self) -> Vec2 {
         Vec2 {
             x: self.w,
@@ -143,6 +159,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxx(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -152,6 +169,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxy(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -161,6 +179,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxz(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -170,6 +189,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxw(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -179,6 +199,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyx(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -188,6 +209,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyy(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -197,6 +219,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyz(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -206,6 +229,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyw(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -215,6 +239,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzx(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -224,6 +249,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzy(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -233,6 +259,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzz(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -242,6 +269,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzw(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -251,6 +279,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xwx(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -260,6 +289,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xwy(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -269,6 +299,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xwz(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -278,6 +309,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xww(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -287,6 +319,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxx(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -296,6 +329,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxy(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -305,6 +339,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxz(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -314,6 +349,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxw(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -323,6 +359,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyx(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -332,6 +369,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyy(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -341,6 +379,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyz(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -350,6 +389,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyw(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -359,6 +399,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzx(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -368,6 +409,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzy(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -377,6 +419,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzz(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -386,6 +429,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzw(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -395,6 +439,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn ywx(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -404,6 +449,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn ywy(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -413,6 +459,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn ywz(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -422,6 +469,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yww(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -431,6 +479,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxx(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -440,6 +489,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxy(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -449,6 +499,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxz(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -458,6 +509,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxw(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -467,6 +519,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyx(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -476,6 +529,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyy(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -485,6 +539,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyz(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -494,6 +549,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyw(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -503,6 +559,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzx(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -512,6 +569,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzy(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -521,6 +579,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzz(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -530,6 +589,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzw(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -539,6 +599,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zwx(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -548,6 +609,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zwy(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -557,6 +619,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zwz(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -566,6 +629,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zww(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -575,6 +639,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wxx(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -584,6 +649,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wxy(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -593,6 +659,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wxz(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -602,6 +669,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wxw(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -611,6 +679,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wyx(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -620,6 +689,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wyy(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -629,6 +699,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wyz(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -638,6 +709,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wyw(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -647,6 +719,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wzx(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -656,6 +729,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wzy(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -665,6 +739,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wzz(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -674,6 +749,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wzw(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -683,6 +759,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wwx(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -692,6 +769,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wwy(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -701,6 +779,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wwz(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -710,6 +789,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn www(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -719,1281 +799,1537 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxxx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_00_00_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xxxy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_00_00_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xxxz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_00_00_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xxxw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_00_00_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xxyx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_01_00_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xxyy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_01_00_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xxyz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_01_00_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xxyw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_01_00_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xxzx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_10_00_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xxzy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_10_00_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xxzz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_10_00_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xxzw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_10_00_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xxwx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_11_00_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xxwy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_11_00_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xxwz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_11_00_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xxww(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_11_00_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xyxx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_00_01_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xyxy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_00_01_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xyxz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_00_01_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xyxw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_00_01_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xyyx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_01_01_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xyyy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_01_01_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xyyz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_01_01_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xyyw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_01_01_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xyzx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_10_01_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xyzy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_10_01_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xyzz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_10_01_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xyzw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_10_01_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xywx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_11_01_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xywy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_11_01_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xywz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_11_01_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xyww(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_11_01_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xzxx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_00_10_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xzxy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_00_10_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xzxz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_00_10_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xzxw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_00_10_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xzyx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_01_10_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xzyy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_01_10_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xzyz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_01_10_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xzyw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_01_10_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xzzx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_10_10_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xzzy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_10_10_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xzzz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_10_10_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xzzw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_10_10_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xzwx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_11_10_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xzwy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_11_10_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xzwz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_11_10_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xzww(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_11_10_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xwxx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_00_11_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xwxy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_00_11_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xwxz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_00_11_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xwxw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_00_11_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xwyx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_01_11_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xwyy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_01_11_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xwyz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_01_11_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xwyw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_01_11_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xwzx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_10_11_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xwzy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_10_11_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xwzz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_10_11_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xwzw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_10_11_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xwwx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_11_11_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xwwy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_11_11_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xwwz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_11_11_00) })
     }
 
     #[inline]
+    #[must_use]
     fn xwww(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_11_11_00) })
     }
 
     #[inline]
+    #[must_use]
     fn yxxx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_00_00_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yxxy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_00_00_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yxxz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_00_00_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yxxw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_00_00_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yxyx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_01_00_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yxyy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_01_00_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yxyz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_01_00_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yxyw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_01_00_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yxzx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_10_00_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yxzy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_10_00_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yxzz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_10_00_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yxzw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_10_00_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yxwx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_11_00_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yxwy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_11_00_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yxwz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_11_00_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yxww(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_11_00_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yyxx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_00_01_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yyxy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_00_01_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yyxz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_00_01_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yyxw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_00_01_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yyyx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_01_01_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yyyy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_01_01_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yyyz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_01_01_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yyyw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_01_01_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yyzx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_10_01_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yyzy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_10_01_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yyzz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_10_01_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yyzw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_10_01_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yywx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_11_01_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yywy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_11_01_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yywz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_11_01_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yyww(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_11_01_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yzxx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_00_10_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yzxy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_00_10_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yzxz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_00_10_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yzxw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_00_10_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yzyx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_01_10_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yzyy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_01_10_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yzyz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_01_10_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yzyw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_01_10_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yzzx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_10_10_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yzzy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_10_10_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yzzz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_10_10_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yzzw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_10_10_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yzwx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_11_10_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yzwy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_11_10_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yzwz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_11_10_01) })
     }
 
     #[inline]
+    #[must_use]
     fn yzww(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_11_10_01) })
     }
 
     #[inline]
+    #[must_use]
     fn ywxx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_00_11_01) })
     }
 
     #[inline]
+    #[must_use]
     fn ywxy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_00_11_01) })
     }
 
     #[inline]
+    #[must_use]
     fn ywxz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_00_11_01) })
     }
 
     #[inline]
+    #[must_use]
     fn ywxw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_00_11_01) })
     }
 
     #[inline]
+    #[must_use]
     fn ywyx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_01_11_01) })
     }
 
     #[inline]
+    #[must_use]
     fn ywyy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_01_11_01) })
     }
 
     #[inline]
+    #[must_use]
     fn ywyz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_01_11_01) })
     }
 
     #[inline]
+    #[must_use]
     fn ywyw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_01_11_01) })
     }
 
     #[inline]
+    #[must_use]
     fn ywzx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_10_11_01) })
     }
 
     #[inline]
+    #[must_use]
     fn ywzy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_10_11_01) })
     }
 
     #[inline]
+    #[must_use]
     fn ywzz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_10_11_01) })
     }
 
     #[inline]
+    #[must_use]
     fn ywzw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_10_11_01) })
     }
 
     #[inline]
+    #[must_use]
     fn ywwx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_11_11_01) })
     }
 
     #[inline]
+    #[must_use]
     fn ywwy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_11_11_01) })
     }
 
     #[inline]
+    #[must_use]
     fn ywwz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_11_11_01) })
     }
 
     #[inline]
+    #[must_use]
     fn ywww(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_11_11_01) })
     }
 
     #[inline]
+    #[must_use]
     fn zxxx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_00_00_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zxxy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_00_00_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zxxz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_00_00_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zxxw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_00_00_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zxyx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_01_00_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zxyy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_01_00_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zxyz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_01_00_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zxyw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_01_00_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zxzx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_10_00_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zxzy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_10_00_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zxzz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_10_00_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zxzw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_10_00_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zxwx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_11_00_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zxwy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_11_00_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zxwz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_11_00_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zxww(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_11_00_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zyxx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_00_01_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zyxy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_00_01_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zyxz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_00_01_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zyxw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_00_01_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zyyx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_01_01_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zyyy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_01_01_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zyyz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_01_01_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zyyw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_01_01_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zyzx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_10_01_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zyzy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_10_01_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zyzz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_10_01_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zyzw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_10_01_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zywx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_11_01_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zywy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_11_01_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zywz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_11_01_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zyww(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_11_01_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zzxx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_00_10_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zzxy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_00_10_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zzxz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_00_10_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zzxw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_00_10_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zzyx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_01_10_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zzyy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_01_10_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zzyz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_01_10_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zzyw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_01_10_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zzzx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_10_10_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zzzy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_10_10_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zzzz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_10_10_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zzzw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_10_10_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zzwx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_11_10_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zzwy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_11_10_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zzwz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_11_10_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zzww(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_11_10_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zwxx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_00_11_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zwxy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_00_11_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zwxz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_00_11_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zwxw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_00_11_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zwyx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_01_11_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zwyy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_01_11_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zwyz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_01_11_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zwyw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_01_11_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zwzx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_10_11_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zwzy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_10_11_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zwzz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_10_11_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zwzw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_10_11_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zwwx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_11_11_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zwwy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_11_11_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zwwz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_11_11_10) })
     }
 
     #[inline]
+    #[must_use]
     fn zwww(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_11_11_10) })
     }
 
     #[inline]
+    #[must_use]
     fn wxxx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_00_00_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wxxy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_00_00_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wxxz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_00_00_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wxxw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_00_00_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wxyx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_01_00_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wxyy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_01_00_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wxyz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_01_00_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wxyw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_01_00_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wxzx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_10_00_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wxzy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_10_00_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wxzz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_10_00_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wxzw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_10_00_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wxwx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_11_00_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wxwy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_11_00_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wxwz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_11_00_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wxww(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_11_00_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wyxx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_00_01_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wyxy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_00_01_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wyxz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_00_01_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wyxw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_00_01_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wyyx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_01_01_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wyyy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_01_01_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wyyz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_01_01_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wyyw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_01_01_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wyzx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_10_01_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wyzy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_10_01_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wyzz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_10_01_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wyzw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_10_01_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wywx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_11_01_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wywy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_11_01_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wywz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_11_01_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wyww(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_11_01_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wzxx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_00_10_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wzxy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_00_10_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wzxz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_00_10_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wzxw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_00_10_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wzyx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_01_10_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wzyy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_01_10_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wzyz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_01_10_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wzyw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_01_10_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wzzx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_10_10_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wzzy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_10_10_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wzzz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_10_10_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wzzw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_10_10_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wzwx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_11_10_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wzwy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_11_10_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wzwz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_11_10_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wzww(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_11_10_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wwxx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_00_11_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wwxy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_00_11_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wwxz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_00_11_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wwxw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_00_11_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wwyx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_01_11_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wwyy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_01_11_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wwyz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_01_11_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wwyw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_01_11_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wwzx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_10_11_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wwzy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_10_11_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wwzz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_10_11_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wwzw(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_10_11_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wwwx(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_11_11_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wwwy(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b01_11_11_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wwwz(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b10_11_11_11) })
     }
 
     #[inline]
+    #[must_use]
     fn wwww(self) -> Vec4 {
         Vec4(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_11_11_11) })
     }
diff --git a/src/swizzles/u16vec2_impl.rs b/src/swizzles/u16vec2_impl.rs
new file mode 100644
index 0000000..8d47ef7
--- /dev/null
+++ b/src/swizzles/u16vec2_impl.rs
@@ -0,0 +1,221 @@
+// Generated from swizzle_impl.rs.tera template. Edit the template, not the generated file.
+
+use crate::{U16Vec2, U16Vec3, U16Vec4, Vec2Swizzles};
+
+impl Vec2Swizzles for U16Vec2 {
+    type Vec3 = U16Vec3;
+
+    type Vec4 = U16Vec4;
+
+    #[inline]
+    #[must_use]
+    fn xx(self) -> U16Vec2 {
+        U16Vec2 {
+            x: self.x,
+            y: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xy(self) -> U16Vec2 {
+        U16Vec2 {
+            x: self.x,
+            y: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yx(self) -> U16Vec2 {
+        U16Vec2 {
+            x: self.y,
+            y: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yy(self) -> U16Vec2 {
+        U16Vec2 {
+            x: self.y,
+            y: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxx(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.x,
+            y: self.x,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxy(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.x,
+            y: self.x,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyx(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.x,
+            y: self.y,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyy(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.x,
+            y: self.y,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxx(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.y,
+            y: self.x,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxy(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.y,
+            y: self.x,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyx(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.y,
+            y: self.y,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyy(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.y,
+            y: self.y,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxxx(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.x, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxxy(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.x, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxyx(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.x, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxyy(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.x, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyxx(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.y, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyxy(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.y, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyyx(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.y, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyyy(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.y, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxxx(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.x, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxxy(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.x, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxyx(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.x, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxyy(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.x, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyxx(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.y, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyxy(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.y, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyyx(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.y, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyyy(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.y, self.y, self.y)
+    }
+}
diff --git a/src/swizzles/u16vec3_impl.rs b/src/swizzles/u16vec3_impl.rs
new file mode 100644
index 0000000..ae8cdcc
--- /dev/null
+++ b/src/swizzles/u16vec3_impl.rs
@@ -0,0 +1,846 @@
+// Generated from swizzle_impl.rs.tera template. Edit the template, not the generated file.
+
+use crate::{U16Vec2, U16Vec3, U16Vec4, Vec3Swizzles};
+
+impl Vec3Swizzles for U16Vec3 {
+    type Vec2 = U16Vec2;
+
+    type Vec4 = U16Vec4;
+
+    #[inline]
+    #[must_use]
+    fn xx(self) -> U16Vec2 {
+        U16Vec2 {
+            x: self.x,
+            y: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xy(self) -> U16Vec2 {
+        U16Vec2 {
+            x: self.x,
+            y: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xz(self) -> U16Vec2 {
+        U16Vec2 {
+            x: self.x,
+            y: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yx(self) -> U16Vec2 {
+        U16Vec2 {
+            x: self.y,
+            y: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yy(self) -> U16Vec2 {
+        U16Vec2 {
+            x: self.y,
+            y: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yz(self) -> U16Vec2 {
+        U16Vec2 {
+            x: self.y,
+            y: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zx(self) -> U16Vec2 {
+        U16Vec2 {
+            x: self.z,
+            y: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zy(self) -> U16Vec2 {
+        U16Vec2 {
+            x: self.z,
+            y: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zz(self) -> U16Vec2 {
+        U16Vec2 {
+            x: self.z,
+            y: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxx(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.x,
+            y: self.x,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxy(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.x,
+            y: self.x,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxz(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.x,
+            y: self.x,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyx(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.x,
+            y: self.y,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyy(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.x,
+            y: self.y,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyz(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.x,
+            y: self.y,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzx(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.x,
+            y: self.z,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzy(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.x,
+            y: self.z,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzz(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.x,
+            y: self.z,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxx(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.y,
+            y: self.x,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxy(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.y,
+            y: self.x,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxz(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.y,
+            y: self.x,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyx(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.y,
+            y: self.y,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyy(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.y,
+            y: self.y,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyz(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.y,
+            y: self.y,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzx(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.y,
+            y: self.z,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzy(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.y,
+            y: self.z,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzz(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.y,
+            y: self.z,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxx(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.z,
+            y: self.x,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxy(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.z,
+            y: self.x,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxz(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.z,
+            y: self.x,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyx(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.z,
+            y: self.y,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyy(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.z,
+            y: self.y,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyz(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.z,
+            y: self.y,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzx(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.z,
+            y: self.z,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzy(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.z,
+            y: self.z,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzz(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.z,
+            y: self.z,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxxx(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.x, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxxy(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.x, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxxz(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.x, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxyx(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.x, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxyy(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.x, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxyz(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.x, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxzx(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.x, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxzy(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.x, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxzz(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.x, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyxx(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.y, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyxy(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.y, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyxz(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.y, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyyx(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.y, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyyy(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.y, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyyz(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.y, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyzx(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.y, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyzy(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.y, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyzz(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.y, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzxx(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.z, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzxy(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.z, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzxz(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.z, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzyx(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.z, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzyy(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.z, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzyz(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.z, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzzx(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.z, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzzy(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.z, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzzz(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.z, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxxx(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.x, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxxy(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.x, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxxz(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.x, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxyx(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.x, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxyy(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.x, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxyz(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.x, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxzx(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.x, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxzy(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.x, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxzz(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.x, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyxx(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.y, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyxy(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.y, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyxz(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.y, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyyx(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.y, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyyy(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.y, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyyz(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.y, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyzx(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.y, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyzy(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.y, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyzz(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.y, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzxx(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.z, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzxy(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.z, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzxz(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.z, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzyx(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.z, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzyy(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.z, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzyz(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.z, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzzx(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.z, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzzy(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.z, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzzz(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.z, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxxx(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.x, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxxy(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.x, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxxz(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.x, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxyx(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.x, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxyy(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.x, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxyz(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.x, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxzx(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.x, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxzy(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.x, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxzz(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.x, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyxx(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.y, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyxy(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.y, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyxz(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.y, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyyx(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.y, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyyy(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.y, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyyz(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.y, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyzx(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.y, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyzy(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.y, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyzz(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.y, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzxx(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.z, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzxy(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.z, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzxz(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.z, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzyx(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.z, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzyy(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.z, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzyz(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.z, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzzx(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.z, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzzy(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.z, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzzz(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.z, self.z, self.z)
+    }
+}
diff --git a/src/swizzles/u16vec4_impl.rs b/src/swizzles/u16vec4_impl.rs
new file mode 100644
index 0000000..15fd834
--- /dev/null
+++ b/src/swizzles/u16vec4_impl.rs
@@ -0,0 +1,2329 @@
+// Generated from swizzle_impl.rs.tera template. Edit the template, not the generated file.
+
+use crate::{U16Vec2, U16Vec3, U16Vec4, Vec4Swizzles};
+
+impl Vec4Swizzles for U16Vec4 {
+    type Vec2 = U16Vec2;
+
+    type Vec3 = U16Vec3;
+
+    #[inline]
+    #[must_use]
+    fn xx(self) -> U16Vec2 {
+        U16Vec2 {
+            x: self.x,
+            y: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xy(self) -> U16Vec2 {
+        U16Vec2 {
+            x: self.x,
+            y: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xz(self) -> U16Vec2 {
+        U16Vec2 {
+            x: self.x,
+            y: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xw(self) -> U16Vec2 {
+        U16Vec2 {
+            x: self.x,
+            y: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yx(self) -> U16Vec2 {
+        U16Vec2 {
+            x: self.y,
+            y: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yy(self) -> U16Vec2 {
+        U16Vec2 {
+            x: self.y,
+            y: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yz(self) -> U16Vec2 {
+        U16Vec2 {
+            x: self.y,
+            y: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yw(self) -> U16Vec2 {
+        U16Vec2 {
+            x: self.y,
+            y: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zx(self) -> U16Vec2 {
+        U16Vec2 {
+            x: self.z,
+            y: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zy(self) -> U16Vec2 {
+        U16Vec2 {
+            x: self.z,
+            y: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zz(self) -> U16Vec2 {
+        U16Vec2 {
+            x: self.z,
+            y: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zw(self) -> U16Vec2 {
+        U16Vec2 {
+            x: self.z,
+            y: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wx(self) -> U16Vec2 {
+        U16Vec2 {
+            x: self.w,
+            y: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wy(self) -> U16Vec2 {
+        U16Vec2 {
+            x: self.w,
+            y: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wz(self) -> U16Vec2 {
+        U16Vec2 {
+            x: self.w,
+            y: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn ww(self) -> U16Vec2 {
+        U16Vec2 {
+            x: self.w,
+            y: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxx(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.x,
+            y: self.x,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxy(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.x,
+            y: self.x,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxz(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.x,
+            y: self.x,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxw(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.x,
+            y: self.x,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyx(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.x,
+            y: self.y,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyy(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.x,
+            y: self.y,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyz(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.x,
+            y: self.y,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyw(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.x,
+            y: self.y,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzx(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.x,
+            y: self.z,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzy(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.x,
+            y: self.z,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzz(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.x,
+            y: self.z,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzw(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.x,
+            y: self.z,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwx(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.x,
+            y: self.w,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwy(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.x,
+            y: self.w,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwz(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.x,
+            y: self.w,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xww(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.x,
+            y: self.w,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxx(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.y,
+            y: self.x,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxy(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.y,
+            y: self.x,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxz(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.y,
+            y: self.x,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxw(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.y,
+            y: self.x,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyx(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.y,
+            y: self.y,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyy(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.y,
+            y: self.y,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyz(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.y,
+            y: self.y,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyw(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.y,
+            y: self.y,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzx(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.y,
+            y: self.z,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzy(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.y,
+            y: self.z,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzz(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.y,
+            y: self.z,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzw(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.y,
+            y: self.z,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywx(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.y,
+            y: self.w,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywy(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.y,
+            y: self.w,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywz(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.y,
+            y: self.w,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yww(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.y,
+            y: self.w,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxx(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.z,
+            y: self.x,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxy(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.z,
+            y: self.x,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxz(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.z,
+            y: self.x,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxw(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.z,
+            y: self.x,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyx(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.z,
+            y: self.y,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyy(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.z,
+            y: self.y,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyz(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.z,
+            y: self.y,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyw(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.z,
+            y: self.y,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzx(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.z,
+            y: self.z,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzy(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.z,
+            y: self.z,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzz(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.z,
+            y: self.z,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzw(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.z,
+            y: self.z,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwx(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.z,
+            y: self.w,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwy(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.z,
+            y: self.w,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwz(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.z,
+            y: self.w,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zww(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.z,
+            y: self.w,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxx(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.w,
+            y: self.x,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxy(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.w,
+            y: self.x,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxz(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.w,
+            y: self.x,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxw(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.w,
+            y: self.x,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyx(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.w,
+            y: self.y,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyy(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.w,
+            y: self.y,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyz(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.w,
+            y: self.y,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyw(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.w,
+            y: self.y,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzx(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.w,
+            y: self.z,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzy(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.w,
+            y: self.z,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzz(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.w,
+            y: self.z,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzw(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.w,
+            y: self.z,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwx(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.w,
+            y: self.w,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwy(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.w,
+            y: self.w,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwz(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.w,
+            y: self.w,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn www(self) -> U16Vec3 {
+        U16Vec3 {
+            x: self.w,
+            y: self.w,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxxx(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.x, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxxy(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.x, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxxz(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.x, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxxw(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.x, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxyx(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.x, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxyy(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.x, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxyz(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.x, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxyw(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.x, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxzx(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.x, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxzy(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.x, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxzz(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.x, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxzw(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.x, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxwx(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.x, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxwy(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.x, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxwz(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.x, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxww(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.x, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyxx(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.y, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyxy(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.y, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyxz(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.y, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyxw(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.y, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyyx(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.y, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyyy(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.y, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyyz(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.y, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyyw(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.y, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyzx(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.y, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyzy(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.y, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyzz(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.y, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyzw(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.y, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xywx(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.y, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xywy(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.y, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xywz(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.y, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyww(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.y, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzxx(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.z, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzxy(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.z, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzxz(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.z, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzxw(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.z, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzyx(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.z, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzyy(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.z, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzyz(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.z, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzyw(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.z, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzzx(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.z, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzzy(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.z, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzzz(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.z, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzzw(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.z, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzwx(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.z, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzwy(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.z, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzwz(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.z, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzww(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.z, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwxx(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.w, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwxy(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.w, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwxz(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.w, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwxw(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.w, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwyx(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.w, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwyy(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.w, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwyz(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.w, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwyw(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.w, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwzx(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.w, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwzy(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.w, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwzz(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.w, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwzw(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.w, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwwx(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.w, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwwy(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.w, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwwz(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.w, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwww(self) -> U16Vec4 {
+        U16Vec4::new(self.x, self.w, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxxx(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.x, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxxy(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.x, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxxz(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.x, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxxw(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.x, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxyx(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.x, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxyy(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.x, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxyz(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.x, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxyw(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.x, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxzx(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.x, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxzy(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.x, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxzz(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.x, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxzw(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.x, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxwx(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.x, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxwy(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.x, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxwz(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.x, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxww(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.x, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyxx(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.y, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyxy(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.y, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyxz(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.y, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyxw(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.y, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyyx(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.y, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyyy(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.y, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyyz(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.y, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyyw(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.y, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyzx(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.y, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyzy(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.y, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyzz(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.y, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyzw(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.y, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yywx(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.y, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yywy(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.y, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yywz(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.y, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyww(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.y, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzxx(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.z, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzxy(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.z, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzxz(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.z, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzxw(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.z, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzyx(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.z, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzyy(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.z, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzyz(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.z, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzyw(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.z, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzzx(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.z, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzzy(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.z, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzzz(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.z, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzzw(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.z, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzwx(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.z, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzwy(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.z, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzwz(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.z, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzww(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.z, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywxx(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.w, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywxy(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.w, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywxz(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.w, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywxw(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.w, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywyx(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.w, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywyy(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.w, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywyz(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.w, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywyw(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.w, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywzx(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.w, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywzy(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.w, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywzz(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.w, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywzw(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.w, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywwx(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.w, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywwy(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.w, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywwz(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.w, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywww(self) -> U16Vec4 {
+        U16Vec4::new(self.y, self.w, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxxx(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.x, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxxy(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.x, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxxz(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.x, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxxw(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.x, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxyx(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.x, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxyy(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.x, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxyz(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.x, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxyw(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.x, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxzx(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.x, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxzy(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.x, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxzz(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.x, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxzw(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.x, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxwx(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.x, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxwy(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.x, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxwz(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.x, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxww(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.x, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyxx(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.y, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyxy(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.y, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyxz(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.y, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyxw(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.y, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyyx(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.y, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyyy(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.y, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyyz(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.y, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyyw(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.y, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyzx(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.y, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyzy(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.y, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyzz(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.y, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyzw(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.y, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zywx(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.y, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zywy(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.y, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zywz(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.y, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyww(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.y, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzxx(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.z, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzxy(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.z, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzxz(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.z, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzxw(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.z, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzyx(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.z, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzyy(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.z, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzyz(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.z, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzyw(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.z, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzzx(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.z, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzzy(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.z, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzzz(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.z, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzzw(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.z, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzwx(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.z, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzwy(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.z, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzwz(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.z, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzww(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.z, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwxx(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.w, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwxy(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.w, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwxz(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.w, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwxw(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.w, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwyx(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.w, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwyy(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.w, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwyz(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.w, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwyw(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.w, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwzx(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.w, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwzy(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.w, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwzz(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.w, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwzw(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.w, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwwx(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.w, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwwy(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.w, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwwz(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.w, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwww(self) -> U16Vec4 {
+        U16Vec4::new(self.z, self.w, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxxx(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.x, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxxy(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.x, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxxz(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.x, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxxw(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.x, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxyx(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.x, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxyy(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.x, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxyz(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.x, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxyw(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.x, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxzx(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.x, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxzy(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.x, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxzz(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.x, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxzw(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.x, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxwx(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.x, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxwy(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.x, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxwz(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.x, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxww(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.x, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyxx(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.y, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyxy(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.y, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyxz(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.y, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyxw(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.y, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyyx(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.y, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyyy(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.y, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyyz(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.y, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyyw(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.y, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyzx(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.y, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyzy(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.y, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyzz(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.y, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyzw(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.y, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wywx(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.y, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wywy(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.y, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wywz(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.y, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyww(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.y, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzxx(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.z, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzxy(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.z, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzxz(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.z, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzxw(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.z, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzyx(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.z, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzyy(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.z, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzyz(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.z, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzyw(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.z, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzzx(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.z, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzzy(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.z, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzzz(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.z, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzzw(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.z, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzwx(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.z, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzwy(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.z, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzwz(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.z, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzww(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.z, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwxx(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.w, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwxy(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.w, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwxz(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.w, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwxw(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.w, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwyx(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.w, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwyy(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.w, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwyz(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.w, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwyw(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.w, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwzx(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.w, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwzy(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.w, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwzz(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.w, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwzw(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.w, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwwx(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.w, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwwy(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.w, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwwz(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.w, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwww(self) -> U16Vec4 {
+        U16Vec4::new(self.w, self.w, self.w, self.w)
+    }
+}
diff --git a/src/swizzles/u64vec2_impl.rs b/src/swizzles/u64vec2_impl.rs
new file mode 100644
index 0000000..ee23afb
--- /dev/null
+++ b/src/swizzles/u64vec2_impl.rs
@@ -0,0 +1,221 @@
+// Generated from swizzle_impl.rs.tera template. Edit the template, not the generated file.
+
+use crate::{U64Vec2, U64Vec3, U64Vec4, Vec2Swizzles};
+
+impl Vec2Swizzles for U64Vec2 {
+    type Vec3 = U64Vec3;
+
+    type Vec4 = U64Vec4;
+
+    #[inline]
+    #[must_use]
+    fn xx(self) -> U64Vec2 {
+        U64Vec2 {
+            x: self.x,
+            y: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xy(self) -> U64Vec2 {
+        U64Vec2 {
+            x: self.x,
+            y: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yx(self) -> U64Vec2 {
+        U64Vec2 {
+            x: self.y,
+            y: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yy(self) -> U64Vec2 {
+        U64Vec2 {
+            x: self.y,
+            y: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxx(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.x,
+            y: self.x,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxy(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.x,
+            y: self.x,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyx(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.x,
+            y: self.y,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyy(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.x,
+            y: self.y,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxx(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.y,
+            y: self.x,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxy(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.y,
+            y: self.x,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyx(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.y,
+            y: self.y,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyy(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.y,
+            y: self.y,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxxx(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.x, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxxy(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.x, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxyx(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.x, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxyy(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.x, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyxx(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.y, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyxy(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.y, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyyx(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.y, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyyy(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.y, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxxx(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.x, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxxy(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.x, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxyx(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.x, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxyy(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.x, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyxx(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.y, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyxy(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.y, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyyx(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.y, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyyy(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.y, self.y, self.y)
+    }
+}
diff --git a/src/swizzles/u64vec3_impl.rs b/src/swizzles/u64vec3_impl.rs
new file mode 100644
index 0000000..5c0dcc6
--- /dev/null
+++ b/src/swizzles/u64vec3_impl.rs
@@ -0,0 +1,846 @@
+// Generated from swizzle_impl.rs.tera template. Edit the template, not the generated file.
+
+use crate::{U64Vec2, U64Vec3, U64Vec4, Vec3Swizzles};
+
+impl Vec3Swizzles for U64Vec3 {
+    type Vec2 = U64Vec2;
+
+    type Vec4 = U64Vec4;
+
+    #[inline]
+    #[must_use]
+    fn xx(self) -> U64Vec2 {
+        U64Vec2 {
+            x: self.x,
+            y: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xy(self) -> U64Vec2 {
+        U64Vec2 {
+            x: self.x,
+            y: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xz(self) -> U64Vec2 {
+        U64Vec2 {
+            x: self.x,
+            y: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yx(self) -> U64Vec2 {
+        U64Vec2 {
+            x: self.y,
+            y: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yy(self) -> U64Vec2 {
+        U64Vec2 {
+            x: self.y,
+            y: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yz(self) -> U64Vec2 {
+        U64Vec2 {
+            x: self.y,
+            y: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zx(self) -> U64Vec2 {
+        U64Vec2 {
+            x: self.z,
+            y: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zy(self) -> U64Vec2 {
+        U64Vec2 {
+            x: self.z,
+            y: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zz(self) -> U64Vec2 {
+        U64Vec2 {
+            x: self.z,
+            y: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxx(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.x,
+            y: self.x,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxy(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.x,
+            y: self.x,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxz(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.x,
+            y: self.x,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyx(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.x,
+            y: self.y,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyy(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.x,
+            y: self.y,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyz(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.x,
+            y: self.y,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzx(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.x,
+            y: self.z,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzy(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.x,
+            y: self.z,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzz(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.x,
+            y: self.z,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxx(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.y,
+            y: self.x,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxy(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.y,
+            y: self.x,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxz(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.y,
+            y: self.x,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyx(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.y,
+            y: self.y,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyy(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.y,
+            y: self.y,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyz(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.y,
+            y: self.y,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzx(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.y,
+            y: self.z,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzy(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.y,
+            y: self.z,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzz(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.y,
+            y: self.z,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxx(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.z,
+            y: self.x,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxy(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.z,
+            y: self.x,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxz(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.z,
+            y: self.x,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyx(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.z,
+            y: self.y,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyy(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.z,
+            y: self.y,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyz(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.z,
+            y: self.y,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzx(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.z,
+            y: self.z,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzy(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.z,
+            y: self.z,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzz(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.z,
+            y: self.z,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxxx(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.x, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxxy(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.x, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxxz(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.x, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxyx(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.x, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxyy(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.x, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxyz(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.x, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxzx(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.x, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxzy(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.x, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxzz(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.x, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyxx(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.y, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyxy(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.y, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyxz(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.y, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyyx(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.y, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyyy(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.y, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyyz(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.y, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyzx(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.y, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyzy(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.y, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyzz(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.y, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzxx(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.z, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzxy(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.z, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzxz(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.z, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzyx(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.z, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzyy(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.z, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzyz(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.z, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzzx(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.z, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzzy(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.z, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzzz(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.z, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxxx(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.x, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxxy(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.x, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxxz(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.x, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxyx(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.x, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxyy(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.x, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxyz(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.x, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxzx(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.x, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxzy(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.x, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxzz(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.x, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyxx(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.y, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyxy(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.y, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyxz(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.y, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyyx(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.y, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyyy(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.y, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyyz(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.y, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyzx(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.y, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyzy(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.y, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyzz(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.y, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzxx(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.z, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzxy(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.z, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzxz(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.z, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzyx(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.z, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzyy(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.z, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzyz(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.z, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzzx(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.z, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzzy(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.z, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzzz(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.z, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxxx(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.x, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxxy(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.x, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxxz(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.x, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxyx(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.x, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxyy(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.x, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxyz(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.x, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxzx(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.x, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxzy(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.x, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxzz(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.x, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyxx(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.y, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyxy(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.y, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyxz(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.y, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyyx(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.y, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyyy(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.y, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyyz(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.y, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyzx(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.y, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyzy(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.y, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyzz(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.y, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzxx(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.z, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzxy(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.z, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzxz(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.z, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzyx(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.z, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzyy(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.z, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzyz(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.z, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzzx(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.z, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzzy(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.z, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzzz(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.z, self.z, self.z)
+    }
+}
diff --git a/src/swizzles/u64vec4_impl.rs b/src/swizzles/u64vec4_impl.rs
new file mode 100644
index 0000000..111d70f
--- /dev/null
+++ b/src/swizzles/u64vec4_impl.rs
@@ -0,0 +1,2329 @@
+// Generated from swizzle_impl.rs.tera template. Edit the template, not the generated file.
+
+use crate::{U64Vec2, U64Vec3, U64Vec4, Vec4Swizzles};
+
+impl Vec4Swizzles for U64Vec4 {
+    type Vec2 = U64Vec2;
+
+    type Vec3 = U64Vec3;
+
+    #[inline]
+    #[must_use]
+    fn xx(self) -> U64Vec2 {
+        U64Vec2 {
+            x: self.x,
+            y: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xy(self) -> U64Vec2 {
+        U64Vec2 {
+            x: self.x,
+            y: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xz(self) -> U64Vec2 {
+        U64Vec2 {
+            x: self.x,
+            y: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xw(self) -> U64Vec2 {
+        U64Vec2 {
+            x: self.x,
+            y: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yx(self) -> U64Vec2 {
+        U64Vec2 {
+            x: self.y,
+            y: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yy(self) -> U64Vec2 {
+        U64Vec2 {
+            x: self.y,
+            y: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yz(self) -> U64Vec2 {
+        U64Vec2 {
+            x: self.y,
+            y: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yw(self) -> U64Vec2 {
+        U64Vec2 {
+            x: self.y,
+            y: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zx(self) -> U64Vec2 {
+        U64Vec2 {
+            x: self.z,
+            y: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zy(self) -> U64Vec2 {
+        U64Vec2 {
+            x: self.z,
+            y: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zz(self) -> U64Vec2 {
+        U64Vec2 {
+            x: self.z,
+            y: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zw(self) -> U64Vec2 {
+        U64Vec2 {
+            x: self.z,
+            y: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wx(self) -> U64Vec2 {
+        U64Vec2 {
+            x: self.w,
+            y: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wy(self) -> U64Vec2 {
+        U64Vec2 {
+            x: self.w,
+            y: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wz(self) -> U64Vec2 {
+        U64Vec2 {
+            x: self.w,
+            y: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn ww(self) -> U64Vec2 {
+        U64Vec2 {
+            x: self.w,
+            y: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxx(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.x,
+            y: self.x,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxy(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.x,
+            y: self.x,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxz(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.x,
+            y: self.x,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxw(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.x,
+            y: self.x,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyx(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.x,
+            y: self.y,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyy(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.x,
+            y: self.y,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyz(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.x,
+            y: self.y,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyw(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.x,
+            y: self.y,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzx(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.x,
+            y: self.z,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzy(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.x,
+            y: self.z,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzz(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.x,
+            y: self.z,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzw(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.x,
+            y: self.z,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwx(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.x,
+            y: self.w,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwy(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.x,
+            y: self.w,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwz(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.x,
+            y: self.w,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xww(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.x,
+            y: self.w,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxx(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.y,
+            y: self.x,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxy(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.y,
+            y: self.x,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxz(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.y,
+            y: self.x,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxw(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.y,
+            y: self.x,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyx(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.y,
+            y: self.y,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyy(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.y,
+            y: self.y,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyz(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.y,
+            y: self.y,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyw(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.y,
+            y: self.y,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzx(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.y,
+            y: self.z,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzy(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.y,
+            y: self.z,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzz(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.y,
+            y: self.z,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzw(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.y,
+            y: self.z,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywx(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.y,
+            y: self.w,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywy(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.y,
+            y: self.w,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywz(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.y,
+            y: self.w,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn yww(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.y,
+            y: self.w,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxx(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.z,
+            y: self.x,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxy(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.z,
+            y: self.x,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxz(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.z,
+            y: self.x,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxw(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.z,
+            y: self.x,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyx(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.z,
+            y: self.y,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyy(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.z,
+            y: self.y,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyz(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.z,
+            y: self.y,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyw(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.z,
+            y: self.y,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzx(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.z,
+            y: self.z,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzy(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.z,
+            y: self.z,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzz(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.z,
+            y: self.z,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzw(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.z,
+            y: self.z,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwx(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.z,
+            y: self.w,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwy(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.z,
+            y: self.w,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwz(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.z,
+            y: self.w,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn zww(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.z,
+            y: self.w,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxx(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.w,
+            y: self.x,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxy(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.w,
+            y: self.x,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxz(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.w,
+            y: self.x,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxw(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.w,
+            y: self.x,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyx(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.w,
+            y: self.y,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyy(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.w,
+            y: self.y,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyz(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.w,
+            y: self.y,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyw(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.w,
+            y: self.y,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzx(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.w,
+            y: self.z,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzy(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.w,
+            y: self.z,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzz(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.w,
+            y: self.z,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzw(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.w,
+            y: self.z,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwx(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.w,
+            y: self.w,
+            z: self.x,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwy(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.w,
+            y: self.w,
+            z: self.y,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwz(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.w,
+            y: self.w,
+            z: self.z,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn www(self) -> U64Vec3 {
+        U64Vec3 {
+            x: self.w,
+            y: self.w,
+            z: self.w,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxxx(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.x, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxxy(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.x, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxxz(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.x, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxxw(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.x, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxyx(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.x, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxyy(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.x, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxyz(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.x, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxyw(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.x, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxzx(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.x, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxzy(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.x, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxzz(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.x, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxzw(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.x, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxwx(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.x, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxwy(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.x, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxwz(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.x, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xxww(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.x, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyxx(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.y, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyxy(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.y, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyxz(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.y, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyxw(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.y, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyyx(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.y, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyyy(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.y, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyyz(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.y, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyyw(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.y, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyzx(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.y, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyzy(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.y, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyzz(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.y, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyzw(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.y, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xywx(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.y, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xywy(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.y, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xywz(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.y, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xyww(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.y, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzxx(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.z, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzxy(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.z, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzxz(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.z, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzxw(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.z, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzyx(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.z, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzyy(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.z, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzyz(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.z, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzyw(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.z, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzzx(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.z, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzzy(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.z, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzzz(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.z, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzzw(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.z, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzwx(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.z, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzwy(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.z, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzwz(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.z, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xzww(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.z, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwxx(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.w, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwxy(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.w, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwxz(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.w, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwxw(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.w, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwyx(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.w, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwyy(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.w, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwyz(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.w, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwyw(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.w, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwzx(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.w, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwzy(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.w, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwzz(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.w, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwzw(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.w, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwwx(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.w, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwwy(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.w, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwwz(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.w, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn xwww(self) -> U64Vec4 {
+        U64Vec4::new(self.x, self.w, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxxx(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.x, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxxy(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.x, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxxz(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.x, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxxw(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.x, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxyx(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.x, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxyy(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.x, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxyz(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.x, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxyw(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.x, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxzx(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.x, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxzy(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.x, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxzz(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.x, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxzw(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.x, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxwx(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.x, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxwy(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.x, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxwz(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.x, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yxww(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.x, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyxx(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.y, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyxy(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.y, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyxz(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.y, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyxw(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.y, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyyx(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.y, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyyy(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.y, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyyz(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.y, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyyw(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.y, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyzx(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.y, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyzy(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.y, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyzz(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.y, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyzw(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.y, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yywx(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.y, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yywy(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.y, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yywz(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.y, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yyww(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.y, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzxx(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.z, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzxy(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.z, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzxz(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.z, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzxw(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.z, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzyx(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.z, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzyy(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.z, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzyz(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.z, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzyw(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.z, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzzx(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.z, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzzy(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.z, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzzz(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.z, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzzw(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.z, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzwx(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.z, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzwy(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.z, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzwz(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.z, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn yzww(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.z, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywxx(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.w, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywxy(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.w, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywxz(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.w, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywxw(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.w, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywyx(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.w, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywyy(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.w, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywyz(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.w, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywyw(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.w, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywzx(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.w, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywzy(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.w, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywzz(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.w, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywzw(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.w, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywwx(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.w, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywwy(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.w, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywwz(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.w, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn ywww(self) -> U64Vec4 {
+        U64Vec4::new(self.y, self.w, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxxx(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.x, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxxy(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.x, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxxz(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.x, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxxw(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.x, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxyx(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.x, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxyy(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.x, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxyz(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.x, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxyw(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.x, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxzx(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.x, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxzy(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.x, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxzz(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.x, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxzw(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.x, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxwx(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.x, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxwy(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.x, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxwz(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.x, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zxww(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.x, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyxx(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.y, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyxy(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.y, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyxz(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.y, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyxw(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.y, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyyx(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.y, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyyy(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.y, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyyz(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.y, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyyw(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.y, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyzx(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.y, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyzy(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.y, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyzz(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.y, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyzw(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.y, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zywx(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.y, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zywy(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.y, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zywz(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.y, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zyww(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.y, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzxx(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.z, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzxy(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.z, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzxz(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.z, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzxw(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.z, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzyx(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.z, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzyy(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.z, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzyz(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.z, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzyw(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.z, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzzx(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.z, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzzy(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.z, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzzz(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.z, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzzw(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.z, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzwx(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.z, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzwy(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.z, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzwz(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.z, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zzww(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.z, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwxx(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.w, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwxy(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.w, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwxz(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.w, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwxw(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.w, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwyx(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.w, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwyy(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.w, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwyz(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.w, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwyw(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.w, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwzx(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.w, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwzy(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.w, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwzz(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.w, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwzw(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.w, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwwx(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.w, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwwy(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.w, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwwz(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.w, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn zwww(self) -> U64Vec4 {
+        U64Vec4::new(self.z, self.w, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxxx(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.x, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxxy(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.x, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxxz(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.x, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxxw(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.x, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxyx(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.x, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxyy(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.x, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxyz(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.x, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxyw(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.x, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxzx(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.x, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxzy(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.x, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxzz(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.x, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxzw(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.x, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxwx(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.x, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxwy(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.x, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxwz(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.x, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wxww(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.x, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyxx(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.y, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyxy(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.y, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyxz(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.y, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyxw(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.y, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyyx(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.y, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyyy(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.y, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyyz(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.y, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyyw(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.y, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyzx(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.y, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyzy(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.y, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyzz(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.y, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyzw(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.y, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wywx(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.y, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wywy(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.y, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wywz(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.y, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wyww(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.y, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzxx(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.z, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzxy(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.z, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzxz(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.z, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzxw(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.z, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzyx(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.z, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzyy(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.z, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzyz(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.z, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzyw(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.z, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzzx(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.z, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzzy(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.z, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzzz(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.z, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzzw(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.z, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzwx(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.z, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzwy(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.z, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzwz(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.z, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wzww(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.z, self.w, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwxx(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.w, self.x, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwxy(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.w, self.x, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwxz(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.w, self.x, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwxw(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.w, self.x, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwyx(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.w, self.y, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwyy(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.w, self.y, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwyz(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.w, self.y, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwyw(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.w, self.y, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwzx(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.w, self.z, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwzy(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.w, self.z, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwzz(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.w, self.z, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwzw(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.w, self.z, self.w)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwwx(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.w, self.w, self.x)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwwy(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.w, self.w, self.y)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwwz(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.w, self.w, self.z)
+    }
+
+    #[inline]
+    #[must_use]
+    fn wwww(self) -> U64Vec4 {
+        U64Vec4::new(self.w, self.w, self.w, self.w)
+    }
+}
diff --git a/src/swizzles/uvec2_impl.rs b/src/swizzles/uvec2_impl.rs
index 16ddf21..78bb40c 100644
--- a/src/swizzles/uvec2_impl.rs
+++ b/src/swizzles/uvec2_impl.rs
@@ -8,6 +8,7 @@
     type Vec4 = UVec4;
 
     #[inline]
+    #[must_use]
     fn xx(self) -> UVec2 {
         UVec2 {
             x: self.x,
@@ -16,6 +17,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xy(self) -> UVec2 {
         UVec2 {
             x: self.x,
@@ -24,6 +26,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yx(self) -> UVec2 {
         UVec2 {
             x: self.y,
@@ -32,6 +35,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yy(self) -> UVec2 {
         UVec2 {
             x: self.y,
@@ -40,6 +44,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxx(self) -> UVec3 {
         UVec3 {
             x: self.x,
@@ -49,6 +54,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxy(self) -> UVec3 {
         UVec3 {
             x: self.x,
@@ -58,6 +64,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyx(self) -> UVec3 {
         UVec3 {
             x: self.x,
@@ -67,6 +74,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyy(self) -> UVec3 {
         UVec3 {
             x: self.x,
@@ -76,6 +84,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxx(self) -> UVec3 {
         UVec3 {
             x: self.y,
@@ -85,6 +94,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxy(self) -> UVec3 {
         UVec3 {
             x: self.y,
@@ -94,6 +104,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyx(self) -> UVec3 {
         UVec3 {
             x: self.y,
@@ -103,6 +114,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyy(self) -> UVec3 {
         UVec3 {
             x: self.y,
@@ -112,81 +124,97 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxxx(self) -> UVec4 {
         UVec4::new(self.x, self.x, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xxxy(self) -> UVec4 {
         UVec4::new(self.x, self.x, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xxyx(self) -> UVec4 {
         UVec4::new(self.x, self.x, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xxyy(self) -> UVec4 {
         UVec4::new(self.x, self.x, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xyxx(self) -> UVec4 {
         UVec4::new(self.x, self.y, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xyxy(self) -> UVec4 {
         UVec4::new(self.x, self.y, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xyyx(self) -> UVec4 {
         UVec4::new(self.x, self.y, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xyyy(self) -> UVec4 {
         UVec4::new(self.x, self.y, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yxxx(self) -> UVec4 {
         UVec4::new(self.y, self.x, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yxxy(self) -> UVec4 {
         UVec4::new(self.y, self.x, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yxyx(self) -> UVec4 {
         UVec4::new(self.y, self.x, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yxyy(self) -> UVec4 {
         UVec4::new(self.y, self.x, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yyxx(self) -> UVec4 {
         UVec4::new(self.y, self.y, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yyxy(self) -> UVec4 {
         UVec4::new(self.y, self.y, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yyyx(self) -> UVec4 {
         UVec4::new(self.y, self.y, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yyyy(self) -> UVec4 {
         UVec4::new(self.y, self.y, self.y, self.y)
     }
diff --git a/src/swizzles/uvec3_impl.rs b/src/swizzles/uvec3_impl.rs
index 75afb5c..9a91b7c 100644
--- a/src/swizzles/uvec3_impl.rs
+++ b/src/swizzles/uvec3_impl.rs
@@ -8,6 +8,7 @@
     type Vec4 = UVec4;
 
     #[inline]
+    #[must_use]
     fn xx(self) -> UVec2 {
         UVec2 {
             x: self.x,
@@ -16,6 +17,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xy(self) -> UVec2 {
         UVec2 {
             x: self.x,
@@ -24,6 +26,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xz(self) -> UVec2 {
         UVec2 {
             x: self.x,
@@ -32,6 +35,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yx(self) -> UVec2 {
         UVec2 {
             x: self.y,
@@ -40,6 +44,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yy(self) -> UVec2 {
         UVec2 {
             x: self.y,
@@ -48,6 +53,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yz(self) -> UVec2 {
         UVec2 {
             x: self.y,
@@ -56,6 +62,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zx(self) -> UVec2 {
         UVec2 {
             x: self.z,
@@ -64,6 +71,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zy(self) -> UVec2 {
         UVec2 {
             x: self.z,
@@ -72,6 +80,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zz(self) -> UVec2 {
         UVec2 {
             x: self.z,
@@ -80,6 +89,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxx(self) -> UVec3 {
         UVec3 {
             x: self.x,
@@ -89,6 +99,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxy(self) -> UVec3 {
         UVec3 {
             x: self.x,
@@ -98,6 +109,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxz(self) -> UVec3 {
         UVec3 {
             x: self.x,
@@ -107,6 +119,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyx(self) -> UVec3 {
         UVec3 {
             x: self.x,
@@ -116,6 +129,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyy(self) -> UVec3 {
         UVec3 {
             x: self.x,
@@ -125,6 +139,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyz(self) -> UVec3 {
         UVec3 {
             x: self.x,
@@ -134,6 +149,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzx(self) -> UVec3 {
         UVec3 {
             x: self.x,
@@ -143,6 +159,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzy(self) -> UVec3 {
         UVec3 {
             x: self.x,
@@ -152,6 +169,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzz(self) -> UVec3 {
         UVec3 {
             x: self.x,
@@ -161,6 +179,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxx(self) -> UVec3 {
         UVec3 {
             x: self.y,
@@ -170,6 +189,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxy(self) -> UVec3 {
         UVec3 {
             x: self.y,
@@ -179,6 +199,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxz(self) -> UVec3 {
         UVec3 {
             x: self.y,
@@ -188,6 +209,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyx(self) -> UVec3 {
         UVec3 {
             x: self.y,
@@ -197,6 +219,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyy(self) -> UVec3 {
         UVec3 {
             x: self.y,
@@ -206,6 +229,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyz(self) -> UVec3 {
         UVec3 {
             x: self.y,
@@ -215,6 +239,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzx(self) -> UVec3 {
         UVec3 {
             x: self.y,
@@ -224,6 +249,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzy(self) -> UVec3 {
         UVec3 {
             x: self.y,
@@ -233,6 +259,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzz(self) -> UVec3 {
         UVec3 {
             x: self.y,
@@ -242,6 +269,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxx(self) -> UVec3 {
         UVec3 {
             x: self.z,
@@ -251,6 +279,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxy(self) -> UVec3 {
         UVec3 {
             x: self.z,
@@ -260,6 +289,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxz(self) -> UVec3 {
         UVec3 {
             x: self.z,
@@ -269,6 +299,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyx(self) -> UVec3 {
         UVec3 {
             x: self.z,
@@ -278,6 +309,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyy(self) -> UVec3 {
         UVec3 {
             x: self.z,
@@ -287,6 +319,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyz(self) -> UVec3 {
         UVec3 {
             x: self.z,
@@ -296,6 +329,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzx(self) -> UVec3 {
         UVec3 {
             x: self.z,
@@ -305,6 +339,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzy(self) -> UVec3 {
         UVec3 {
             x: self.z,
@@ -314,6 +349,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzz(self) -> UVec3 {
         UVec3 {
             x: self.z,
@@ -323,406 +359,487 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxxx(self) -> UVec4 {
         UVec4::new(self.x, self.x, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xxxy(self) -> UVec4 {
         UVec4::new(self.x, self.x, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xxxz(self) -> UVec4 {
         UVec4::new(self.x, self.x, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xxyx(self) -> UVec4 {
         UVec4::new(self.x, self.x, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xxyy(self) -> UVec4 {
         UVec4::new(self.x, self.x, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xxyz(self) -> UVec4 {
         UVec4::new(self.x, self.x, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xxzx(self) -> UVec4 {
         UVec4::new(self.x, self.x, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xxzy(self) -> UVec4 {
         UVec4::new(self.x, self.x, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xxzz(self) -> UVec4 {
         UVec4::new(self.x, self.x, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xyxx(self) -> UVec4 {
         UVec4::new(self.x, self.y, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xyxy(self) -> UVec4 {
         UVec4::new(self.x, self.y, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xyxz(self) -> UVec4 {
         UVec4::new(self.x, self.y, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xyyx(self) -> UVec4 {
         UVec4::new(self.x, self.y, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xyyy(self) -> UVec4 {
         UVec4::new(self.x, self.y, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xyyz(self) -> UVec4 {
         UVec4::new(self.x, self.y, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xyzx(self) -> UVec4 {
         UVec4::new(self.x, self.y, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xyzy(self) -> UVec4 {
         UVec4::new(self.x, self.y, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xyzz(self) -> UVec4 {
         UVec4::new(self.x, self.y, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xzxx(self) -> UVec4 {
         UVec4::new(self.x, self.z, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xzxy(self) -> UVec4 {
         UVec4::new(self.x, self.z, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xzxz(self) -> UVec4 {
         UVec4::new(self.x, self.z, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xzyx(self) -> UVec4 {
         UVec4::new(self.x, self.z, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xzyy(self) -> UVec4 {
         UVec4::new(self.x, self.z, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xzyz(self) -> UVec4 {
         UVec4::new(self.x, self.z, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xzzx(self) -> UVec4 {
         UVec4::new(self.x, self.z, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xzzy(self) -> UVec4 {
         UVec4::new(self.x, self.z, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xzzz(self) -> UVec4 {
         UVec4::new(self.x, self.z, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yxxx(self) -> UVec4 {
         UVec4::new(self.y, self.x, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yxxy(self) -> UVec4 {
         UVec4::new(self.y, self.x, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yxxz(self) -> UVec4 {
         UVec4::new(self.y, self.x, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yxyx(self) -> UVec4 {
         UVec4::new(self.y, self.x, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yxyy(self) -> UVec4 {
         UVec4::new(self.y, self.x, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yxyz(self) -> UVec4 {
         UVec4::new(self.y, self.x, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yxzx(self) -> UVec4 {
         UVec4::new(self.y, self.x, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yxzy(self) -> UVec4 {
         UVec4::new(self.y, self.x, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yxzz(self) -> UVec4 {
         UVec4::new(self.y, self.x, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yyxx(self) -> UVec4 {
         UVec4::new(self.y, self.y, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yyxy(self) -> UVec4 {
         UVec4::new(self.y, self.y, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yyxz(self) -> UVec4 {
         UVec4::new(self.y, self.y, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yyyx(self) -> UVec4 {
         UVec4::new(self.y, self.y, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yyyy(self) -> UVec4 {
         UVec4::new(self.y, self.y, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yyyz(self) -> UVec4 {
         UVec4::new(self.y, self.y, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yyzx(self) -> UVec4 {
         UVec4::new(self.y, self.y, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yyzy(self) -> UVec4 {
         UVec4::new(self.y, self.y, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yyzz(self) -> UVec4 {
         UVec4::new(self.y, self.y, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yzxx(self) -> UVec4 {
         UVec4::new(self.y, self.z, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yzxy(self) -> UVec4 {
         UVec4::new(self.y, self.z, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yzxz(self) -> UVec4 {
         UVec4::new(self.y, self.z, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yzyx(self) -> UVec4 {
         UVec4::new(self.y, self.z, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yzyy(self) -> UVec4 {
         UVec4::new(self.y, self.z, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yzyz(self) -> UVec4 {
         UVec4::new(self.y, self.z, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yzzx(self) -> UVec4 {
         UVec4::new(self.y, self.z, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yzzy(self) -> UVec4 {
         UVec4::new(self.y, self.z, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yzzz(self) -> UVec4 {
         UVec4::new(self.y, self.z, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zxxx(self) -> UVec4 {
         UVec4::new(self.z, self.x, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zxxy(self) -> UVec4 {
         UVec4::new(self.z, self.x, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zxxz(self) -> UVec4 {
         UVec4::new(self.z, self.x, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zxyx(self) -> UVec4 {
         UVec4::new(self.z, self.x, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zxyy(self) -> UVec4 {
         UVec4::new(self.z, self.x, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zxyz(self) -> UVec4 {
         UVec4::new(self.z, self.x, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zxzx(self) -> UVec4 {
         UVec4::new(self.z, self.x, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zxzy(self) -> UVec4 {
         UVec4::new(self.z, self.x, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zxzz(self) -> UVec4 {
         UVec4::new(self.z, self.x, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zyxx(self) -> UVec4 {
         UVec4::new(self.z, self.y, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zyxy(self) -> UVec4 {
         UVec4::new(self.z, self.y, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zyxz(self) -> UVec4 {
         UVec4::new(self.z, self.y, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zyyx(self) -> UVec4 {
         UVec4::new(self.z, self.y, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zyyy(self) -> UVec4 {
         UVec4::new(self.z, self.y, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zyyz(self) -> UVec4 {
         UVec4::new(self.z, self.y, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zyzx(self) -> UVec4 {
         UVec4::new(self.z, self.y, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zyzy(self) -> UVec4 {
         UVec4::new(self.z, self.y, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zyzz(self) -> UVec4 {
         UVec4::new(self.z, self.y, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zzxx(self) -> UVec4 {
         UVec4::new(self.z, self.z, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zzxy(self) -> UVec4 {
         UVec4::new(self.z, self.z, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zzxz(self) -> UVec4 {
         UVec4::new(self.z, self.z, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zzyx(self) -> UVec4 {
         UVec4::new(self.z, self.z, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zzyy(self) -> UVec4 {
         UVec4::new(self.z, self.z, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zzyz(self) -> UVec4 {
         UVec4::new(self.z, self.z, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zzzx(self) -> UVec4 {
         UVec4::new(self.z, self.z, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zzzy(self) -> UVec4 {
         UVec4::new(self.z, self.z, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zzzz(self) -> UVec4 {
         UVec4::new(self.z, self.z, self.z, self.z)
     }
diff --git a/src/swizzles/uvec4_impl.rs b/src/swizzles/uvec4_impl.rs
index 6d43573..afd3d32 100644
--- a/src/swizzles/uvec4_impl.rs
+++ b/src/swizzles/uvec4_impl.rs
@@ -8,6 +8,7 @@
     type Vec3 = UVec3;
 
     #[inline]
+    #[must_use]
     fn xx(self) -> UVec2 {
         UVec2 {
             x: self.x,
@@ -16,6 +17,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xy(self) -> UVec2 {
         UVec2 {
             x: self.x,
@@ -24,6 +26,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xz(self) -> UVec2 {
         UVec2 {
             x: self.x,
@@ -32,6 +35,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xw(self) -> UVec2 {
         UVec2 {
             x: self.x,
@@ -40,6 +44,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yx(self) -> UVec2 {
         UVec2 {
             x: self.y,
@@ -48,6 +53,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yy(self) -> UVec2 {
         UVec2 {
             x: self.y,
@@ -56,6 +62,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yz(self) -> UVec2 {
         UVec2 {
             x: self.y,
@@ -64,6 +71,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yw(self) -> UVec2 {
         UVec2 {
             x: self.y,
@@ -72,6 +80,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zx(self) -> UVec2 {
         UVec2 {
             x: self.z,
@@ -80,6 +89,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zy(self) -> UVec2 {
         UVec2 {
             x: self.z,
@@ -88,6 +98,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zz(self) -> UVec2 {
         UVec2 {
             x: self.z,
@@ -96,6 +107,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zw(self) -> UVec2 {
         UVec2 {
             x: self.z,
@@ -104,6 +116,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wx(self) -> UVec2 {
         UVec2 {
             x: self.w,
@@ -112,6 +125,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wy(self) -> UVec2 {
         UVec2 {
             x: self.w,
@@ -120,6 +134,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wz(self) -> UVec2 {
         UVec2 {
             x: self.w,
@@ -128,6 +143,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn ww(self) -> UVec2 {
         UVec2 {
             x: self.w,
@@ -136,6 +152,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxx(self) -> UVec3 {
         UVec3 {
             x: self.x,
@@ -145,6 +162,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxy(self) -> UVec3 {
         UVec3 {
             x: self.x,
@@ -154,6 +172,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxz(self) -> UVec3 {
         UVec3 {
             x: self.x,
@@ -163,6 +182,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxw(self) -> UVec3 {
         UVec3 {
             x: self.x,
@@ -172,6 +192,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyx(self) -> UVec3 {
         UVec3 {
             x: self.x,
@@ -181,6 +202,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyy(self) -> UVec3 {
         UVec3 {
             x: self.x,
@@ -190,6 +212,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyz(self) -> UVec3 {
         UVec3 {
             x: self.x,
@@ -199,6 +222,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyw(self) -> UVec3 {
         UVec3 {
             x: self.x,
@@ -208,6 +232,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzx(self) -> UVec3 {
         UVec3 {
             x: self.x,
@@ -217,6 +242,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzy(self) -> UVec3 {
         UVec3 {
             x: self.x,
@@ -226,6 +252,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzz(self) -> UVec3 {
         UVec3 {
             x: self.x,
@@ -235,6 +262,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzw(self) -> UVec3 {
         UVec3 {
             x: self.x,
@@ -244,6 +272,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xwx(self) -> UVec3 {
         UVec3 {
             x: self.x,
@@ -253,6 +282,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xwy(self) -> UVec3 {
         UVec3 {
             x: self.x,
@@ -262,6 +292,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xwz(self) -> UVec3 {
         UVec3 {
             x: self.x,
@@ -271,6 +302,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xww(self) -> UVec3 {
         UVec3 {
             x: self.x,
@@ -280,6 +312,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxx(self) -> UVec3 {
         UVec3 {
             x: self.y,
@@ -289,6 +322,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxy(self) -> UVec3 {
         UVec3 {
             x: self.y,
@@ -298,6 +332,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxz(self) -> UVec3 {
         UVec3 {
             x: self.y,
@@ -307,6 +342,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxw(self) -> UVec3 {
         UVec3 {
             x: self.y,
@@ -316,6 +352,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyx(self) -> UVec3 {
         UVec3 {
             x: self.y,
@@ -325,6 +362,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyy(self) -> UVec3 {
         UVec3 {
             x: self.y,
@@ -334,6 +372,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyz(self) -> UVec3 {
         UVec3 {
             x: self.y,
@@ -343,6 +382,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyw(self) -> UVec3 {
         UVec3 {
             x: self.y,
@@ -352,6 +392,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzx(self) -> UVec3 {
         UVec3 {
             x: self.y,
@@ -361,6 +402,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzy(self) -> UVec3 {
         UVec3 {
             x: self.y,
@@ -370,6 +412,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzz(self) -> UVec3 {
         UVec3 {
             x: self.y,
@@ -379,6 +422,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzw(self) -> UVec3 {
         UVec3 {
             x: self.y,
@@ -388,6 +432,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn ywx(self) -> UVec3 {
         UVec3 {
             x: self.y,
@@ -397,6 +442,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn ywy(self) -> UVec3 {
         UVec3 {
             x: self.y,
@@ -406,6 +452,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn ywz(self) -> UVec3 {
         UVec3 {
             x: self.y,
@@ -415,6 +462,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yww(self) -> UVec3 {
         UVec3 {
             x: self.y,
@@ -424,6 +472,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxx(self) -> UVec3 {
         UVec3 {
             x: self.z,
@@ -433,6 +482,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxy(self) -> UVec3 {
         UVec3 {
             x: self.z,
@@ -442,6 +492,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxz(self) -> UVec3 {
         UVec3 {
             x: self.z,
@@ -451,6 +502,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxw(self) -> UVec3 {
         UVec3 {
             x: self.z,
@@ -460,6 +512,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyx(self) -> UVec3 {
         UVec3 {
             x: self.z,
@@ -469,6 +522,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyy(self) -> UVec3 {
         UVec3 {
             x: self.z,
@@ -478,6 +532,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyz(self) -> UVec3 {
         UVec3 {
             x: self.z,
@@ -487,6 +542,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyw(self) -> UVec3 {
         UVec3 {
             x: self.z,
@@ -496,6 +552,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzx(self) -> UVec3 {
         UVec3 {
             x: self.z,
@@ -505,6 +562,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzy(self) -> UVec3 {
         UVec3 {
             x: self.z,
@@ -514,6 +572,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzz(self) -> UVec3 {
         UVec3 {
             x: self.z,
@@ -523,6 +582,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzw(self) -> UVec3 {
         UVec3 {
             x: self.z,
@@ -532,6 +592,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zwx(self) -> UVec3 {
         UVec3 {
             x: self.z,
@@ -541,6 +602,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zwy(self) -> UVec3 {
         UVec3 {
             x: self.z,
@@ -550,6 +612,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zwz(self) -> UVec3 {
         UVec3 {
             x: self.z,
@@ -559,6 +622,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zww(self) -> UVec3 {
         UVec3 {
             x: self.z,
@@ -568,6 +632,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wxx(self) -> UVec3 {
         UVec3 {
             x: self.w,
@@ -577,6 +642,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wxy(self) -> UVec3 {
         UVec3 {
             x: self.w,
@@ -586,6 +652,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wxz(self) -> UVec3 {
         UVec3 {
             x: self.w,
@@ -595,6 +662,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wxw(self) -> UVec3 {
         UVec3 {
             x: self.w,
@@ -604,6 +672,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wyx(self) -> UVec3 {
         UVec3 {
             x: self.w,
@@ -613,6 +682,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wyy(self) -> UVec3 {
         UVec3 {
             x: self.w,
@@ -622,6 +692,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wyz(self) -> UVec3 {
         UVec3 {
             x: self.w,
@@ -631,6 +702,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wyw(self) -> UVec3 {
         UVec3 {
             x: self.w,
@@ -640,6 +712,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wzx(self) -> UVec3 {
         UVec3 {
             x: self.w,
@@ -649,6 +722,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wzy(self) -> UVec3 {
         UVec3 {
             x: self.w,
@@ -658,6 +732,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wzz(self) -> UVec3 {
         UVec3 {
             x: self.w,
@@ -667,6 +742,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wzw(self) -> UVec3 {
         UVec3 {
             x: self.w,
@@ -676,6 +752,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wwx(self) -> UVec3 {
         UVec3 {
             x: self.w,
@@ -685,6 +762,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wwy(self) -> UVec3 {
         UVec3 {
             x: self.w,
@@ -694,6 +772,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wwz(self) -> UVec3 {
         UVec3 {
             x: self.w,
@@ -703,6 +782,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn www(self) -> UVec3 {
         UVec3 {
             x: self.w,
@@ -712,1281 +792,1537 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxxx(self) -> UVec4 {
         UVec4::new(self.x, self.x, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xxxy(self) -> UVec4 {
         UVec4::new(self.x, self.x, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xxxz(self) -> UVec4 {
         UVec4::new(self.x, self.x, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xxxw(self) -> UVec4 {
         UVec4::new(self.x, self.x, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xxyx(self) -> UVec4 {
         UVec4::new(self.x, self.x, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xxyy(self) -> UVec4 {
         UVec4::new(self.x, self.x, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xxyz(self) -> UVec4 {
         UVec4::new(self.x, self.x, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xxyw(self) -> UVec4 {
         UVec4::new(self.x, self.x, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xxzx(self) -> UVec4 {
         UVec4::new(self.x, self.x, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xxzy(self) -> UVec4 {
         UVec4::new(self.x, self.x, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xxzz(self) -> UVec4 {
         UVec4::new(self.x, self.x, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xxzw(self) -> UVec4 {
         UVec4::new(self.x, self.x, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xxwx(self) -> UVec4 {
         UVec4::new(self.x, self.x, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xxwy(self) -> UVec4 {
         UVec4::new(self.x, self.x, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xxwz(self) -> UVec4 {
         UVec4::new(self.x, self.x, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xxww(self) -> UVec4 {
         UVec4::new(self.x, self.x, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xyxx(self) -> UVec4 {
         UVec4::new(self.x, self.y, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xyxy(self) -> UVec4 {
         UVec4::new(self.x, self.y, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xyxz(self) -> UVec4 {
         UVec4::new(self.x, self.y, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xyxw(self) -> UVec4 {
         UVec4::new(self.x, self.y, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xyyx(self) -> UVec4 {
         UVec4::new(self.x, self.y, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xyyy(self) -> UVec4 {
         UVec4::new(self.x, self.y, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xyyz(self) -> UVec4 {
         UVec4::new(self.x, self.y, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xyyw(self) -> UVec4 {
         UVec4::new(self.x, self.y, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xyzx(self) -> UVec4 {
         UVec4::new(self.x, self.y, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xyzy(self) -> UVec4 {
         UVec4::new(self.x, self.y, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xyzz(self) -> UVec4 {
         UVec4::new(self.x, self.y, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xyzw(self) -> UVec4 {
         UVec4::new(self.x, self.y, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xywx(self) -> UVec4 {
         UVec4::new(self.x, self.y, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xywy(self) -> UVec4 {
         UVec4::new(self.x, self.y, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xywz(self) -> UVec4 {
         UVec4::new(self.x, self.y, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xyww(self) -> UVec4 {
         UVec4::new(self.x, self.y, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xzxx(self) -> UVec4 {
         UVec4::new(self.x, self.z, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xzxy(self) -> UVec4 {
         UVec4::new(self.x, self.z, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xzxz(self) -> UVec4 {
         UVec4::new(self.x, self.z, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xzxw(self) -> UVec4 {
         UVec4::new(self.x, self.z, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xzyx(self) -> UVec4 {
         UVec4::new(self.x, self.z, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xzyy(self) -> UVec4 {
         UVec4::new(self.x, self.z, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xzyz(self) -> UVec4 {
         UVec4::new(self.x, self.z, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xzyw(self) -> UVec4 {
         UVec4::new(self.x, self.z, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xzzx(self) -> UVec4 {
         UVec4::new(self.x, self.z, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xzzy(self) -> UVec4 {
         UVec4::new(self.x, self.z, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xzzz(self) -> UVec4 {
         UVec4::new(self.x, self.z, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xzzw(self) -> UVec4 {
         UVec4::new(self.x, self.z, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xzwx(self) -> UVec4 {
         UVec4::new(self.x, self.z, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xzwy(self) -> UVec4 {
         UVec4::new(self.x, self.z, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xzwz(self) -> UVec4 {
         UVec4::new(self.x, self.z, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xzww(self) -> UVec4 {
         UVec4::new(self.x, self.z, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xwxx(self) -> UVec4 {
         UVec4::new(self.x, self.w, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xwxy(self) -> UVec4 {
         UVec4::new(self.x, self.w, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xwxz(self) -> UVec4 {
         UVec4::new(self.x, self.w, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xwxw(self) -> UVec4 {
         UVec4::new(self.x, self.w, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xwyx(self) -> UVec4 {
         UVec4::new(self.x, self.w, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xwyy(self) -> UVec4 {
         UVec4::new(self.x, self.w, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xwyz(self) -> UVec4 {
         UVec4::new(self.x, self.w, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xwyw(self) -> UVec4 {
         UVec4::new(self.x, self.w, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xwzx(self) -> UVec4 {
         UVec4::new(self.x, self.w, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xwzy(self) -> UVec4 {
         UVec4::new(self.x, self.w, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xwzz(self) -> UVec4 {
         UVec4::new(self.x, self.w, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xwzw(self) -> UVec4 {
         UVec4::new(self.x, self.w, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn xwwx(self) -> UVec4 {
         UVec4::new(self.x, self.w, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xwwy(self) -> UVec4 {
         UVec4::new(self.x, self.w, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xwwz(self) -> UVec4 {
         UVec4::new(self.x, self.w, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xwww(self) -> UVec4 {
         UVec4::new(self.x, self.w, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yxxx(self) -> UVec4 {
         UVec4::new(self.y, self.x, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yxxy(self) -> UVec4 {
         UVec4::new(self.y, self.x, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yxxz(self) -> UVec4 {
         UVec4::new(self.y, self.x, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yxxw(self) -> UVec4 {
         UVec4::new(self.y, self.x, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yxyx(self) -> UVec4 {
         UVec4::new(self.y, self.x, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yxyy(self) -> UVec4 {
         UVec4::new(self.y, self.x, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yxyz(self) -> UVec4 {
         UVec4::new(self.y, self.x, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yxyw(self) -> UVec4 {
         UVec4::new(self.y, self.x, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yxzx(self) -> UVec4 {
         UVec4::new(self.y, self.x, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yxzy(self) -> UVec4 {
         UVec4::new(self.y, self.x, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yxzz(self) -> UVec4 {
         UVec4::new(self.y, self.x, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yxzw(self) -> UVec4 {
         UVec4::new(self.y, self.x, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yxwx(self) -> UVec4 {
         UVec4::new(self.y, self.x, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yxwy(self) -> UVec4 {
         UVec4::new(self.y, self.x, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yxwz(self) -> UVec4 {
         UVec4::new(self.y, self.x, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yxww(self) -> UVec4 {
         UVec4::new(self.y, self.x, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yyxx(self) -> UVec4 {
         UVec4::new(self.y, self.y, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yyxy(self) -> UVec4 {
         UVec4::new(self.y, self.y, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yyxz(self) -> UVec4 {
         UVec4::new(self.y, self.y, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yyxw(self) -> UVec4 {
         UVec4::new(self.y, self.y, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yyyx(self) -> UVec4 {
         UVec4::new(self.y, self.y, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yyyy(self) -> UVec4 {
         UVec4::new(self.y, self.y, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yyyz(self) -> UVec4 {
         UVec4::new(self.y, self.y, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yyyw(self) -> UVec4 {
         UVec4::new(self.y, self.y, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yyzx(self) -> UVec4 {
         UVec4::new(self.y, self.y, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yyzy(self) -> UVec4 {
         UVec4::new(self.y, self.y, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yyzz(self) -> UVec4 {
         UVec4::new(self.y, self.y, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yyzw(self) -> UVec4 {
         UVec4::new(self.y, self.y, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yywx(self) -> UVec4 {
         UVec4::new(self.y, self.y, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yywy(self) -> UVec4 {
         UVec4::new(self.y, self.y, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yywz(self) -> UVec4 {
         UVec4::new(self.y, self.y, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yyww(self) -> UVec4 {
         UVec4::new(self.y, self.y, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yzxx(self) -> UVec4 {
         UVec4::new(self.y, self.z, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yzxy(self) -> UVec4 {
         UVec4::new(self.y, self.z, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yzxz(self) -> UVec4 {
         UVec4::new(self.y, self.z, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yzxw(self) -> UVec4 {
         UVec4::new(self.y, self.z, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yzyx(self) -> UVec4 {
         UVec4::new(self.y, self.z, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yzyy(self) -> UVec4 {
         UVec4::new(self.y, self.z, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yzyz(self) -> UVec4 {
         UVec4::new(self.y, self.z, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yzyw(self) -> UVec4 {
         UVec4::new(self.y, self.z, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yzzx(self) -> UVec4 {
         UVec4::new(self.y, self.z, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yzzy(self) -> UVec4 {
         UVec4::new(self.y, self.z, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yzzz(self) -> UVec4 {
         UVec4::new(self.y, self.z, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yzzw(self) -> UVec4 {
         UVec4::new(self.y, self.z, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn yzwx(self) -> UVec4 {
         UVec4::new(self.y, self.z, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yzwy(self) -> UVec4 {
         UVec4::new(self.y, self.z, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yzwz(self) -> UVec4 {
         UVec4::new(self.y, self.z, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yzww(self) -> UVec4 {
         UVec4::new(self.y, self.z, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn ywxx(self) -> UVec4 {
         UVec4::new(self.y, self.w, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn ywxy(self) -> UVec4 {
         UVec4::new(self.y, self.w, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn ywxz(self) -> UVec4 {
         UVec4::new(self.y, self.w, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn ywxw(self) -> UVec4 {
         UVec4::new(self.y, self.w, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn ywyx(self) -> UVec4 {
         UVec4::new(self.y, self.w, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn ywyy(self) -> UVec4 {
         UVec4::new(self.y, self.w, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn ywyz(self) -> UVec4 {
         UVec4::new(self.y, self.w, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn ywyw(self) -> UVec4 {
         UVec4::new(self.y, self.w, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn ywzx(self) -> UVec4 {
         UVec4::new(self.y, self.w, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn ywzy(self) -> UVec4 {
         UVec4::new(self.y, self.w, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn ywzz(self) -> UVec4 {
         UVec4::new(self.y, self.w, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn ywzw(self) -> UVec4 {
         UVec4::new(self.y, self.w, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn ywwx(self) -> UVec4 {
         UVec4::new(self.y, self.w, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn ywwy(self) -> UVec4 {
         UVec4::new(self.y, self.w, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn ywwz(self) -> UVec4 {
         UVec4::new(self.y, self.w, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn ywww(self) -> UVec4 {
         UVec4::new(self.y, self.w, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zxxx(self) -> UVec4 {
         UVec4::new(self.z, self.x, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zxxy(self) -> UVec4 {
         UVec4::new(self.z, self.x, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zxxz(self) -> UVec4 {
         UVec4::new(self.z, self.x, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zxxw(self) -> UVec4 {
         UVec4::new(self.z, self.x, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zxyx(self) -> UVec4 {
         UVec4::new(self.z, self.x, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zxyy(self) -> UVec4 {
         UVec4::new(self.z, self.x, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zxyz(self) -> UVec4 {
         UVec4::new(self.z, self.x, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zxyw(self) -> UVec4 {
         UVec4::new(self.z, self.x, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zxzx(self) -> UVec4 {
         UVec4::new(self.z, self.x, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zxzy(self) -> UVec4 {
         UVec4::new(self.z, self.x, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zxzz(self) -> UVec4 {
         UVec4::new(self.z, self.x, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zxzw(self) -> UVec4 {
         UVec4::new(self.z, self.x, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zxwx(self) -> UVec4 {
         UVec4::new(self.z, self.x, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zxwy(self) -> UVec4 {
         UVec4::new(self.z, self.x, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zxwz(self) -> UVec4 {
         UVec4::new(self.z, self.x, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zxww(self) -> UVec4 {
         UVec4::new(self.z, self.x, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zyxx(self) -> UVec4 {
         UVec4::new(self.z, self.y, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zyxy(self) -> UVec4 {
         UVec4::new(self.z, self.y, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zyxz(self) -> UVec4 {
         UVec4::new(self.z, self.y, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zyxw(self) -> UVec4 {
         UVec4::new(self.z, self.y, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zyyx(self) -> UVec4 {
         UVec4::new(self.z, self.y, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zyyy(self) -> UVec4 {
         UVec4::new(self.z, self.y, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zyyz(self) -> UVec4 {
         UVec4::new(self.z, self.y, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zyyw(self) -> UVec4 {
         UVec4::new(self.z, self.y, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zyzx(self) -> UVec4 {
         UVec4::new(self.z, self.y, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zyzy(self) -> UVec4 {
         UVec4::new(self.z, self.y, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zyzz(self) -> UVec4 {
         UVec4::new(self.z, self.y, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zyzw(self) -> UVec4 {
         UVec4::new(self.z, self.y, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zywx(self) -> UVec4 {
         UVec4::new(self.z, self.y, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zywy(self) -> UVec4 {
         UVec4::new(self.z, self.y, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zywz(self) -> UVec4 {
         UVec4::new(self.z, self.y, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zyww(self) -> UVec4 {
         UVec4::new(self.z, self.y, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zzxx(self) -> UVec4 {
         UVec4::new(self.z, self.z, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zzxy(self) -> UVec4 {
         UVec4::new(self.z, self.z, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zzxz(self) -> UVec4 {
         UVec4::new(self.z, self.z, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zzxw(self) -> UVec4 {
         UVec4::new(self.z, self.z, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zzyx(self) -> UVec4 {
         UVec4::new(self.z, self.z, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zzyy(self) -> UVec4 {
         UVec4::new(self.z, self.z, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zzyz(self) -> UVec4 {
         UVec4::new(self.z, self.z, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zzyw(self) -> UVec4 {
         UVec4::new(self.z, self.z, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zzzx(self) -> UVec4 {
         UVec4::new(self.z, self.z, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zzzy(self) -> UVec4 {
         UVec4::new(self.z, self.z, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zzzz(self) -> UVec4 {
         UVec4::new(self.z, self.z, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zzzw(self) -> UVec4 {
         UVec4::new(self.z, self.z, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zzwx(self) -> UVec4 {
         UVec4::new(self.z, self.z, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zzwy(self) -> UVec4 {
         UVec4::new(self.z, self.z, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zzwz(self) -> UVec4 {
         UVec4::new(self.z, self.z, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zzww(self) -> UVec4 {
         UVec4::new(self.z, self.z, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zwxx(self) -> UVec4 {
         UVec4::new(self.z, self.w, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zwxy(self) -> UVec4 {
         UVec4::new(self.z, self.w, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zwxz(self) -> UVec4 {
         UVec4::new(self.z, self.w, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zwxw(self) -> UVec4 {
         UVec4::new(self.z, self.w, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zwyx(self) -> UVec4 {
         UVec4::new(self.z, self.w, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zwyy(self) -> UVec4 {
         UVec4::new(self.z, self.w, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zwyz(self) -> UVec4 {
         UVec4::new(self.z, self.w, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zwyw(self) -> UVec4 {
         UVec4::new(self.z, self.w, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zwzx(self) -> UVec4 {
         UVec4::new(self.z, self.w, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zwzy(self) -> UVec4 {
         UVec4::new(self.z, self.w, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zwzz(self) -> UVec4 {
         UVec4::new(self.z, self.w, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zwzw(self) -> UVec4 {
         UVec4::new(self.z, self.w, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn zwwx(self) -> UVec4 {
         UVec4::new(self.z, self.w, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zwwy(self) -> UVec4 {
         UVec4::new(self.z, self.w, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zwwz(self) -> UVec4 {
         UVec4::new(self.z, self.w, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zwww(self) -> UVec4 {
         UVec4::new(self.z, self.w, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wxxx(self) -> UVec4 {
         UVec4::new(self.w, self.x, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wxxy(self) -> UVec4 {
         UVec4::new(self.w, self.x, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wxxz(self) -> UVec4 {
         UVec4::new(self.w, self.x, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wxxw(self) -> UVec4 {
         UVec4::new(self.w, self.x, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wxyx(self) -> UVec4 {
         UVec4::new(self.w, self.x, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wxyy(self) -> UVec4 {
         UVec4::new(self.w, self.x, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wxyz(self) -> UVec4 {
         UVec4::new(self.w, self.x, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wxyw(self) -> UVec4 {
         UVec4::new(self.w, self.x, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wxzx(self) -> UVec4 {
         UVec4::new(self.w, self.x, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wxzy(self) -> UVec4 {
         UVec4::new(self.w, self.x, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wxzz(self) -> UVec4 {
         UVec4::new(self.w, self.x, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wxzw(self) -> UVec4 {
         UVec4::new(self.w, self.x, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wxwx(self) -> UVec4 {
         UVec4::new(self.w, self.x, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wxwy(self) -> UVec4 {
         UVec4::new(self.w, self.x, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wxwz(self) -> UVec4 {
         UVec4::new(self.w, self.x, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wxww(self) -> UVec4 {
         UVec4::new(self.w, self.x, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wyxx(self) -> UVec4 {
         UVec4::new(self.w, self.y, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wyxy(self) -> UVec4 {
         UVec4::new(self.w, self.y, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wyxz(self) -> UVec4 {
         UVec4::new(self.w, self.y, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wyxw(self) -> UVec4 {
         UVec4::new(self.w, self.y, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wyyx(self) -> UVec4 {
         UVec4::new(self.w, self.y, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wyyy(self) -> UVec4 {
         UVec4::new(self.w, self.y, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wyyz(self) -> UVec4 {
         UVec4::new(self.w, self.y, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wyyw(self) -> UVec4 {
         UVec4::new(self.w, self.y, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wyzx(self) -> UVec4 {
         UVec4::new(self.w, self.y, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wyzy(self) -> UVec4 {
         UVec4::new(self.w, self.y, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wyzz(self) -> UVec4 {
         UVec4::new(self.w, self.y, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wyzw(self) -> UVec4 {
         UVec4::new(self.w, self.y, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wywx(self) -> UVec4 {
         UVec4::new(self.w, self.y, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wywy(self) -> UVec4 {
         UVec4::new(self.w, self.y, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wywz(self) -> UVec4 {
         UVec4::new(self.w, self.y, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wyww(self) -> UVec4 {
         UVec4::new(self.w, self.y, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wzxx(self) -> UVec4 {
         UVec4::new(self.w, self.z, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wzxy(self) -> UVec4 {
         UVec4::new(self.w, self.z, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wzxz(self) -> UVec4 {
         UVec4::new(self.w, self.z, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wzxw(self) -> UVec4 {
         UVec4::new(self.w, self.z, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wzyx(self) -> UVec4 {
         UVec4::new(self.w, self.z, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wzyy(self) -> UVec4 {
         UVec4::new(self.w, self.z, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wzyz(self) -> UVec4 {
         UVec4::new(self.w, self.z, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wzyw(self) -> UVec4 {
         UVec4::new(self.w, self.z, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wzzx(self) -> UVec4 {
         UVec4::new(self.w, self.z, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wzzy(self) -> UVec4 {
         UVec4::new(self.w, self.z, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wzzz(self) -> UVec4 {
         UVec4::new(self.w, self.z, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wzzw(self) -> UVec4 {
         UVec4::new(self.w, self.z, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wzwx(self) -> UVec4 {
         UVec4::new(self.w, self.z, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wzwy(self) -> UVec4 {
         UVec4::new(self.w, self.z, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wzwz(self) -> UVec4 {
         UVec4::new(self.w, self.z, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wzww(self) -> UVec4 {
         UVec4::new(self.w, self.z, self.w, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wwxx(self) -> UVec4 {
         UVec4::new(self.w, self.w, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wwxy(self) -> UVec4 {
         UVec4::new(self.w, self.w, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wwxz(self) -> UVec4 {
         UVec4::new(self.w, self.w, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wwxw(self) -> UVec4 {
         UVec4::new(self.w, self.w, self.x, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wwyx(self) -> UVec4 {
         UVec4::new(self.w, self.w, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wwyy(self) -> UVec4 {
         UVec4::new(self.w, self.w, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wwyz(self) -> UVec4 {
         UVec4::new(self.w, self.w, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wwyw(self) -> UVec4 {
         UVec4::new(self.w, self.w, self.y, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wwzx(self) -> UVec4 {
         UVec4::new(self.w, self.w, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wwzy(self) -> UVec4 {
         UVec4::new(self.w, self.w, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wwzz(self) -> UVec4 {
         UVec4::new(self.w, self.w, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wwzw(self) -> UVec4 {
         UVec4::new(self.w, self.w, self.z, self.w)
     }
 
     #[inline]
+    #[must_use]
     fn wwwx(self) -> UVec4 {
         UVec4::new(self.w, self.w, self.w, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn wwwy(self) -> UVec4 {
         UVec4::new(self.w, self.w, self.w, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn wwwz(self) -> UVec4 {
         UVec4::new(self.w, self.w, self.w, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn wwww(self) -> UVec4 {
         UVec4::new(self.w, self.w, self.w, self.w)
     }
diff --git a/src/swizzles/vec2_impl.rs b/src/swizzles/vec2_impl.rs
index 4842194..e4d68aa 100644
--- a/src/swizzles/vec2_impl.rs
+++ b/src/swizzles/vec2_impl.rs
@@ -8,6 +8,7 @@
     type Vec4 = Vec4;
 
     #[inline]
+    #[must_use]
     fn xx(self) -> Vec2 {
         Vec2 {
             x: self.x,
@@ -16,6 +17,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xy(self) -> Vec2 {
         Vec2 {
             x: self.x,
@@ -24,6 +26,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yx(self) -> Vec2 {
         Vec2 {
             x: self.y,
@@ -32,6 +35,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yy(self) -> Vec2 {
         Vec2 {
             x: self.y,
@@ -40,6 +44,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxx(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -49,6 +54,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxy(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -58,6 +64,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyx(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -67,6 +74,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyy(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -76,6 +84,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxx(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -85,6 +94,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxy(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -94,6 +104,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyx(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -103,6 +114,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyy(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -112,81 +124,97 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxxx(self) -> Vec4 {
         Vec4::new(self.x, self.x, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xxxy(self) -> Vec4 {
         Vec4::new(self.x, self.x, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xxyx(self) -> Vec4 {
         Vec4::new(self.x, self.x, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xxyy(self) -> Vec4 {
         Vec4::new(self.x, self.x, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xyxx(self) -> Vec4 {
         Vec4::new(self.x, self.y, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xyxy(self) -> Vec4 {
         Vec4::new(self.x, self.y, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xyyx(self) -> Vec4 {
         Vec4::new(self.x, self.y, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xyyy(self) -> Vec4 {
         Vec4::new(self.x, self.y, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yxxx(self) -> Vec4 {
         Vec4::new(self.y, self.x, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yxxy(self) -> Vec4 {
         Vec4::new(self.y, self.x, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yxyx(self) -> Vec4 {
         Vec4::new(self.y, self.x, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yxyy(self) -> Vec4 {
         Vec4::new(self.y, self.x, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yyxx(self) -> Vec4 {
         Vec4::new(self.y, self.y, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yyxy(self) -> Vec4 {
         Vec4::new(self.y, self.y, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yyyx(self) -> Vec4 {
         Vec4::new(self.y, self.y, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yyyy(self) -> Vec4 {
         Vec4::new(self.y, self.y, self.y, self.y)
     }
diff --git a/src/swizzles/vec3_impl.rs b/src/swizzles/vec3_impl.rs
index e60e8e1..db657e2 100644
--- a/src/swizzles/vec3_impl.rs
+++ b/src/swizzles/vec3_impl.rs
@@ -8,6 +8,7 @@
     type Vec4 = Vec4;
 
     #[inline]
+    #[must_use]
     fn xx(self) -> Vec2 {
         Vec2 {
             x: self.x,
@@ -16,6 +17,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xy(self) -> Vec2 {
         Vec2 {
             x: self.x,
@@ -24,6 +26,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xz(self) -> Vec2 {
         Vec2 {
             x: self.x,
@@ -32,6 +35,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yx(self) -> Vec2 {
         Vec2 {
             x: self.y,
@@ -40,6 +44,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yy(self) -> Vec2 {
         Vec2 {
             x: self.y,
@@ -48,6 +53,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yz(self) -> Vec2 {
         Vec2 {
             x: self.y,
@@ -56,6 +62,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zx(self) -> Vec2 {
         Vec2 {
             x: self.z,
@@ -64,6 +71,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zy(self) -> Vec2 {
         Vec2 {
             x: self.z,
@@ -72,6 +80,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zz(self) -> Vec2 {
         Vec2 {
             x: self.z,
@@ -80,6 +89,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxx(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -89,6 +99,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxy(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -98,6 +109,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxz(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -107,6 +119,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyx(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -116,6 +129,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyy(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -125,6 +139,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyz(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -134,6 +149,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzx(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -143,6 +159,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzy(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -152,6 +169,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzz(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -161,6 +179,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxx(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -170,6 +189,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxy(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -179,6 +199,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxz(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -188,6 +209,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyx(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -197,6 +219,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyy(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -206,6 +229,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyz(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -215,6 +239,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzx(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -224,6 +249,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzy(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -233,6 +259,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzz(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -242,6 +269,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxx(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -251,6 +279,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxy(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -260,6 +289,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxz(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -269,6 +299,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyx(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -278,6 +309,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyy(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -287,6 +319,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyz(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -296,6 +329,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzx(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -305,6 +339,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzy(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -314,6 +349,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzz(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -323,406 +359,487 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxxx(self) -> Vec4 {
         Vec4::new(self.x, self.x, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xxxy(self) -> Vec4 {
         Vec4::new(self.x, self.x, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xxxz(self) -> Vec4 {
         Vec4::new(self.x, self.x, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xxyx(self) -> Vec4 {
         Vec4::new(self.x, self.x, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xxyy(self) -> Vec4 {
         Vec4::new(self.x, self.x, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xxyz(self) -> Vec4 {
         Vec4::new(self.x, self.x, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xxzx(self) -> Vec4 {
         Vec4::new(self.x, self.x, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xxzy(self) -> Vec4 {
         Vec4::new(self.x, self.x, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xxzz(self) -> Vec4 {
         Vec4::new(self.x, self.x, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xyxx(self) -> Vec4 {
         Vec4::new(self.x, self.y, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xyxy(self) -> Vec4 {
         Vec4::new(self.x, self.y, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xyxz(self) -> Vec4 {
         Vec4::new(self.x, self.y, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xyyx(self) -> Vec4 {
         Vec4::new(self.x, self.y, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xyyy(self) -> Vec4 {
         Vec4::new(self.x, self.y, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xyyz(self) -> Vec4 {
         Vec4::new(self.x, self.y, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xyzx(self) -> Vec4 {
         Vec4::new(self.x, self.y, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xyzy(self) -> Vec4 {
         Vec4::new(self.x, self.y, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xyzz(self) -> Vec4 {
         Vec4::new(self.x, self.y, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xzxx(self) -> Vec4 {
         Vec4::new(self.x, self.z, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xzxy(self) -> Vec4 {
         Vec4::new(self.x, self.z, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xzxz(self) -> Vec4 {
         Vec4::new(self.x, self.z, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xzyx(self) -> Vec4 {
         Vec4::new(self.x, self.z, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xzyy(self) -> Vec4 {
         Vec4::new(self.x, self.z, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xzyz(self) -> Vec4 {
         Vec4::new(self.x, self.z, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn xzzx(self) -> Vec4 {
         Vec4::new(self.x, self.z, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn xzzy(self) -> Vec4 {
         Vec4::new(self.x, self.z, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn xzzz(self) -> Vec4 {
         Vec4::new(self.x, self.z, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yxxx(self) -> Vec4 {
         Vec4::new(self.y, self.x, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yxxy(self) -> Vec4 {
         Vec4::new(self.y, self.x, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yxxz(self) -> Vec4 {
         Vec4::new(self.y, self.x, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yxyx(self) -> Vec4 {
         Vec4::new(self.y, self.x, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yxyy(self) -> Vec4 {
         Vec4::new(self.y, self.x, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yxyz(self) -> Vec4 {
         Vec4::new(self.y, self.x, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yxzx(self) -> Vec4 {
         Vec4::new(self.y, self.x, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yxzy(self) -> Vec4 {
         Vec4::new(self.y, self.x, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yxzz(self) -> Vec4 {
         Vec4::new(self.y, self.x, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yyxx(self) -> Vec4 {
         Vec4::new(self.y, self.y, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yyxy(self) -> Vec4 {
         Vec4::new(self.y, self.y, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yyxz(self) -> Vec4 {
         Vec4::new(self.y, self.y, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yyyx(self) -> Vec4 {
         Vec4::new(self.y, self.y, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yyyy(self) -> Vec4 {
         Vec4::new(self.y, self.y, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yyyz(self) -> Vec4 {
         Vec4::new(self.y, self.y, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yyzx(self) -> Vec4 {
         Vec4::new(self.y, self.y, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yyzy(self) -> Vec4 {
         Vec4::new(self.y, self.y, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yyzz(self) -> Vec4 {
         Vec4::new(self.y, self.y, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yzxx(self) -> Vec4 {
         Vec4::new(self.y, self.z, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yzxy(self) -> Vec4 {
         Vec4::new(self.y, self.z, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yzxz(self) -> Vec4 {
         Vec4::new(self.y, self.z, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yzyx(self) -> Vec4 {
         Vec4::new(self.y, self.z, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yzyy(self) -> Vec4 {
         Vec4::new(self.y, self.z, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yzyz(self) -> Vec4 {
         Vec4::new(self.y, self.z, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn yzzx(self) -> Vec4 {
         Vec4::new(self.y, self.z, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn yzzy(self) -> Vec4 {
         Vec4::new(self.y, self.z, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn yzzz(self) -> Vec4 {
         Vec4::new(self.y, self.z, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zxxx(self) -> Vec4 {
         Vec4::new(self.z, self.x, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zxxy(self) -> Vec4 {
         Vec4::new(self.z, self.x, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zxxz(self) -> Vec4 {
         Vec4::new(self.z, self.x, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zxyx(self) -> Vec4 {
         Vec4::new(self.z, self.x, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zxyy(self) -> Vec4 {
         Vec4::new(self.z, self.x, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zxyz(self) -> Vec4 {
         Vec4::new(self.z, self.x, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zxzx(self) -> Vec4 {
         Vec4::new(self.z, self.x, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zxzy(self) -> Vec4 {
         Vec4::new(self.z, self.x, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zxzz(self) -> Vec4 {
         Vec4::new(self.z, self.x, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zyxx(self) -> Vec4 {
         Vec4::new(self.z, self.y, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zyxy(self) -> Vec4 {
         Vec4::new(self.z, self.y, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zyxz(self) -> Vec4 {
         Vec4::new(self.z, self.y, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zyyx(self) -> Vec4 {
         Vec4::new(self.z, self.y, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zyyy(self) -> Vec4 {
         Vec4::new(self.z, self.y, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zyyz(self) -> Vec4 {
         Vec4::new(self.z, self.y, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zyzx(self) -> Vec4 {
         Vec4::new(self.z, self.y, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zyzy(self) -> Vec4 {
         Vec4::new(self.z, self.y, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zyzz(self) -> Vec4 {
         Vec4::new(self.z, self.y, self.z, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zzxx(self) -> Vec4 {
         Vec4::new(self.z, self.z, self.x, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zzxy(self) -> Vec4 {
         Vec4::new(self.z, self.z, self.x, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zzxz(self) -> Vec4 {
         Vec4::new(self.z, self.z, self.x, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zzyx(self) -> Vec4 {
         Vec4::new(self.z, self.z, self.y, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zzyy(self) -> Vec4 {
         Vec4::new(self.z, self.z, self.y, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zzyz(self) -> Vec4 {
         Vec4::new(self.z, self.z, self.y, self.z)
     }
 
     #[inline]
+    #[must_use]
     fn zzzx(self) -> Vec4 {
         Vec4::new(self.z, self.z, self.z, self.x)
     }
 
     #[inline]
+    #[must_use]
     fn zzzy(self) -> Vec4 {
         Vec4::new(self.z, self.z, self.z, self.y)
     }
 
     #[inline]
+    #[must_use]
     fn zzzz(self) -> Vec4 {
         Vec4::new(self.z, self.z, self.z, self.z)
     }
diff --git a/src/swizzles/vec_traits.rs b/src/swizzles/vec_traits.rs
index 3b95433..2b6481c 100644
--- a/src/swizzles/vec_traits.rs
+++ b/src/swizzles/vec_traits.rs
@@ -6,6 +6,7 @@
     type Vec4;
 
     #[inline]
+    #[must_use]
     fn xy(self) -> Self {
         self
     }
@@ -71,6 +72,7 @@
     type Vec4;
 
     #[inline]
+    #[must_use]
     fn xyz(self) -> Self {
         self
     }
@@ -314,6 +316,7 @@
     type Vec3;
 
     #[inline]
+    #[must_use]
     fn xyzw(self) -> Self {
         self
     }
diff --git a/src/swizzles/wasm32/vec3a_impl.rs b/src/swizzles/wasm32/vec3a_impl.rs
index 978f494..7bfe7cc 100644
--- a/src/swizzles/wasm32/vec3a_impl.rs
+++ b/src/swizzles/wasm32/vec3a_impl.rs
@@ -12,6 +12,7 @@
     type Vec4 = Vec4;
 
     #[inline]
+    #[must_use]
     fn xx(self) -> Vec2 {
         Vec2 {
             x: self.x,
@@ -20,6 +21,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xy(self) -> Vec2 {
         Vec2 {
             x: self.x,
@@ -28,6 +30,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xz(self) -> Vec2 {
         Vec2 {
             x: self.x,
@@ -36,6 +39,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yx(self) -> Vec2 {
         Vec2 {
             x: self.y,
@@ -44,6 +48,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yy(self) -> Vec2 {
         Vec2 {
             x: self.y,
@@ -52,6 +57,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yz(self) -> Vec2 {
         Vec2 {
             x: self.y,
@@ -60,6 +66,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zx(self) -> Vec2 {
         Vec2 {
             x: self.z,
@@ -68,6 +75,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zy(self) -> Vec2 {
         Vec2 {
             x: self.z,
@@ -76,6 +84,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zz(self) -> Vec2 {
         Vec2 {
             x: self.z,
@@ -84,541 +93,649 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxx(self) -> Vec3A {
         Vec3A(i32x4_shuffle::<0, 0, 4, 4>(self.0, self.0).into())
     }
 
     #[inline]
+    #[must_use]
     fn xxy(self) -> Vec3A {
         Vec3A(i32x4_shuffle::<0, 0, 5, 4>(self.0, self.0).into())
     }
 
     #[inline]
+    #[must_use]
     fn xxz(self) -> Vec3A {
         Vec3A(i32x4_shuffle::<0, 0, 6, 4>(self.0, self.0).into())
     }
 
     #[inline]
+    #[must_use]
     fn xyx(self) -> Vec3A {
         Vec3A(i32x4_shuffle::<0, 1, 4, 4>(self.0, self.0).into())
     }
 
     #[inline]
+    #[must_use]
     fn xyy(self) -> Vec3A {
         Vec3A(i32x4_shuffle::<0, 1, 5, 4>(self.0, self.0).into())
     }
 
     #[inline]
+    #[must_use]
     fn xyz(self) -> Vec3A {
         Vec3A(i32x4_shuffle::<0, 1, 6, 4>(self.0, self.0).into())
     }
 
     #[inline]
+    #[must_use]
     fn xzx(self) -> Vec3A {
         Vec3A(i32x4_shuffle::<0, 2, 4, 4>(self.0, self.0).into())
     }
 
     #[inline]
+    #[must_use]
     fn xzy(self) -> Vec3A {
         Vec3A(i32x4_shuffle::<0, 2, 5, 4>(self.0, self.0).into())
     }
 
     #[inline]
+    #[must_use]
     fn xzz(self) -> Vec3A {
         Vec3A(i32x4_shuffle::<0, 2, 6, 4>(self.0, self.0).into())
     }
 
     #[inline]
+    #[must_use]
     fn yxx(self) -> Vec3A {
         Vec3A(i32x4_shuffle::<1, 0, 4, 4>(self.0, self.0).into())
     }
 
     #[inline]
+    #[must_use]
     fn yxy(self) -> Vec3A {
         Vec3A(i32x4_shuffle::<1, 0, 5, 4>(self.0, self.0).into())
     }
 
     #[inline]
+    #[must_use]
     fn yxz(self) -> Vec3A {
         Vec3A(i32x4_shuffle::<1, 0, 6, 4>(self.0, self.0).into())
     }
 
     #[inline]
+    #[must_use]
     fn yyx(self) -> Vec3A {
         Vec3A(i32x4_shuffle::<1, 1, 4, 4>(self.0, self.0).into())
     }
 
     #[inline]
+    #[must_use]
     fn yyy(self) -> Vec3A {
         Vec3A(i32x4_shuffle::<1, 1, 5, 4>(self.0, self.0).into())
     }
 
     #[inline]
+    #[must_use]
     fn yyz(self) -> Vec3A {
         Vec3A(i32x4_shuffle::<1, 1, 6, 4>(self.0, self.0).into())
     }
 
     #[inline]
+    #[must_use]
     fn yzx(self) -> Vec3A {
         Vec3A(i32x4_shuffle::<1, 2, 4, 4>(self.0, self.0).into())
     }
 
     #[inline]
+    #[must_use]
     fn yzy(self) -> Vec3A {
         Vec3A(i32x4_shuffle::<1, 2, 5, 4>(self.0, self.0).into())
     }
 
     #[inline]
+    #[must_use]
     fn yzz(self) -> Vec3A {
         Vec3A(i32x4_shuffle::<1, 2, 6, 4>(self.0, self.0).into())
     }
 
     #[inline]
+    #[must_use]
     fn zxx(self) -> Vec3A {
         Vec3A(i32x4_shuffle::<2, 0, 4, 4>(self.0, self.0).into())
     }
 
     #[inline]
+    #[must_use]
     fn zxy(self) -> Vec3A {
         Vec3A(i32x4_shuffle::<2, 0, 5, 4>(self.0, self.0).into())
     }
 
     #[inline]
+    #[must_use]
     fn zxz(self) -> Vec3A {
         Vec3A(i32x4_shuffle::<2, 0, 6, 4>(self.0, self.0).into())
     }
 
     #[inline]
+    #[must_use]
     fn zyx(self) -> Vec3A {
         Vec3A(i32x4_shuffle::<2, 1, 4, 4>(self.0, self.0).into())
     }
 
     #[inline]
+    #[must_use]
     fn zyy(self) -> Vec3A {
         Vec3A(i32x4_shuffle::<2, 1, 5, 4>(self.0, self.0).into())
     }
 
     #[inline]
+    #[must_use]
     fn zyz(self) -> Vec3A {
         Vec3A(i32x4_shuffle::<2, 1, 6, 4>(self.0, self.0).into())
     }
 
     #[inline]
+    #[must_use]
     fn zzx(self) -> Vec3A {
         Vec3A(i32x4_shuffle::<2, 2, 4, 4>(self.0, self.0).into())
     }
 
     #[inline]
+    #[must_use]
     fn zzy(self) -> Vec3A {
         Vec3A(i32x4_shuffle::<2, 2, 5, 4>(self.0, self.0).into())
     }
 
     #[inline]
+    #[must_use]
     fn zzz(self) -> Vec3A {
         Vec3A(i32x4_shuffle::<2, 2, 6, 4>(self.0, self.0).into())
     }
 
     #[inline]
+    #[must_use]
     fn xxxx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 0, 4, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xxxy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 0, 4, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xxxz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 0, 4, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xxyx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 0, 5, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xxyy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 0, 5, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xxyz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 0, 5, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xxzx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 0, 6, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xxzy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 0, 6, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xxzz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 0, 6, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xyxx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 1, 4, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xyxy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 1, 4, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xyxz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 1, 4, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xyyx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 1, 5, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xyyy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 1, 5, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xyyz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 1, 5, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xyzx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 1, 6, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xyzy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 1, 6, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xyzz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 1, 6, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xzxx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 2, 4, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xzxy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 2, 4, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xzxz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 2, 4, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xzyx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 2, 5, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xzyy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 2, 5, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xzyz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 2, 5, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xzzx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 2, 6, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xzzy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 2, 6, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xzzz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 2, 6, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yxxx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 0, 4, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yxxy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 0, 4, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yxxz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 0, 4, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yxyx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 0, 5, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yxyy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 0, 5, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yxyz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 0, 5, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yxzx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 0, 6, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yxzy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 0, 6, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yxzz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 0, 6, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yyxx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 1, 4, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yyxy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 1, 4, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yyxz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 1, 4, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yyyx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 1, 5, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yyyy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 1, 5, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yyyz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 1, 5, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yyzx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 1, 6, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yyzy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 1, 6, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yyzz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 1, 6, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yzxx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 2, 4, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yzxy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 2, 4, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yzxz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 2, 4, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yzyx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 2, 5, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yzyy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 2, 5, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yzyz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 2, 5, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yzzx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 2, 6, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yzzy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 2, 6, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yzzz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 2, 6, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zxxx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 0, 4, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zxxy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 0, 4, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zxxz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 0, 4, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zxyx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 0, 5, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zxyy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 0, 5, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zxyz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 0, 5, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zxzx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 0, 6, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zxzy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 0, 6, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zxzz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 0, 6, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zyxx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 1, 4, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zyxy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 1, 4, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zyxz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 1, 4, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zyyx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 1, 5, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zyyy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 1, 5, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zyyz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 1, 5, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zyzx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 1, 6, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zyzy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 1, 6, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zyzz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 1, 6, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zzxx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 2, 4, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zzxy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 2, 4, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zzxz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 2, 4, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zzyx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 2, 5, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zzyy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 2, 5, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zzyz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 2, 5, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zzzx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 2, 6, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zzzy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 2, 6, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zzzz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 2, 6, 6>(self.0, self.0))
     }
diff --git a/src/swizzles/wasm32/vec4_impl.rs b/src/swizzles/wasm32/vec4_impl.rs
index 73ff28f..5b58927 100644
--- a/src/swizzles/wasm32/vec4_impl.rs
+++ b/src/swizzles/wasm32/vec4_impl.rs
@@ -12,6 +12,7 @@
     type Vec3 = Vec3;
 
     #[inline]
+    #[must_use]
     fn xx(self) -> Vec2 {
         Vec2 {
             x: self.x,
@@ -20,6 +21,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xy(self) -> Vec2 {
         Vec2 {
             x: self.x,
@@ -28,6 +30,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xz(self) -> Vec2 {
         Vec2 {
             x: self.x,
@@ -36,6 +39,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xw(self) -> Vec2 {
         Vec2 {
             x: self.x,
@@ -44,6 +48,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yx(self) -> Vec2 {
         Vec2 {
             x: self.y,
@@ -52,6 +57,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yy(self) -> Vec2 {
         Vec2 {
             x: self.y,
@@ -60,6 +66,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yz(self) -> Vec2 {
         Vec2 {
             x: self.y,
@@ -68,6 +75,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yw(self) -> Vec2 {
         Vec2 {
             x: self.y,
@@ -76,6 +84,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zx(self) -> Vec2 {
         Vec2 {
             x: self.z,
@@ -84,6 +93,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zy(self) -> Vec2 {
         Vec2 {
             x: self.z,
@@ -92,6 +102,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zz(self) -> Vec2 {
         Vec2 {
             x: self.z,
@@ -100,6 +111,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zw(self) -> Vec2 {
         Vec2 {
             x: self.z,
@@ -108,6 +120,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wx(self) -> Vec2 {
         Vec2 {
             x: self.w,
@@ -116,6 +129,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wy(self) -> Vec2 {
         Vec2 {
             x: self.w,
@@ -124,6 +138,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wz(self) -> Vec2 {
         Vec2 {
             x: self.w,
@@ -132,6 +147,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn ww(self) -> Vec2 {
         Vec2 {
             x: self.w,
@@ -140,6 +156,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxx(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -149,6 +166,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxy(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -158,6 +176,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxz(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -167,6 +186,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxw(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -176,6 +196,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyx(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -185,6 +206,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyy(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -194,6 +216,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyz(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -203,6 +226,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xyw(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -212,6 +236,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzx(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -221,6 +246,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzy(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -230,6 +256,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzz(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -239,6 +266,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xzw(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -248,6 +276,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xwx(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -257,6 +286,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xwy(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -266,6 +296,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xwz(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -275,6 +306,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn xww(self) -> Vec3 {
         Vec3 {
             x: self.x,
@@ -284,6 +316,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxx(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -293,6 +326,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxy(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -302,6 +336,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxz(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -311,6 +346,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yxw(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -320,6 +356,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyx(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -329,6 +366,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyy(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -338,6 +376,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyz(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -347,6 +386,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yyw(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -356,6 +396,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzx(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -365,6 +406,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzy(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -374,6 +416,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzz(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -383,6 +426,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yzw(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -392,6 +436,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn ywx(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -401,6 +446,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn ywy(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -410,6 +456,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn ywz(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -419,6 +466,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn yww(self) -> Vec3 {
         Vec3 {
             x: self.y,
@@ -428,6 +476,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxx(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -437,6 +486,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxy(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -446,6 +496,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxz(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -455,6 +506,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zxw(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -464,6 +516,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyx(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -473,6 +526,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyy(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -482,6 +536,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyz(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -491,6 +546,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zyw(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -500,6 +556,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzx(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -509,6 +566,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzy(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -518,6 +576,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzz(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -527,6 +586,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zzw(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -536,6 +596,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zwx(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -545,6 +606,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zwy(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -554,6 +616,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zwz(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -563,6 +626,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn zww(self) -> Vec3 {
         Vec3 {
             x: self.z,
@@ -572,6 +636,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wxx(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -581,6 +646,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wxy(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -590,6 +656,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wxz(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -599,6 +666,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wxw(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -608,6 +676,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wyx(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -617,6 +686,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wyy(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -626,6 +696,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wyz(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -635,6 +706,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wyw(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -644,6 +716,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wzx(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -653,6 +726,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wzy(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -662,6 +736,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wzz(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -671,6 +746,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wzw(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -680,6 +756,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wwx(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -689,6 +766,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wwy(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -698,6 +776,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn wwz(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -707,6 +786,7 @@
     }
 
     #[inline]
+    #[must_use]
     fn www(self) -> Vec3 {
         Vec3 {
             x: self.w,
@@ -716,1281 +796,1537 @@
     }
 
     #[inline]
+    #[must_use]
     fn xxxx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 0, 4, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xxxy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 0, 4, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xxxz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 0, 4, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xxxw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 0, 4, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xxyx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 0, 5, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xxyy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 0, 5, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xxyz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 0, 5, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xxyw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 0, 5, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xxzx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 0, 6, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xxzy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 0, 6, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xxzz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 0, 6, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xxzw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 0, 6, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xxwx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 0, 7, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xxwy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 0, 7, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xxwz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 0, 7, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xxww(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 0, 7, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xyxx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 1, 4, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xyxy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 1, 4, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xyxz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 1, 4, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xyxw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 1, 4, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xyyx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 1, 5, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xyyy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 1, 5, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xyyz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 1, 5, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xyyw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 1, 5, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xyzx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 1, 6, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xyzy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 1, 6, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xyzz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 1, 6, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xyzw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 1, 6, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xywx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 1, 7, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xywy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 1, 7, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xywz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 1, 7, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xyww(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 1, 7, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xzxx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 2, 4, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xzxy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 2, 4, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xzxz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 2, 4, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xzxw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 2, 4, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xzyx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 2, 5, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xzyy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 2, 5, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xzyz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 2, 5, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xzyw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 2, 5, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xzzx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 2, 6, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xzzy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 2, 6, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xzzz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 2, 6, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xzzw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 2, 6, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xzwx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 2, 7, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xzwy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 2, 7, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xzwz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 2, 7, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xzww(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 2, 7, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xwxx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 3, 4, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xwxy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 3, 4, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xwxz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 3, 4, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xwxw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 3, 4, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xwyx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 3, 5, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xwyy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 3, 5, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xwyz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 3, 5, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xwyw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 3, 5, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xwzx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 3, 6, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xwzy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 3, 6, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xwzz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 3, 6, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xwzw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 3, 6, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xwwx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 3, 7, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xwwy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 3, 7, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xwwz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 3, 7, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn xwww(self) -> Vec4 {
         Vec4(i32x4_shuffle::<0, 3, 7, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yxxx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 0, 4, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yxxy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 0, 4, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yxxz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 0, 4, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yxxw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 0, 4, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yxyx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 0, 5, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yxyy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 0, 5, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yxyz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 0, 5, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yxyw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 0, 5, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yxzx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 0, 6, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yxzy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 0, 6, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yxzz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 0, 6, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yxzw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 0, 6, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yxwx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 0, 7, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yxwy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 0, 7, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yxwz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 0, 7, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yxww(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 0, 7, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yyxx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 1, 4, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yyxy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 1, 4, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yyxz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 1, 4, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yyxw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 1, 4, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yyyx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 1, 5, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yyyy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 1, 5, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yyyz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 1, 5, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yyyw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 1, 5, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yyzx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 1, 6, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yyzy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 1, 6, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yyzz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 1, 6, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yyzw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 1, 6, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yywx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 1, 7, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yywy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 1, 7, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yywz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 1, 7, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yyww(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 1, 7, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yzxx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 2, 4, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yzxy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 2, 4, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yzxz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 2, 4, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yzxw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 2, 4, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yzyx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 2, 5, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yzyy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 2, 5, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yzyz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 2, 5, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yzyw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 2, 5, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yzzx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 2, 6, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yzzy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 2, 6, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yzzz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 2, 6, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yzzw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 2, 6, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yzwx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 2, 7, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yzwy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 2, 7, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yzwz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 2, 7, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn yzww(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 2, 7, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn ywxx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 3, 4, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn ywxy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 3, 4, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn ywxz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 3, 4, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn ywxw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 3, 4, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn ywyx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 3, 5, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn ywyy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 3, 5, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn ywyz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 3, 5, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn ywyw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 3, 5, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn ywzx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 3, 6, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn ywzy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 3, 6, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn ywzz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 3, 6, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn ywzw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 3, 6, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn ywwx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 3, 7, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn ywwy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 3, 7, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn ywwz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 3, 7, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn ywww(self) -> Vec4 {
         Vec4(i32x4_shuffle::<1, 3, 7, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zxxx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 0, 4, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zxxy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 0, 4, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zxxz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 0, 4, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zxxw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 0, 4, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zxyx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 0, 5, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zxyy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 0, 5, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zxyz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 0, 5, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zxyw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 0, 5, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zxzx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 0, 6, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zxzy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 0, 6, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zxzz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 0, 6, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zxzw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 0, 6, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zxwx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 0, 7, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zxwy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 0, 7, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zxwz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 0, 7, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zxww(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 0, 7, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zyxx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 1, 4, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zyxy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 1, 4, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zyxz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 1, 4, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zyxw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 1, 4, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zyyx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 1, 5, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zyyy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 1, 5, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zyyz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 1, 5, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zyyw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 1, 5, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zyzx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 1, 6, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zyzy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 1, 6, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zyzz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 1, 6, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zyzw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 1, 6, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zywx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 1, 7, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zywy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 1, 7, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zywz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 1, 7, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zyww(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 1, 7, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zzxx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 2, 4, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zzxy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 2, 4, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zzxz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 2, 4, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zzxw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 2, 4, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zzyx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 2, 5, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zzyy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 2, 5, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zzyz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 2, 5, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zzyw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 2, 5, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zzzx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 2, 6, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zzzy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 2, 6, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zzzz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 2, 6, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zzzw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 2, 6, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zzwx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 2, 7, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zzwy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 2, 7, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zzwz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 2, 7, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zzww(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 2, 7, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zwxx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 3, 4, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zwxy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 3, 4, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zwxz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 3, 4, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zwxw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 3, 4, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zwyx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 3, 5, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zwyy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 3, 5, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zwyz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 3, 5, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zwyw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 3, 5, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zwzx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 3, 6, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zwzy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 3, 6, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zwzz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 3, 6, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zwzw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 3, 6, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zwwx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 3, 7, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zwwy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 3, 7, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zwwz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 3, 7, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn zwww(self) -> Vec4 {
         Vec4(i32x4_shuffle::<2, 3, 7, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wxxx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 0, 4, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wxxy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 0, 4, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wxxz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 0, 4, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wxxw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 0, 4, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wxyx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 0, 5, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wxyy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 0, 5, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wxyz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 0, 5, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wxyw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 0, 5, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wxzx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 0, 6, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wxzy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 0, 6, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wxzz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 0, 6, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wxzw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 0, 6, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wxwx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 0, 7, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wxwy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 0, 7, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wxwz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 0, 7, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wxww(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 0, 7, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wyxx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 1, 4, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wyxy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 1, 4, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wyxz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 1, 4, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wyxw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 1, 4, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wyyx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 1, 5, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wyyy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 1, 5, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wyyz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 1, 5, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wyyw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 1, 5, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wyzx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 1, 6, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wyzy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 1, 6, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wyzz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 1, 6, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wyzw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 1, 6, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wywx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 1, 7, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wywy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 1, 7, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wywz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 1, 7, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wyww(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 1, 7, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wzxx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 2, 4, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wzxy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 2, 4, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wzxz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 2, 4, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wzxw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 2, 4, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wzyx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 2, 5, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wzyy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 2, 5, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wzyz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 2, 5, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wzyw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 2, 5, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wzzx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 2, 6, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wzzy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 2, 6, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wzzz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 2, 6, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wzzw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 2, 6, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wzwx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 2, 7, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wzwy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 2, 7, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wzwz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 2, 7, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wzww(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 2, 7, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wwxx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 3, 4, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wwxy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 3, 4, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wwxz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 3, 4, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wwxw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 3, 4, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wwyx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 3, 5, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wwyy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 3, 5, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wwyz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 3, 5, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wwyw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 3, 5, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wwzx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 3, 6, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wwzy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 3, 6, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wwzz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 3, 6, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wwzw(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 3, 6, 7>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wwwx(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 3, 7, 4>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wwwy(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 3, 7, 5>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wwwz(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 3, 7, 6>(self.0, self.0))
     }
 
     #[inline]
+    #[must_use]
     fn wwww(self) -> Vec4 {
         Vec4(i32x4_shuffle::<3, 3, 7, 7>(self.0, self.0))
     }
diff --git a/src/u16.rs b/src/u16.rs
new file mode 100644
index 0000000..405278b
--- /dev/null
+++ b/src/u16.rs
@@ -0,0 +1,44 @@
+mod u16vec2;
+mod u16vec3;
+mod u16vec4;
+
+pub use u16vec2::{u16vec2, U16Vec2};
+pub use u16vec3::{u16vec3, U16Vec3};
+pub use u16vec4::{u16vec4, U16Vec4};
+
+#[cfg(not(target_arch = "spirv"))]
+mod test {
+    use super::*;
+
+    mod const_test_u16vec2 {
+        const_assert_eq!(4, core::mem::size_of::<super::U16Vec2>());
+
+        #[cfg(not(feature = "cuda"))]
+        const_assert_eq!(
+            core::mem::align_of::<u16>(),
+            core::mem::align_of::<super::U16Vec2>()
+        );
+        #[cfg(feature = "cuda")]
+        const_assert_eq!(4, core::mem::align_of::<super::U16Vec2>());
+    }
+
+    mod const_test_u16vec3 {
+        const_assert_eq!(
+            core::mem::align_of::<u16>(),
+            core::mem::align_of::<super::U16Vec3>()
+        );
+        const_assert_eq!(6, core::mem::size_of::<super::U16Vec3>());
+    }
+
+    mod const_test_u16vec4 {
+        const_assert_eq!(8, core::mem::size_of::<super::U16Vec4>());
+
+        #[cfg(not(feature = "cuda"))]
+        const_assert_eq!(
+            core::mem::align_of::<u16>(),
+            core::mem::align_of::<super::U16Vec4>()
+        );
+        #[cfg(feature = "cuda")]
+        const_assert_eq!(8, core::mem::align_of::<super::U16Vec4>());
+    }
+}
diff --git a/src/u16/u16vec2.rs b/src/u16/u16vec2.rs
new file mode 100644
index 0000000..3ee390c
--- /dev/null
+++ b/src/u16/u16vec2.rs
@@ -0,0 +1,1127 @@
+// Generated from vec.rs.tera template. Edit the template, not the generated file.
+
+use crate::{BVec2, I16Vec2, I64Vec2, IVec2, U16Vec3, U64Vec2, UVec2};
+
+#[cfg(not(target_arch = "spirv"))]
+use core::fmt;
+use core::iter::{Product, Sum};
+use core::{f32, ops::*};
+
+/// Creates a 2-dimensional vector.
+#[inline(always)]
+#[must_use]
+pub const fn u16vec2(x: u16, y: u16) -> U16Vec2 {
+    U16Vec2::new(x, y)
+}
+
+/// A 2-dimensional vector.
+#[cfg_attr(not(target_arch = "spirv"), derive(Hash))]
+#[derive(Clone, Copy, PartialEq, Eq)]
+#[cfg_attr(feature = "cuda", repr(align(4)))]
+#[cfg_attr(not(target_arch = "spirv"), repr(C))]
+#[cfg_attr(target_arch = "spirv", repr(simd))]
+pub struct U16Vec2 {
+    pub x: u16,
+    pub y: u16,
+}
+
+impl U16Vec2 {
+    /// All zeroes.
+    pub const ZERO: Self = Self::splat(0);
+
+    /// All ones.
+    pub const ONE: Self = Self::splat(1);
+
+    /// All `u16::MIN`.
+    pub const MIN: Self = Self::splat(u16::MIN);
+
+    /// All `u16::MAX`.
+    pub const MAX: Self = Self::splat(u16::MAX);
+
+    /// A unit vector pointing along the positive X axis.
+    pub const X: Self = Self::new(1, 0);
+
+    /// A unit vector pointing along the positive Y axis.
+    pub const Y: Self = Self::new(0, 1);
+
+    /// The unit axes.
+    pub const AXES: [Self; 2] = [Self::X, Self::Y];
+
+    /// Creates a new vector.
+    #[inline(always)]
+    #[must_use]
+    pub const fn new(x: u16, y: u16) -> Self {
+        Self { x, y }
+    }
+
+    /// Creates a vector with all elements set to `v`.
+    #[inline]
+    #[must_use]
+    pub const fn splat(v: u16) -> Self {
+        Self { x: v, y: v }
+    }
+
+    /// Creates a vector from the elements in `if_true` and `if_false`, selecting which to use
+    /// for each element of `self`.
+    ///
+    /// A true element in the mask uses the corresponding element from `if_true`, and false
+    /// uses the element from `if_false`.
+    #[inline]
+    #[must_use]
+    pub fn select(mask: BVec2, if_true: Self, if_false: Self) -> Self {
+        Self {
+            x: if mask.test(0) { if_true.x } else { if_false.x },
+            y: if mask.test(1) { if_true.y } else { if_false.y },
+        }
+    }
+
+    /// Creates a new vector from an array.
+    #[inline]
+    #[must_use]
+    pub const fn from_array(a: [u16; 2]) -> Self {
+        Self::new(a[0], a[1])
+    }
+
+    /// `[x, y]`
+    #[inline]
+    #[must_use]
+    pub const fn to_array(&self) -> [u16; 2] {
+        [self.x, self.y]
+    }
+
+    /// Creates a vector from the first 2 values in `slice`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `slice` is less than 2 elements long.
+    #[inline]
+    #[must_use]
+    pub const fn from_slice(slice: &[u16]) -> Self {
+        Self::new(slice[0], slice[1])
+    }
+
+    /// Writes the elements of `self` to the first 2 elements in `slice`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `slice` is less than 2 elements long.
+    #[inline]
+    pub fn write_to_slice(self, slice: &mut [u16]) {
+        slice[0] = self.x;
+        slice[1] = self.y;
+    }
+
+    /// Creates a 3D vector from `self` and the given `z` value.
+    #[inline]
+    #[must_use]
+    pub const fn extend(self, z: u16) -> U16Vec3 {
+        U16Vec3::new(self.x, self.y, z)
+    }
+
+    /// Computes the dot product of `self` and `rhs`.
+    #[inline]
+    #[must_use]
+    pub fn dot(self, rhs: Self) -> u16 {
+        (self.x * rhs.x) + (self.y * rhs.y)
+    }
+
+    /// Returns a vector where every component is the dot product of `self` and `rhs`.
+    #[inline]
+    #[must_use]
+    pub fn dot_into_vec(self, rhs: Self) -> Self {
+        Self::splat(self.dot(rhs))
+    }
+
+    /// Returns a vector containing the minimum values for each element of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.min(rhs.x), self.y.min(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub fn min(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.min(rhs.x),
+            y: self.y.min(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the maximum values for each element of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.max(rhs.x), self.y.max(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub fn max(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.max(rhs.x),
+            y: self.y.max(rhs.y),
+        }
+    }
+
+    /// Component-wise clamping of values, similar to [`u16::clamp`].
+    ///
+    /// Each element in `min` must be less-or-equal to the corresponding element in `max`.
+    ///
+    /// # Panics
+    ///
+    /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
+    #[inline]
+    #[must_use]
+    pub fn clamp(self, min: Self, max: Self) -> Self {
+        glam_assert!(min.cmple(max).all(), "clamp: expected min <= max");
+        self.max(min).min(max)
+    }
+
+    /// Returns the horizontal minimum of `self`.
+    ///
+    /// In other words this computes `min(x, y, ..)`.
+    #[inline]
+    #[must_use]
+    pub fn min_element(self) -> u16 {
+        self.x.min(self.y)
+    }
+
+    /// Returns the horizontal maximum of `self`.
+    ///
+    /// In other words this computes `max(x, y, ..)`.
+    #[inline]
+    #[must_use]
+    pub fn max_element(self) -> u16 {
+        self.x.max(self.y)
+    }
+
+    /// Returns a vector mask containing the result of a `==` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words, this computes `[self.x == rhs.x, self.y == rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpeq(self, rhs: Self) -> BVec2 {
+        BVec2::new(self.x.eq(&rhs.x), self.y.eq(&rhs.y))
+    }
+
+    /// Returns a vector mask containing the result of a `!=` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x != rhs.x, self.y != rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpne(self, rhs: Self) -> BVec2 {
+        BVec2::new(self.x.ne(&rhs.x), self.y.ne(&rhs.y))
+    }
+
+    /// Returns a vector mask containing the result of a `>=` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x >= rhs.x, self.y >= rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpge(self, rhs: Self) -> BVec2 {
+        BVec2::new(self.x.ge(&rhs.x), self.y.ge(&rhs.y))
+    }
+
+    /// Returns a vector mask containing the result of a `>` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x > rhs.x, self.y > rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpgt(self, rhs: Self) -> BVec2 {
+        BVec2::new(self.x.gt(&rhs.x), self.y.gt(&rhs.y))
+    }
+
+    /// Returns a vector mask containing the result of a `<=` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x <= rhs.x, self.y <= rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmple(self, rhs: Self) -> BVec2 {
+        BVec2::new(self.x.le(&rhs.x), self.y.le(&rhs.y))
+    }
+
+    /// Returns a vector mask containing the result of a `<` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x < rhs.x, self.y < rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmplt(self, rhs: Self) -> BVec2 {
+        BVec2::new(self.x.lt(&rhs.x), self.y.lt(&rhs.y))
+    }
+
+    /// Computes the squared length of `self`.
+    #[doc(alias = "magnitude2")]
+    #[inline]
+    #[must_use]
+    pub fn length_squared(self) -> u16 {
+        self.dot(self)
+    }
+
+    /// Casts all elements of `self` to `f32`.
+    #[inline]
+    #[must_use]
+    pub fn as_vec2(&self) -> crate::Vec2 {
+        crate::Vec2::new(self.x as f32, self.y as f32)
+    }
+
+    /// Casts all elements of `self` to `f64`.
+    #[inline]
+    #[must_use]
+    pub fn as_dvec2(&self) -> crate::DVec2 {
+        crate::DVec2::new(self.x as f64, self.y as f64)
+    }
+
+    /// Casts all elements of `self` to `i16`.
+    #[inline]
+    #[must_use]
+    pub fn as_i16vec2(&self) -> crate::I16Vec2 {
+        crate::I16Vec2::new(self.x as i16, self.y as i16)
+    }
+
+    /// Casts all elements of `self` to `i32`.
+    #[inline]
+    #[must_use]
+    pub fn as_ivec2(&self) -> crate::IVec2 {
+        crate::IVec2::new(self.x as i32, self.y as i32)
+    }
+
+    /// Casts all elements of `self` to `u32`.
+    #[inline]
+    #[must_use]
+    pub fn as_uvec2(&self) -> crate::UVec2 {
+        crate::UVec2::new(self.x as u32, self.y as u32)
+    }
+
+    /// Casts all elements of `self` to `i64`.
+    #[inline]
+    #[must_use]
+    pub fn as_i64vec2(&self) -> crate::I64Vec2 {
+        crate::I64Vec2::new(self.x as i64, self.y as i64)
+    }
+
+    /// Casts all elements of `self` to `u64`.
+    #[inline]
+    #[must_use]
+    pub fn as_u64vec2(&self) -> crate::U64Vec2 {
+        crate::U64Vec2::new(self.x as u64, self.y as u64)
+    }
+
+    /// Returns a vector containing the wrapping addition of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_add(rhs.x), self.y.wrapping_add(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_add(rhs.x),
+            y: self.y.wrapping_add(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the wrapping subtraction of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_sub(rhs.x), self.y.wrapping_sub(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_sub(rhs.x),
+            y: self.y.wrapping_sub(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the wrapping multiplication of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_mul(rhs.x), self.y.wrapping_mul(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_mul(rhs.x),
+            y: self.y.wrapping_mul(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the wrapping division of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_div(rhs.x), self.y.wrapping_div(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_div(rhs.x),
+            y: self.y.wrapping_div(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the saturating addition of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_add(rhs.x), self.y.saturating_add(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_add(rhs.x),
+            y: self.y.saturating_add(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the saturating subtraction of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_sub(rhs.x), self.y.saturating_sub(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_sub(rhs.x),
+            y: self.y.saturating_sub(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the saturating multiplication of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_mul(rhs.x), self.y.saturating_mul(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_mul(rhs.x),
+            y: self.y.saturating_mul(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the saturating division of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_div(rhs.x), self.y.saturating_div(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_div(rhs.x),
+            y: self.y.saturating_div(rhs.y),
+        }
+    }
+}
+
+impl Default for U16Vec2 {
+    #[inline(always)]
+    fn default() -> Self {
+        Self::ZERO
+    }
+}
+
+impl Div<U16Vec2> for U16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.div(rhs.x),
+            y: self.y.div(rhs.y),
+        }
+    }
+}
+
+impl DivAssign<U16Vec2> for U16Vec2 {
+    #[inline]
+    fn div_assign(&mut self, rhs: Self) {
+        self.x.div_assign(rhs.x);
+        self.y.div_assign(rhs.y);
+    }
+}
+
+impl Div<u16> for U16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn div(self, rhs: u16) -> Self {
+        Self {
+            x: self.x.div(rhs),
+            y: self.y.div(rhs),
+        }
+    }
+}
+
+impl DivAssign<u16> for U16Vec2 {
+    #[inline]
+    fn div_assign(&mut self, rhs: u16) {
+        self.x.div_assign(rhs);
+        self.y.div_assign(rhs);
+    }
+}
+
+impl Div<U16Vec2> for u16 {
+    type Output = U16Vec2;
+    #[inline]
+    fn div(self, rhs: U16Vec2) -> U16Vec2 {
+        U16Vec2 {
+            x: self.div(rhs.x),
+            y: self.div(rhs.y),
+        }
+    }
+}
+
+impl Mul<U16Vec2> for U16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.mul(rhs.x),
+            y: self.y.mul(rhs.y),
+        }
+    }
+}
+
+impl MulAssign<U16Vec2> for U16Vec2 {
+    #[inline]
+    fn mul_assign(&mut self, rhs: Self) {
+        self.x.mul_assign(rhs.x);
+        self.y.mul_assign(rhs.y);
+    }
+}
+
+impl Mul<u16> for U16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn mul(self, rhs: u16) -> Self {
+        Self {
+            x: self.x.mul(rhs),
+            y: self.y.mul(rhs),
+        }
+    }
+}
+
+impl MulAssign<u16> for U16Vec2 {
+    #[inline]
+    fn mul_assign(&mut self, rhs: u16) {
+        self.x.mul_assign(rhs);
+        self.y.mul_assign(rhs);
+    }
+}
+
+impl Mul<U16Vec2> for u16 {
+    type Output = U16Vec2;
+    #[inline]
+    fn mul(self, rhs: U16Vec2) -> U16Vec2 {
+        U16Vec2 {
+            x: self.mul(rhs.x),
+            y: self.mul(rhs.y),
+        }
+    }
+}
+
+impl Add<U16Vec2> for U16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.add(rhs.x),
+            y: self.y.add(rhs.y),
+        }
+    }
+}
+
+impl AddAssign<U16Vec2> for U16Vec2 {
+    #[inline]
+    fn add_assign(&mut self, rhs: Self) {
+        self.x.add_assign(rhs.x);
+        self.y.add_assign(rhs.y);
+    }
+}
+
+impl Add<u16> for U16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn add(self, rhs: u16) -> Self {
+        Self {
+            x: self.x.add(rhs),
+            y: self.y.add(rhs),
+        }
+    }
+}
+
+impl AddAssign<u16> for U16Vec2 {
+    #[inline]
+    fn add_assign(&mut self, rhs: u16) {
+        self.x.add_assign(rhs);
+        self.y.add_assign(rhs);
+    }
+}
+
+impl Add<U16Vec2> for u16 {
+    type Output = U16Vec2;
+    #[inline]
+    fn add(self, rhs: U16Vec2) -> U16Vec2 {
+        U16Vec2 {
+            x: self.add(rhs.x),
+            y: self.add(rhs.y),
+        }
+    }
+}
+
+impl Sub<U16Vec2> for U16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.sub(rhs.x),
+            y: self.y.sub(rhs.y),
+        }
+    }
+}
+
+impl SubAssign<U16Vec2> for U16Vec2 {
+    #[inline]
+    fn sub_assign(&mut self, rhs: U16Vec2) {
+        self.x.sub_assign(rhs.x);
+        self.y.sub_assign(rhs.y);
+    }
+}
+
+impl Sub<u16> for U16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn sub(self, rhs: u16) -> Self {
+        Self {
+            x: self.x.sub(rhs),
+            y: self.y.sub(rhs),
+        }
+    }
+}
+
+impl SubAssign<u16> for U16Vec2 {
+    #[inline]
+    fn sub_assign(&mut self, rhs: u16) {
+        self.x.sub_assign(rhs);
+        self.y.sub_assign(rhs);
+    }
+}
+
+impl Sub<U16Vec2> for u16 {
+    type Output = U16Vec2;
+    #[inline]
+    fn sub(self, rhs: U16Vec2) -> U16Vec2 {
+        U16Vec2 {
+            x: self.sub(rhs.x),
+            y: self.sub(rhs.y),
+        }
+    }
+}
+
+impl Rem<U16Vec2> for U16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn rem(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.rem(rhs.x),
+            y: self.y.rem(rhs.y),
+        }
+    }
+}
+
+impl RemAssign<U16Vec2> for U16Vec2 {
+    #[inline]
+    fn rem_assign(&mut self, rhs: Self) {
+        self.x.rem_assign(rhs.x);
+        self.y.rem_assign(rhs.y);
+    }
+}
+
+impl Rem<u16> for U16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn rem(self, rhs: u16) -> Self {
+        Self {
+            x: self.x.rem(rhs),
+            y: self.y.rem(rhs),
+        }
+    }
+}
+
+impl RemAssign<u16> for U16Vec2 {
+    #[inline]
+    fn rem_assign(&mut self, rhs: u16) {
+        self.x.rem_assign(rhs);
+        self.y.rem_assign(rhs);
+    }
+}
+
+impl Rem<U16Vec2> for u16 {
+    type Output = U16Vec2;
+    #[inline]
+    fn rem(self, rhs: U16Vec2) -> U16Vec2 {
+        U16Vec2 {
+            x: self.rem(rhs.x),
+            y: self.rem(rhs.y),
+        }
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl AsRef<[u16; 2]> for U16Vec2 {
+    #[inline]
+    fn as_ref(&self) -> &[u16; 2] {
+        unsafe { &*(self as *const U16Vec2 as *const [u16; 2]) }
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl AsMut<[u16; 2]> for U16Vec2 {
+    #[inline]
+    fn as_mut(&mut self) -> &mut [u16; 2] {
+        unsafe { &mut *(self as *mut U16Vec2 as *mut [u16; 2]) }
+    }
+}
+
+impl Sum for U16Vec2 {
+    #[inline]
+    fn sum<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = Self>,
+    {
+        iter.fold(Self::ZERO, Self::add)
+    }
+}
+
+impl<'a> Sum<&'a Self> for U16Vec2 {
+    #[inline]
+    fn sum<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = &'a Self>,
+    {
+        iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
+    }
+}
+
+impl Product for U16Vec2 {
+    #[inline]
+    fn product<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = Self>,
+    {
+        iter.fold(Self::ONE, Self::mul)
+    }
+}
+
+impl<'a> Product<&'a Self> for U16Vec2 {
+    #[inline]
+    fn product<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = &'a Self>,
+    {
+        iter.fold(Self::ONE, |a, &b| Self::mul(a, b))
+    }
+}
+
+impl Not for U16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn not(self) -> Self::Output {
+        Self {
+            x: self.x.not(),
+            y: self.y.not(),
+        }
+    }
+}
+
+impl BitAnd for U16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn bitand(self, rhs: Self) -> Self::Output {
+        Self {
+            x: self.x.bitand(rhs.x),
+            y: self.y.bitand(rhs.y),
+        }
+    }
+}
+
+impl BitOr for U16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn bitor(self, rhs: Self) -> Self::Output {
+        Self {
+            x: self.x.bitor(rhs.x),
+            y: self.y.bitor(rhs.y),
+        }
+    }
+}
+
+impl BitXor for U16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn bitxor(self, rhs: Self) -> Self::Output {
+        Self {
+            x: self.x.bitxor(rhs.x),
+            y: self.y.bitxor(rhs.y),
+        }
+    }
+}
+
+impl BitAnd<u16> for U16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn bitand(self, rhs: u16) -> Self::Output {
+        Self {
+            x: self.x.bitand(rhs),
+            y: self.y.bitand(rhs),
+        }
+    }
+}
+
+impl BitOr<u16> for U16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn bitor(self, rhs: u16) -> Self::Output {
+        Self {
+            x: self.x.bitor(rhs),
+            y: self.y.bitor(rhs),
+        }
+    }
+}
+
+impl BitXor<u16> for U16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn bitxor(self, rhs: u16) -> Self::Output {
+        Self {
+            x: self.x.bitxor(rhs),
+            y: self.y.bitxor(rhs),
+        }
+    }
+}
+
+impl Shl<i8> for U16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i8) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i8> for U16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i8) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+        }
+    }
+}
+
+impl Shl<i16> for U16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i16) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i16> for U16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i16) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+        }
+    }
+}
+
+impl Shl<i32> for U16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i32) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i32> for U16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i32) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+        }
+    }
+}
+
+impl Shl<i64> for U16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i64> for U16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u8> for U16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u8) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u8> for U16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u8) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u16> for U16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u16) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u16> for U16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u16) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u32> for U16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u32) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u32> for U16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u32) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u64> for U16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u64> for U16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+        }
+    }
+}
+
+impl Shl<crate::IVec2> for U16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: crate::IVec2) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs.x),
+            y: self.y.shl(rhs.y),
+        }
+    }
+}
+
+impl Shr<crate::IVec2> for U16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: crate::IVec2) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs.x),
+            y: self.y.shr(rhs.y),
+        }
+    }
+}
+
+impl Shl<crate::UVec2> for U16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: crate::UVec2) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs.x),
+            y: self.y.shl(rhs.y),
+        }
+    }
+}
+
+impl Shr<crate::UVec2> for U16Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: crate::UVec2) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs.x),
+            y: self.y.shr(rhs.y),
+        }
+    }
+}
+
+impl Index<usize> for U16Vec2 {
+    type Output = u16;
+    #[inline]
+    fn index(&self, index: usize) -> &Self::Output {
+        match index {
+            0 => &self.x,
+            1 => &self.y,
+            _ => panic!("index out of bounds"),
+        }
+    }
+}
+
+impl IndexMut<usize> for U16Vec2 {
+    #[inline]
+    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
+        match index {
+            0 => &mut self.x,
+            1 => &mut self.y,
+            _ => panic!("index out of bounds"),
+        }
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl fmt::Display for U16Vec2 {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "[{}, {}]", self.x, self.y)
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl fmt::Debug for U16Vec2 {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt.debug_tuple(stringify!(U16Vec2))
+            .field(&self.x)
+            .field(&self.y)
+            .finish()
+    }
+}
+
+impl From<[u16; 2]> for U16Vec2 {
+    #[inline]
+    fn from(a: [u16; 2]) -> Self {
+        Self::new(a[0], a[1])
+    }
+}
+
+impl From<U16Vec2> for [u16; 2] {
+    #[inline]
+    fn from(v: U16Vec2) -> Self {
+        [v.x, v.y]
+    }
+}
+
+impl From<(u16, u16)> for U16Vec2 {
+    #[inline]
+    fn from(t: (u16, u16)) -> Self {
+        Self::new(t.0, t.1)
+    }
+}
+
+impl From<U16Vec2> for (u16, u16) {
+    #[inline]
+    fn from(v: U16Vec2) -> Self {
+        (v.x, v.y)
+    }
+}
+
+impl TryFrom<I16Vec2> for U16Vec2 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: I16Vec2) -> Result<Self, Self::Error> {
+        Ok(Self::new(u16::try_from(v.x)?, u16::try_from(v.y)?))
+    }
+}
+
+impl TryFrom<IVec2> for U16Vec2 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: IVec2) -> Result<Self, Self::Error> {
+        Ok(Self::new(u16::try_from(v.x)?, u16::try_from(v.y)?))
+    }
+}
+
+impl TryFrom<UVec2> for U16Vec2 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: UVec2) -> Result<Self, Self::Error> {
+        Ok(Self::new(u16::try_from(v.x)?, u16::try_from(v.y)?))
+    }
+}
+
+impl TryFrom<I64Vec2> for U16Vec2 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: I64Vec2) -> Result<Self, Self::Error> {
+        Ok(Self::new(u16::try_from(v.x)?, u16::try_from(v.y)?))
+    }
+}
+
+impl TryFrom<U64Vec2> for U16Vec2 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: U64Vec2) -> Result<Self, Self::Error> {
+        Ok(Self::new(u16::try_from(v.x)?, u16::try_from(v.y)?))
+    }
+}
diff --git a/src/u16/u16vec3.rs b/src/u16/u16vec3.rs
new file mode 100644
index 0000000..e2859a0
--- /dev/null
+++ b/src/u16/u16vec3.rs
@@ -0,0 +1,1264 @@
+// Generated from vec.rs.tera template. Edit the template, not the generated file.
+
+use crate::{BVec3, I16Vec3, I64Vec3, IVec3, U16Vec2, U16Vec4, U64Vec3, UVec3};
+
+#[cfg(not(target_arch = "spirv"))]
+use core::fmt;
+use core::iter::{Product, Sum};
+use core::{f32, ops::*};
+
+/// Creates a 3-dimensional vector.
+#[inline(always)]
+#[must_use]
+pub const fn u16vec3(x: u16, y: u16, z: u16) -> U16Vec3 {
+    U16Vec3::new(x, y, z)
+}
+
+/// A 3-dimensional vector.
+#[cfg_attr(not(target_arch = "spirv"), derive(Hash))]
+#[derive(Clone, Copy, PartialEq, Eq)]
+#[cfg_attr(not(target_arch = "spirv"), repr(C))]
+#[cfg_attr(target_arch = "spirv", repr(simd))]
+pub struct U16Vec3 {
+    pub x: u16,
+    pub y: u16,
+    pub z: u16,
+}
+
+impl U16Vec3 {
+    /// All zeroes.
+    pub const ZERO: Self = Self::splat(0);
+
+    /// All ones.
+    pub const ONE: Self = Self::splat(1);
+
+    /// All `u16::MIN`.
+    pub const MIN: Self = Self::splat(u16::MIN);
+
+    /// All `u16::MAX`.
+    pub const MAX: Self = Self::splat(u16::MAX);
+
+    /// A unit vector pointing along the positive X axis.
+    pub const X: Self = Self::new(1, 0, 0);
+
+    /// A unit vector pointing along the positive Y axis.
+    pub const Y: Self = Self::new(0, 1, 0);
+
+    /// A unit vector pointing along the positive Z axis.
+    pub const Z: Self = Self::new(0, 0, 1);
+
+    /// The unit axes.
+    pub const AXES: [Self; 3] = [Self::X, Self::Y, Self::Z];
+
+    /// Creates a new vector.
+    #[inline(always)]
+    #[must_use]
+    pub const fn new(x: u16, y: u16, z: u16) -> Self {
+        Self { x, y, z }
+    }
+
+    /// Creates a vector with all elements set to `v`.
+    #[inline]
+    #[must_use]
+    pub const fn splat(v: u16) -> Self {
+        Self { x: v, y: v, z: v }
+    }
+
+    /// Creates a vector from the elements in `if_true` and `if_false`, selecting which to use
+    /// for each element of `self`.
+    ///
+    /// A true element in the mask uses the corresponding element from `if_true`, and false
+    /// uses the element from `if_false`.
+    #[inline]
+    #[must_use]
+    pub fn select(mask: BVec3, if_true: Self, if_false: Self) -> Self {
+        Self {
+            x: if mask.test(0) { if_true.x } else { if_false.x },
+            y: if mask.test(1) { if_true.y } else { if_false.y },
+            z: if mask.test(2) { if_true.z } else { if_false.z },
+        }
+    }
+
+    /// Creates a new vector from an array.
+    #[inline]
+    #[must_use]
+    pub const fn from_array(a: [u16; 3]) -> Self {
+        Self::new(a[0], a[1], a[2])
+    }
+
+    /// `[x, y, z]`
+    #[inline]
+    #[must_use]
+    pub const fn to_array(&self) -> [u16; 3] {
+        [self.x, self.y, self.z]
+    }
+
+    /// Creates a vector from the first 3 values in `slice`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `slice` is less than 3 elements long.
+    #[inline]
+    #[must_use]
+    pub const fn from_slice(slice: &[u16]) -> Self {
+        Self::new(slice[0], slice[1], slice[2])
+    }
+
+    /// Writes the elements of `self` to the first 3 elements in `slice`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `slice` is less than 3 elements long.
+    #[inline]
+    pub fn write_to_slice(self, slice: &mut [u16]) {
+        slice[0] = self.x;
+        slice[1] = self.y;
+        slice[2] = self.z;
+    }
+
+    /// Internal method for creating a 3D vector from a 4D vector, discarding `w`.
+    #[allow(dead_code)]
+    #[inline]
+    #[must_use]
+    pub(crate) fn from_vec4(v: U16Vec4) -> Self {
+        Self {
+            x: v.x,
+            y: v.y,
+            z: v.z,
+        }
+    }
+
+    /// Creates a 4D vector from `self` and the given `w` value.
+    #[inline]
+    #[must_use]
+    pub fn extend(self, w: u16) -> U16Vec4 {
+        U16Vec4::new(self.x, self.y, self.z, w)
+    }
+
+    /// Creates a 2D vector from the `x` and `y` elements of `self`, discarding `z`.
+    ///
+    /// Truncation may also be performed by using [`self.xy()`][crate::swizzles::Vec3Swizzles::xy()].
+    #[inline]
+    #[must_use]
+    pub fn truncate(self) -> U16Vec2 {
+        use crate::swizzles::Vec3Swizzles;
+        self.xy()
+    }
+
+    /// Computes the dot product of `self` and `rhs`.
+    #[inline]
+    #[must_use]
+    pub fn dot(self, rhs: Self) -> u16 {
+        (self.x * rhs.x) + (self.y * rhs.y) + (self.z * rhs.z)
+    }
+
+    /// Returns a vector where every component is the dot product of `self` and `rhs`.
+    #[inline]
+    #[must_use]
+    pub fn dot_into_vec(self, rhs: Self) -> Self {
+        Self::splat(self.dot(rhs))
+    }
+
+    /// Computes the cross product of `self` and `rhs`.
+    #[inline]
+    #[must_use]
+    pub fn cross(self, rhs: Self) -> Self {
+        Self {
+            x: self.y * rhs.z - rhs.y * self.z,
+            y: self.z * rhs.x - rhs.z * self.x,
+            z: self.x * rhs.y - rhs.x * self.y,
+        }
+    }
+
+    /// Returns a vector containing the minimum values for each element of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.min(rhs.x), self.y.min(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub fn min(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.min(rhs.x),
+            y: self.y.min(rhs.y),
+            z: self.z.min(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the maximum values for each element of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.max(rhs.x), self.y.max(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub fn max(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.max(rhs.x),
+            y: self.y.max(rhs.y),
+            z: self.z.max(rhs.z),
+        }
+    }
+
+    /// Component-wise clamping of values, similar to [`u16::clamp`].
+    ///
+    /// Each element in `min` must be less-or-equal to the corresponding element in `max`.
+    ///
+    /// # Panics
+    ///
+    /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
+    #[inline]
+    #[must_use]
+    pub fn clamp(self, min: Self, max: Self) -> Self {
+        glam_assert!(min.cmple(max).all(), "clamp: expected min <= max");
+        self.max(min).min(max)
+    }
+
+    /// Returns the horizontal minimum of `self`.
+    ///
+    /// In other words this computes `min(x, y, ..)`.
+    #[inline]
+    #[must_use]
+    pub fn min_element(self) -> u16 {
+        self.x.min(self.y.min(self.z))
+    }
+
+    /// Returns the horizontal maximum of `self`.
+    ///
+    /// In other words this computes `max(x, y, ..)`.
+    #[inline]
+    #[must_use]
+    pub fn max_element(self) -> u16 {
+        self.x.max(self.y.max(self.z))
+    }
+
+    /// Returns a vector mask containing the result of a `==` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words, this computes `[self.x == rhs.x, self.y == rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpeq(self, rhs: Self) -> BVec3 {
+        BVec3::new(self.x.eq(&rhs.x), self.y.eq(&rhs.y), self.z.eq(&rhs.z))
+    }
+
+    /// Returns a vector mask containing the result of a `!=` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x != rhs.x, self.y != rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpne(self, rhs: Self) -> BVec3 {
+        BVec3::new(self.x.ne(&rhs.x), self.y.ne(&rhs.y), self.z.ne(&rhs.z))
+    }
+
+    /// Returns a vector mask containing the result of a `>=` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x >= rhs.x, self.y >= rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpge(self, rhs: Self) -> BVec3 {
+        BVec3::new(self.x.ge(&rhs.x), self.y.ge(&rhs.y), self.z.ge(&rhs.z))
+    }
+
+    /// Returns a vector mask containing the result of a `>` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x > rhs.x, self.y > rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpgt(self, rhs: Self) -> BVec3 {
+        BVec3::new(self.x.gt(&rhs.x), self.y.gt(&rhs.y), self.z.gt(&rhs.z))
+    }
+
+    /// Returns a vector mask containing the result of a `<=` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x <= rhs.x, self.y <= rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmple(self, rhs: Self) -> BVec3 {
+        BVec3::new(self.x.le(&rhs.x), self.y.le(&rhs.y), self.z.le(&rhs.z))
+    }
+
+    /// Returns a vector mask containing the result of a `<` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x < rhs.x, self.y < rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmplt(self, rhs: Self) -> BVec3 {
+        BVec3::new(self.x.lt(&rhs.x), self.y.lt(&rhs.y), self.z.lt(&rhs.z))
+    }
+
+    /// Computes the squared length of `self`.
+    #[doc(alias = "magnitude2")]
+    #[inline]
+    #[must_use]
+    pub fn length_squared(self) -> u16 {
+        self.dot(self)
+    }
+
+    /// Casts all elements of `self` to `f32`.
+    #[inline]
+    #[must_use]
+    pub fn as_vec3(&self) -> crate::Vec3 {
+        crate::Vec3::new(self.x as f32, self.y as f32, self.z as f32)
+    }
+
+    /// Casts all elements of `self` to `f32`.
+    #[inline]
+    #[must_use]
+    pub fn as_vec3a(&self) -> crate::Vec3A {
+        crate::Vec3A::new(self.x as f32, self.y as f32, self.z as f32)
+    }
+
+    /// Casts all elements of `self` to `f64`.
+    #[inline]
+    #[must_use]
+    pub fn as_dvec3(&self) -> crate::DVec3 {
+        crate::DVec3::new(self.x as f64, self.y as f64, self.z as f64)
+    }
+
+    /// Casts all elements of `self` to `i16`.
+    #[inline]
+    #[must_use]
+    pub fn as_i16vec3(&self) -> crate::I16Vec3 {
+        crate::I16Vec3::new(self.x as i16, self.y as i16, self.z as i16)
+    }
+
+    /// Casts all elements of `self` to `i32`.
+    #[inline]
+    #[must_use]
+    pub fn as_ivec3(&self) -> crate::IVec3 {
+        crate::IVec3::new(self.x as i32, self.y as i32, self.z as i32)
+    }
+
+    /// Casts all elements of `self` to `u32`.
+    #[inline]
+    #[must_use]
+    pub fn as_uvec3(&self) -> crate::UVec3 {
+        crate::UVec3::new(self.x as u32, self.y as u32, self.z as u32)
+    }
+
+    /// Casts all elements of `self` to `i64`.
+    #[inline]
+    #[must_use]
+    pub fn as_i64vec3(&self) -> crate::I64Vec3 {
+        crate::I64Vec3::new(self.x as i64, self.y as i64, self.z as i64)
+    }
+
+    /// Casts all elements of `self` to `u64`.
+    #[inline]
+    #[must_use]
+    pub fn as_u64vec3(&self) -> crate::U64Vec3 {
+        crate::U64Vec3::new(self.x as u64, self.y as u64, self.z as u64)
+    }
+
+    /// Returns a vector containing the wrapping addition of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_add(rhs.x), self.y.wrapping_add(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_add(rhs.x),
+            y: self.y.wrapping_add(rhs.y),
+            z: self.z.wrapping_add(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the wrapping subtraction of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_sub(rhs.x), self.y.wrapping_sub(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_sub(rhs.x),
+            y: self.y.wrapping_sub(rhs.y),
+            z: self.z.wrapping_sub(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the wrapping multiplication of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_mul(rhs.x), self.y.wrapping_mul(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_mul(rhs.x),
+            y: self.y.wrapping_mul(rhs.y),
+            z: self.z.wrapping_mul(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the wrapping division of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_div(rhs.x), self.y.wrapping_div(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_div(rhs.x),
+            y: self.y.wrapping_div(rhs.y),
+            z: self.z.wrapping_div(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the saturating addition of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_add(rhs.x), self.y.saturating_add(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_add(rhs.x),
+            y: self.y.saturating_add(rhs.y),
+            z: self.z.saturating_add(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the saturating subtraction of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_sub(rhs.x), self.y.saturating_sub(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_sub(rhs.x),
+            y: self.y.saturating_sub(rhs.y),
+            z: self.z.saturating_sub(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the saturating multiplication of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_mul(rhs.x), self.y.saturating_mul(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_mul(rhs.x),
+            y: self.y.saturating_mul(rhs.y),
+            z: self.z.saturating_mul(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the saturating division of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_div(rhs.x), self.y.saturating_div(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_div(rhs.x),
+            y: self.y.saturating_div(rhs.y),
+            z: self.z.saturating_div(rhs.z),
+        }
+    }
+}
+
+impl Default for U16Vec3 {
+    #[inline(always)]
+    fn default() -> Self {
+        Self::ZERO
+    }
+}
+
+impl Div<U16Vec3> for U16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.div(rhs.x),
+            y: self.y.div(rhs.y),
+            z: self.z.div(rhs.z),
+        }
+    }
+}
+
+impl DivAssign<U16Vec3> for U16Vec3 {
+    #[inline]
+    fn div_assign(&mut self, rhs: Self) {
+        self.x.div_assign(rhs.x);
+        self.y.div_assign(rhs.y);
+        self.z.div_assign(rhs.z);
+    }
+}
+
+impl Div<u16> for U16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn div(self, rhs: u16) -> Self {
+        Self {
+            x: self.x.div(rhs),
+            y: self.y.div(rhs),
+            z: self.z.div(rhs),
+        }
+    }
+}
+
+impl DivAssign<u16> for U16Vec3 {
+    #[inline]
+    fn div_assign(&mut self, rhs: u16) {
+        self.x.div_assign(rhs);
+        self.y.div_assign(rhs);
+        self.z.div_assign(rhs);
+    }
+}
+
+impl Div<U16Vec3> for u16 {
+    type Output = U16Vec3;
+    #[inline]
+    fn div(self, rhs: U16Vec3) -> U16Vec3 {
+        U16Vec3 {
+            x: self.div(rhs.x),
+            y: self.div(rhs.y),
+            z: self.div(rhs.z),
+        }
+    }
+}
+
+impl Mul<U16Vec3> for U16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.mul(rhs.x),
+            y: self.y.mul(rhs.y),
+            z: self.z.mul(rhs.z),
+        }
+    }
+}
+
+impl MulAssign<U16Vec3> for U16Vec3 {
+    #[inline]
+    fn mul_assign(&mut self, rhs: Self) {
+        self.x.mul_assign(rhs.x);
+        self.y.mul_assign(rhs.y);
+        self.z.mul_assign(rhs.z);
+    }
+}
+
+impl Mul<u16> for U16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn mul(self, rhs: u16) -> Self {
+        Self {
+            x: self.x.mul(rhs),
+            y: self.y.mul(rhs),
+            z: self.z.mul(rhs),
+        }
+    }
+}
+
+impl MulAssign<u16> for U16Vec3 {
+    #[inline]
+    fn mul_assign(&mut self, rhs: u16) {
+        self.x.mul_assign(rhs);
+        self.y.mul_assign(rhs);
+        self.z.mul_assign(rhs);
+    }
+}
+
+impl Mul<U16Vec3> for u16 {
+    type Output = U16Vec3;
+    #[inline]
+    fn mul(self, rhs: U16Vec3) -> U16Vec3 {
+        U16Vec3 {
+            x: self.mul(rhs.x),
+            y: self.mul(rhs.y),
+            z: self.mul(rhs.z),
+        }
+    }
+}
+
+impl Add<U16Vec3> for U16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.add(rhs.x),
+            y: self.y.add(rhs.y),
+            z: self.z.add(rhs.z),
+        }
+    }
+}
+
+impl AddAssign<U16Vec3> for U16Vec3 {
+    #[inline]
+    fn add_assign(&mut self, rhs: Self) {
+        self.x.add_assign(rhs.x);
+        self.y.add_assign(rhs.y);
+        self.z.add_assign(rhs.z);
+    }
+}
+
+impl Add<u16> for U16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn add(self, rhs: u16) -> Self {
+        Self {
+            x: self.x.add(rhs),
+            y: self.y.add(rhs),
+            z: self.z.add(rhs),
+        }
+    }
+}
+
+impl AddAssign<u16> for U16Vec3 {
+    #[inline]
+    fn add_assign(&mut self, rhs: u16) {
+        self.x.add_assign(rhs);
+        self.y.add_assign(rhs);
+        self.z.add_assign(rhs);
+    }
+}
+
+impl Add<U16Vec3> for u16 {
+    type Output = U16Vec3;
+    #[inline]
+    fn add(self, rhs: U16Vec3) -> U16Vec3 {
+        U16Vec3 {
+            x: self.add(rhs.x),
+            y: self.add(rhs.y),
+            z: self.add(rhs.z),
+        }
+    }
+}
+
+impl Sub<U16Vec3> for U16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.sub(rhs.x),
+            y: self.y.sub(rhs.y),
+            z: self.z.sub(rhs.z),
+        }
+    }
+}
+
+impl SubAssign<U16Vec3> for U16Vec3 {
+    #[inline]
+    fn sub_assign(&mut self, rhs: U16Vec3) {
+        self.x.sub_assign(rhs.x);
+        self.y.sub_assign(rhs.y);
+        self.z.sub_assign(rhs.z);
+    }
+}
+
+impl Sub<u16> for U16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn sub(self, rhs: u16) -> Self {
+        Self {
+            x: self.x.sub(rhs),
+            y: self.y.sub(rhs),
+            z: self.z.sub(rhs),
+        }
+    }
+}
+
+impl SubAssign<u16> for U16Vec3 {
+    #[inline]
+    fn sub_assign(&mut self, rhs: u16) {
+        self.x.sub_assign(rhs);
+        self.y.sub_assign(rhs);
+        self.z.sub_assign(rhs);
+    }
+}
+
+impl Sub<U16Vec3> for u16 {
+    type Output = U16Vec3;
+    #[inline]
+    fn sub(self, rhs: U16Vec3) -> U16Vec3 {
+        U16Vec3 {
+            x: self.sub(rhs.x),
+            y: self.sub(rhs.y),
+            z: self.sub(rhs.z),
+        }
+    }
+}
+
+impl Rem<U16Vec3> for U16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn rem(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.rem(rhs.x),
+            y: self.y.rem(rhs.y),
+            z: self.z.rem(rhs.z),
+        }
+    }
+}
+
+impl RemAssign<U16Vec3> for U16Vec3 {
+    #[inline]
+    fn rem_assign(&mut self, rhs: Self) {
+        self.x.rem_assign(rhs.x);
+        self.y.rem_assign(rhs.y);
+        self.z.rem_assign(rhs.z);
+    }
+}
+
+impl Rem<u16> for U16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn rem(self, rhs: u16) -> Self {
+        Self {
+            x: self.x.rem(rhs),
+            y: self.y.rem(rhs),
+            z: self.z.rem(rhs),
+        }
+    }
+}
+
+impl RemAssign<u16> for U16Vec3 {
+    #[inline]
+    fn rem_assign(&mut self, rhs: u16) {
+        self.x.rem_assign(rhs);
+        self.y.rem_assign(rhs);
+        self.z.rem_assign(rhs);
+    }
+}
+
+impl Rem<U16Vec3> for u16 {
+    type Output = U16Vec3;
+    #[inline]
+    fn rem(self, rhs: U16Vec3) -> U16Vec3 {
+        U16Vec3 {
+            x: self.rem(rhs.x),
+            y: self.rem(rhs.y),
+            z: self.rem(rhs.z),
+        }
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl AsRef<[u16; 3]> for U16Vec3 {
+    #[inline]
+    fn as_ref(&self) -> &[u16; 3] {
+        unsafe { &*(self as *const U16Vec3 as *const [u16; 3]) }
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl AsMut<[u16; 3]> for U16Vec3 {
+    #[inline]
+    fn as_mut(&mut self) -> &mut [u16; 3] {
+        unsafe { &mut *(self as *mut U16Vec3 as *mut [u16; 3]) }
+    }
+}
+
+impl Sum for U16Vec3 {
+    #[inline]
+    fn sum<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = Self>,
+    {
+        iter.fold(Self::ZERO, Self::add)
+    }
+}
+
+impl<'a> Sum<&'a Self> for U16Vec3 {
+    #[inline]
+    fn sum<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = &'a Self>,
+    {
+        iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
+    }
+}
+
+impl Product for U16Vec3 {
+    #[inline]
+    fn product<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = Self>,
+    {
+        iter.fold(Self::ONE, Self::mul)
+    }
+}
+
+impl<'a> Product<&'a Self> for U16Vec3 {
+    #[inline]
+    fn product<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = &'a Self>,
+    {
+        iter.fold(Self::ONE, |a, &b| Self::mul(a, b))
+    }
+}
+
+impl Not for U16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn not(self) -> Self::Output {
+        Self {
+            x: self.x.not(),
+            y: self.y.not(),
+            z: self.z.not(),
+        }
+    }
+}
+
+impl BitAnd for U16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn bitand(self, rhs: Self) -> Self::Output {
+        Self {
+            x: self.x.bitand(rhs.x),
+            y: self.y.bitand(rhs.y),
+            z: self.z.bitand(rhs.z),
+        }
+    }
+}
+
+impl BitOr for U16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn bitor(self, rhs: Self) -> Self::Output {
+        Self {
+            x: self.x.bitor(rhs.x),
+            y: self.y.bitor(rhs.y),
+            z: self.z.bitor(rhs.z),
+        }
+    }
+}
+
+impl BitXor for U16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn bitxor(self, rhs: Self) -> Self::Output {
+        Self {
+            x: self.x.bitxor(rhs.x),
+            y: self.y.bitxor(rhs.y),
+            z: self.z.bitxor(rhs.z),
+        }
+    }
+}
+
+impl BitAnd<u16> for U16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn bitand(self, rhs: u16) -> Self::Output {
+        Self {
+            x: self.x.bitand(rhs),
+            y: self.y.bitand(rhs),
+            z: self.z.bitand(rhs),
+        }
+    }
+}
+
+impl BitOr<u16> for U16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn bitor(self, rhs: u16) -> Self::Output {
+        Self {
+            x: self.x.bitor(rhs),
+            y: self.y.bitor(rhs),
+            z: self.z.bitor(rhs),
+        }
+    }
+}
+
+impl BitXor<u16> for U16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn bitxor(self, rhs: u16) -> Self::Output {
+        Self {
+            x: self.x.bitxor(rhs),
+            y: self.y.bitxor(rhs),
+            z: self.z.bitxor(rhs),
+        }
+    }
+}
+
+impl Shl<i8> for U16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i8) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i8> for U16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i8) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+        }
+    }
+}
+
+impl Shl<i16> for U16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i16) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i16> for U16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i16) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+        }
+    }
+}
+
+impl Shl<i32> for U16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i32) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i32> for U16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i32) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+        }
+    }
+}
+
+impl Shl<i64> for U16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i64> for U16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u8> for U16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u8) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u8> for U16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u8) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u16> for U16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u16) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u16> for U16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u16) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u32> for U16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u32) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u32> for U16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u32) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u64> for U16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u64> for U16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+        }
+    }
+}
+
+impl Shl<crate::IVec3> for U16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: crate::IVec3) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs.x),
+            y: self.y.shl(rhs.y),
+            z: self.z.shl(rhs.z),
+        }
+    }
+}
+
+impl Shr<crate::IVec3> for U16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: crate::IVec3) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs.x),
+            y: self.y.shr(rhs.y),
+            z: self.z.shr(rhs.z),
+        }
+    }
+}
+
+impl Shl<crate::UVec3> for U16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: crate::UVec3) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs.x),
+            y: self.y.shl(rhs.y),
+            z: self.z.shl(rhs.z),
+        }
+    }
+}
+
+impl Shr<crate::UVec3> for U16Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: crate::UVec3) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs.x),
+            y: self.y.shr(rhs.y),
+            z: self.z.shr(rhs.z),
+        }
+    }
+}
+
+impl Index<usize> for U16Vec3 {
+    type Output = u16;
+    #[inline]
+    fn index(&self, index: usize) -> &Self::Output {
+        match index {
+            0 => &self.x,
+            1 => &self.y,
+            2 => &self.z,
+            _ => panic!("index out of bounds"),
+        }
+    }
+}
+
+impl IndexMut<usize> for U16Vec3 {
+    #[inline]
+    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
+        match index {
+            0 => &mut self.x,
+            1 => &mut self.y,
+            2 => &mut self.z,
+            _ => panic!("index out of bounds"),
+        }
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl fmt::Display for U16Vec3 {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "[{}, {}, {}]", self.x, self.y, self.z)
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl fmt::Debug for U16Vec3 {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt.debug_tuple(stringify!(U16Vec3))
+            .field(&self.x)
+            .field(&self.y)
+            .field(&self.z)
+            .finish()
+    }
+}
+
+impl From<[u16; 3]> for U16Vec3 {
+    #[inline]
+    fn from(a: [u16; 3]) -> Self {
+        Self::new(a[0], a[1], a[2])
+    }
+}
+
+impl From<U16Vec3> for [u16; 3] {
+    #[inline]
+    fn from(v: U16Vec3) -> Self {
+        [v.x, v.y, v.z]
+    }
+}
+
+impl From<(u16, u16, u16)> for U16Vec3 {
+    #[inline]
+    fn from(t: (u16, u16, u16)) -> Self {
+        Self::new(t.0, t.1, t.2)
+    }
+}
+
+impl From<U16Vec3> for (u16, u16, u16) {
+    #[inline]
+    fn from(v: U16Vec3) -> Self {
+        (v.x, v.y, v.z)
+    }
+}
+
+impl From<(U16Vec2, u16)> for U16Vec3 {
+    #[inline]
+    fn from((v, z): (U16Vec2, u16)) -> Self {
+        Self::new(v.x, v.y, z)
+    }
+}
+
+impl TryFrom<I16Vec3> for U16Vec3 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: I16Vec3) -> Result<Self, Self::Error> {
+        Ok(Self::new(
+            u16::try_from(v.x)?,
+            u16::try_from(v.y)?,
+            u16::try_from(v.z)?,
+        ))
+    }
+}
+
+impl TryFrom<IVec3> for U16Vec3 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: IVec3) -> Result<Self, Self::Error> {
+        Ok(Self::new(
+            u16::try_from(v.x)?,
+            u16::try_from(v.y)?,
+            u16::try_from(v.z)?,
+        ))
+    }
+}
+
+impl TryFrom<UVec3> for U16Vec3 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: UVec3) -> Result<Self, Self::Error> {
+        Ok(Self::new(
+            u16::try_from(v.x)?,
+            u16::try_from(v.y)?,
+            u16::try_from(v.z)?,
+        ))
+    }
+}
+
+impl TryFrom<I64Vec3> for U16Vec3 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: I64Vec3) -> Result<Self, Self::Error> {
+        Ok(Self::new(
+            u16::try_from(v.x)?,
+            u16::try_from(v.y)?,
+            u16::try_from(v.z)?,
+        ))
+    }
+}
+
+impl TryFrom<U64Vec3> for U16Vec3 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: U64Vec3) -> Result<Self, Self::Error> {
+        Ok(Self::new(
+            u16::try_from(v.x)?,
+            u16::try_from(v.y)?,
+            u16::try_from(v.z)?,
+        ))
+    }
+}
diff --git a/src/u16/u16vec4.rs b/src/u16/u16vec4.rs
new file mode 100644
index 0000000..e6b68e5
--- /dev/null
+++ b/src/u16/u16vec4.rs
@@ -0,0 +1,1363 @@
+// Generated from vec.rs.tera template. Edit the template, not the generated file.
+
+use crate::{BVec4, I16Vec4, I64Vec4, IVec4, U16Vec2, U16Vec3, U64Vec4, UVec4};
+
+#[cfg(not(target_arch = "spirv"))]
+use core::fmt;
+use core::iter::{Product, Sum};
+use core::{f32, ops::*};
+
+/// Creates a 4-dimensional vector.
+#[inline(always)]
+#[must_use]
+pub const fn u16vec4(x: u16, y: u16, z: u16, w: u16) -> U16Vec4 {
+    U16Vec4::new(x, y, z, w)
+}
+
+/// A 4-dimensional vector.
+#[cfg_attr(not(target_arch = "spirv"), derive(Hash))]
+#[derive(Clone, Copy, PartialEq, Eq)]
+#[cfg_attr(feature = "cuda", repr(align(8)))]
+#[cfg_attr(not(target_arch = "spirv"), repr(C))]
+#[cfg_attr(target_arch = "spirv", repr(simd))]
+pub struct U16Vec4 {
+    pub x: u16,
+    pub y: u16,
+    pub z: u16,
+    pub w: u16,
+}
+
+impl U16Vec4 {
+    /// All zeroes.
+    pub const ZERO: Self = Self::splat(0);
+
+    /// All ones.
+    pub const ONE: Self = Self::splat(1);
+
+    /// All `u16::MIN`.
+    pub const MIN: Self = Self::splat(u16::MIN);
+
+    /// All `u16::MAX`.
+    pub const MAX: Self = Self::splat(u16::MAX);
+
+    /// A unit vector pointing along the positive X axis.
+    pub const X: Self = Self::new(1, 0, 0, 0);
+
+    /// A unit vector pointing along the positive Y axis.
+    pub const Y: Self = Self::new(0, 1, 0, 0);
+
+    /// A unit vector pointing along the positive Z axis.
+    pub const Z: Self = Self::new(0, 0, 1, 0);
+
+    /// A unit vector pointing along the positive W axis.
+    pub const W: Self = Self::new(0, 0, 0, 1);
+
+    /// The unit axes.
+    pub const AXES: [Self; 4] = [Self::X, Self::Y, Self::Z, Self::W];
+
+    /// Creates a new vector.
+    #[inline(always)]
+    #[must_use]
+    pub const fn new(x: u16, y: u16, z: u16, w: u16) -> Self {
+        Self { x, y, z, w }
+    }
+
+    /// Creates a vector with all elements set to `v`.
+    #[inline]
+    #[must_use]
+    pub const fn splat(v: u16) -> Self {
+        Self {
+            x: v,
+
+            y: v,
+
+            z: v,
+
+            w: v,
+        }
+    }
+
+    /// Creates a vector from the elements in `if_true` and `if_false`, selecting which to use
+    /// for each element of `self`.
+    ///
+    /// A true element in the mask uses the corresponding element from `if_true`, and false
+    /// uses the element from `if_false`.
+    #[inline]
+    #[must_use]
+    pub fn select(mask: BVec4, if_true: Self, if_false: Self) -> Self {
+        Self {
+            x: if mask.test(0) { if_true.x } else { if_false.x },
+            y: if mask.test(1) { if_true.y } else { if_false.y },
+            z: if mask.test(2) { if_true.z } else { if_false.z },
+            w: if mask.test(3) { if_true.w } else { if_false.w },
+        }
+    }
+
+    /// Creates a new vector from an array.
+    #[inline]
+    #[must_use]
+    pub const fn from_array(a: [u16; 4]) -> Self {
+        Self::new(a[0], a[1], a[2], a[3])
+    }
+
+    /// `[x, y, z, w]`
+    #[inline]
+    #[must_use]
+    pub const fn to_array(&self) -> [u16; 4] {
+        [self.x, self.y, self.z, self.w]
+    }
+
+    /// Creates a vector from the first 4 values in `slice`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `slice` is less than 4 elements long.
+    #[inline]
+    #[must_use]
+    pub const fn from_slice(slice: &[u16]) -> Self {
+        Self::new(slice[0], slice[1], slice[2], slice[3])
+    }
+
+    /// Writes the elements of `self` to the first 4 elements in `slice`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `slice` is less than 4 elements long.
+    #[inline]
+    pub fn write_to_slice(self, slice: &mut [u16]) {
+        slice[0] = self.x;
+        slice[1] = self.y;
+        slice[2] = self.z;
+        slice[3] = self.w;
+    }
+
+    /// Creates a 3D vector from the `x`, `y` and `z` elements of `self`, discarding `w`.
+    ///
+    /// Truncation to [`U16Vec3`] may also be performed by using [`self.xyz()`][crate::swizzles::Vec4Swizzles::xyz()].
+    #[inline]
+    #[must_use]
+    pub fn truncate(self) -> U16Vec3 {
+        use crate::swizzles::Vec4Swizzles;
+        self.xyz()
+    }
+
+    /// Computes the dot product of `self` and `rhs`.
+    #[inline]
+    #[must_use]
+    pub fn dot(self, rhs: Self) -> u16 {
+        (self.x * rhs.x) + (self.y * rhs.y) + (self.z * rhs.z) + (self.w * rhs.w)
+    }
+
+    /// Returns a vector where every component is the dot product of `self` and `rhs`.
+    #[inline]
+    #[must_use]
+    pub fn dot_into_vec(self, rhs: Self) -> Self {
+        Self::splat(self.dot(rhs))
+    }
+
+    /// Returns a vector containing the minimum values for each element of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.min(rhs.x), self.y.min(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub fn min(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.min(rhs.x),
+            y: self.y.min(rhs.y),
+            z: self.z.min(rhs.z),
+            w: self.w.min(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the maximum values for each element of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.max(rhs.x), self.y.max(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub fn max(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.max(rhs.x),
+            y: self.y.max(rhs.y),
+            z: self.z.max(rhs.z),
+            w: self.w.max(rhs.w),
+        }
+    }
+
+    /// Component-wise clamping of values, similar to [`u16::clamp`].
+    ///
+    /// Each element in `min` must be less-or-equal to the corresponding element in `max`.
+    ///
+    /// # Panics
+    ///
+    /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
+    #[inline]
+    #[must_use]
+    pub fn clamp(self, min: Self, max: Self) -> Self {
+        glam_assert!(min.cmple(max).all(), "clamp: expected min <= max");
+        self.max(min).min(max)
+    }
+
+    /// Returns the horizontal minimum of `self`.
+    ///
+    /// In other words this computes `min(x, y, ..)`.
+    #[inline]
+    #[must_use]
+    pub fn min_element(self) -> u16 {
+        self.x.min(self.y.min(self.z.min(self.w)))
+    }
+
+    /// Returns the horizontal maximum of `self`.
+    ///
+    /// In other words this computes `max(x, y, ..)`.
+    #[inline]
+    #[must_use]
+    pub fn max_element(self) -> u16 {
+        self.x.max(self.y.max(self.z.max(self.w)))
+    }
+
+    /// Returns a vector mask containing the result of a `==` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words, this computes `[self.x == rhs.x, self.y == rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpeq(self, rhs: Self) -> BVec4 {
+        BVec4::new(
+            self.x.eq(&rhs.x),
+            self.y.eq(&rhs.y),
+            self.z.eq(&rhs.z),
+            self.w.eq(&rhs.w),
+        )
+    }
+
+    /// Returns a vector mask containing the result of a `!=` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x != rhs.x, self.y != rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpne(self, rhs: Self) -> BVec4 {
+        BVec4::new(
+            self.x.ne(&rhs.x),
+            self.y.ne(&rhs.y),
+            self.z.ne(&rhs.z),
+            self.w.ne(&rhs.w),
+        )
+    }
+
+    /// Returns a vector mask containing the result of a `>=` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x >= rhs.x, self.y >= rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpge(self, rhs: Self) -> BVec4 {
+        BVec4::new(
+            self.x.ge(&rhs.x),
+            self.y.ge(&rhs.y),
+            self.z.ge(&rhs.z),
+            self.w.ge(&rhs.w),
+        )
+    }
+
+    /// Returns a vector mask containing the result of a `>` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x > rhs.x, self.y > rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpgt(self, rhs: Self) -> BVec4 {
+        BVec4::new(
+            self.x.gt(&rhs.x),
+            self.y.gt(&rhs.y),
+            self.z.gt(&rhs.z),
+            self.w.gt(&rhs.w),
+        )
+    }
+
+    /// Returns a vector mask containing the result of a `<=` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x <= rhs.x, self.y <= rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmple(self, rhs: Self) -> BVec4 {
+        BVec4::new(
+            self.x.le(&rhs.x),
+            self.y.le(&rhs.y),
+            self.z.le(&rhs.z),
+            self.w.le(&rhs.w),
+        )
+    }
+
+    /// Returns a vector mask containing the result of a `<` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x < rhs.x, self.y < rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmplt(self, rhs: Self) -> BVec4 {
+        BVec4::new(
+            self.x.lt(&rhs.x),
+            self.y.lt(&rhs.y),
+            self.z.lt(&rhs.z),
+            self.w.lt(&rhs.w),
+        )
+    }
+
+    /// Computes the squared length of `self`.
+    #[doc(alias = "magnitude2")]
+    #[inline]
+    #[must_use]
+    pub fn length_squared(self) -> u16 {
+        self.dot(self)
+    }
+
+    /// Casts all elements of `self` to `f32`.
+    #[inline]
+    #[must_use]
+    pub fn as_vec4(&self) -> crate::Vec4 {
+        crate::Vec4::new(self.x as f32, self.y as f32, self.z as f32, self.w as f32)
+    }
+
+    /// Casts all elements of `self` to `f64`.
+    #[inline]
+    #[must_use]
+    pub fn as_dvec4(&self) -> crate::DVec4 {
+        crate::DVec4::new(self.x as f64, self.y as f64, self.z as f64, self.w as f64)
+    }
+
+    /// Casts all elements of `self` to `i16`.
+    #[inline]
+    #[must_use]
+    pub fn as_i16vec4(&self) -> crate::I16Vec4 {
+        crate::I16Vec4::new(self.x as i16, self.y as i16, self.z as i16, self.w as i16)
+    }
+
+    /// Casts all elements of `self` to `i32`.
+    #[inline]
+    #[must_use]
+    pub fn as_ivec4(&self) -> crate::IVec4 {
+        crate::IVec4::new(self.x as i32, self.y as i32, self.z as i32, self.w as i32)
+    }
+
+    /// Casts all elements of `self` to `u32`.
+    #[inline]
+    #[must_use]
+    pub fn as_uvec4(&self) -> crate::UVec4 {
+        crate::UVec4::new(self.x as u32, self.y as u32, self.z as u32, self.w as u32)
+    }
+
+    /// Casts all elements of `self` to `i64`.
+    #[inline]
+    #[must_use]
+    pub fn as_i64vec4(&self) -> crate::I64Vec4 {
+        crate::I64Vec4::new(self.x as i64, self.y as i64, self.z as i64, self.w as i64)
+    }
+
+    /// Casts all elements of `self` to `u64`.
+    #[inline]
+    #[must_use]
+    pub fn as_u64vec4(&self) -> crate::U64Vec4 {
+        crate::U64Vec4::new(self.x as u64, self.y as u64, self.z as u64, self.w as u64)
+    }
+
+    /// Returns a vector containing the wrapping addition of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_add(rhs.x), self.y.wrapping_add(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_add(rhs.x),
+            y: self.y.wrapping_add(rhs.y),
+            z: self.z.wrapping_add(rhs.z),
+            w: self.w.wrapping_add(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the wrapping subtraction of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_sub(rhs.x), self.y.wrapping_sub(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_sub(rhs.x),
+            y: self.y.wrapping_sub(rhs.y),
+            z: self.z.wrapping_sub(rhs.z),
+            w: self.w.wrapping_sub(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the wrapping multiplication of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_mul(rhs.x), self.y.wrapping_mul(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_mul(rhs.x),
+            y: self.y.wrapping_mul(rhs.y),
+            z: self.z.wrapping_mul(rhs.z),
+            w: self.w.wrapping_mul(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the wrapping division of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_div(rhs.x), self.y.wrapping_div(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_div(rhs.x),
+            y: self.y.wrapping_div(rhs.y),
+            z: self.z.wrapping_div(rhs.z),
+            w: self.w.wrapping_div(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the saturating addition of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_add(rhs.x), self.y.saturating_add(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_add(rhs.x),
+            y: self.y.saturating_add(rhs.y),
+            z: self.z.saturating_add(rhs.z),
+            w: self.w.saturating_add(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the saturating subtraction of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_sub(rhs.x), self.y.saturating_sub(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_sub(rhs.x),
+            y: self.y.saturating_sub(rhs.y),
+            z: self.z.saturating_sub(rhs.z),
+            w: self.w.saturating_sub(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the saturating multiplication of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_mul(rhs.x), self.y.saturating_mul(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_mul(rhs.x),
+            y: self.y.saturating_mul(rhs.y),
+            z: self.z.saturating_mul(rhs.z),
+            w: self.w.saturating_mul(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the saturating division of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_div(rhs.x), self.y.saturating_div(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_div(rhs.x),
+            y: self.y.saturating_div(rhs.y),
+            z: self.z.saturating_div(rhs.z),
+            w: self.w.saturating_div(rhs.w),
+        }
+    }
+}
+
+impl Default for U16Vec4 {
+    #[inline(always)]
+    fn default() -> Self {
+        Self::ZERO
+    }
+}
+
+impl Div<U16Vec4> for U16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.div(rhs.x),
+            y: self.y.div(rhs.y),
+            z: self.z.div(rhs.z),
+            w: self.w.div(rhs.w),
+        }
+    }
+}
+
+impl DivAssign<U16Vec4> for U16Vec4 {
+    #[inline]
+    fn div_assign(&mut self, rhs: Self) {
+        self.x.div_assign(rhs.x);
+        self.y.div_assign(rhs.y);
+        self.z.div_assign(rhs.z);
+        self.w.div_assign(rhs.w);
+    }
+}
+
+impl Div<u16> for U16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn div(self, rhs: u16) -> Self {
+        Self {
+            x: self.x.div(rhs),
+            y: self.y.div(rhs),
+            z: self.z.div(rhs),
+            w: self.w.div(rhs),
+        }
+    }
+}
+
+impl DivAssign<u16> for U16Vec4 {
+    #[inline]
+    fn div_assign(&mut self, rhs: u16) {
+        self.x.div_assign(rhs);
+        self.y.div_assign(rhs);
+        self.z.div_assign(rhs);
+        self.w.div_assign(rhs);
+    }
+}
+
+impl Div<U16Vec4> for u16 {
+    type Output = U16Vec4;
+    #[inline]
+    fn div(self, rhs: U16Vec4) -> U16Vec4 {
+        U16Vec4 {
+            x: self.div(rhs.x),
+            y: self.div(rhs.y),
+            z: self.div(rhs.z),
+            w: self.div(rhs.w),
+        }
+    }
+}
+
+impl Mul<U16Vec4> for U16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.mul(rhs.x),
+            y: self.y.mul(rhs.y),
+            z: self.z.mul(rhs.z),
+            w: self.w.mul(rhs.w),
+        }
+    }
+}
+
+impl MulAssign<U16Vec4> for U16Vec4 {
+    #[inline]
+    fn mul_assign(&mut self, rhs: Self) {
+        self.x.mul_assign(rhs.x);
+        self.y.mul_assign(rhs.y);
+        self.z.mul_assign(rhs.z);
+        self.w.mul_assign(rhs.w);
+    }
+}
+
+impl Mul<u16> for U16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn mul(self, rhs: u16) -> Self {
+        Self {
+            x: self.x.mul(rhs),
+            y: self.y.mul(rhs),
+            z: self.z.mul(rhs),
+            w: self.w.mul(rhs),
+        }
+    }
+}
+
+impl MulAssign<u16> for U16Vec4 {
+    #[inline]
+    fn mul_assign(&mut self, rhs: u16) {
+        self.x.mul_assign(rhs);
+        self.y.mul_assign(rhs);
+        self.z.mul_assign(rhs);
+        self.w.mul_assign(rhs);
+    }
+}
+
+impl Mul<U16Vec4> for u16 {
+    type Output = U16Vec4;
+    #[inline]
+    fn mul(self, rhs: U16Vec4) -> U16Vec4 {
+        U16Vec4 {
+            x: self.mul(rhs.x),
+            y: self.mul(rhs.y),
+            z: self.mul(rhs.z),
+            w: self.mul(rhs.w),
+        }
+    }
+}
+
+impl Add<U16Vec4> for U16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.add(rhs.x),
+            y: self.y.add(rhs.y),
+            z: self.z.add(rhs.z),
+            w: self.w.add(rhs.w),
+        }
+    }
+}
+
+impl AddAssign<U16Vec4> for U16Vec4 {
+    #[inline]
+    fn add_assign(&mut self, rhs: Self) {
+        self.x.add_assign(rhs.x);
+        self.y.add_assign(rhs.y);
+        self.z.add_assign(rhs.z);
+        self.w.add_assign(rhs.w);
+    }
+}
+
+impl Add<u16> for U16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn add(self, rhs: u16) -> Self {
+        Self {
+            x: self.x.add(rhs),
+            y: self.y.add(rhs),
+            z: self.z.add(rhs),
+            w: self.w.add(rhs),
+        }
+    }
+}
+
+impl AddAssign<u16> for U16Vec4 {
+    #[inline]
+    fn add_assign(&mut self, rhs: u16) {
+        self.x.add_assign(rhs);
+        self.y.add_assign(rhs);
+        self.z.add_assign(rhs);
+        self.w.add_assign(rhs);
+    }
+}
+
+impl Add<U16Vec4> for u16 {
+    type Output = U16Vec4;
+    #[inline]
+    fn add(self, rhs: U16Vec4) -> U16Vec4 {
+        U16Vec4 {
+            x: self.add(rhs.x),
+            y: self.add(rhs.y),
+            z: self.add(rhs.z),
+            w: self.add(rhs.w),
+        }
+    }
+}
+
+impl Sub<U16Vec4> for U16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.sub(rhs.x),
+            y: self.y.sub(rhs.y),
+            z: self.z.sub(rhs.z),
+            w: self.w.sub(rhs.w),
+        }
+    }
+}
+
+impl SubAssign<U16Vec4> for U16Vec4 {
+    #[inline]
+    fn sub_assign(&mut self, rhs: U16Vec4) {
+        self.x.sub_assign(rhs.x);
+        self.y.sub_assign(rhs.y);
+        self.z.sub_assign(rhs.z);
+        self.w.sub_assign(rhs.w);
+    }
+}
+
+impl Sub<u16> for U16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn sub(self, rhs: u16) -> Self {
+        Self {
+            x: self.x.sub(rhs),
+            y: self.y.sub(rhs),
+            z: self.z.sub(rhs),
+            w: self.w.sub(rhs),
+        }
+    }
+}
+
+impl SubAssign<u16> for U16Vec4 {
+    #[inline]
+    fn sub_assign(&mut self, rhs: u16) {
+        self.x.sub_assign(rhs);
+        self.y.sub_assign(rhs);
+        self.z.sub_assign(rhs);
+        self.w.sub_assign(rhs);
+    }
+}
+
+impl Sub<U16Vec4> for u16 {
+    type Output = U16Vec4;
+    #[inline]
+    fn sub(self, rhs: U16Vec4) -> U16Vec4 {
+        U16Vec4 {
+            x: self.sub(rhs.x),
+            y: self.sub(rhs.y),
+            z: self.sub(rhs.z),
+            w: self.sub(rhs.w),
+        }
+    }
+}
+
+impl Rem<U16Vec4> for U16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn rem(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.rem(rhs.x),
+            y: self.y.rem(rhs.y),
+            z: self.z.rem(rhs.z),
+            w: self.w.rem(rhs.w),
+        }
+    }
+}
+
+impl RemAssign<U16Vec4> for U16Vec4 {
+    #[inline]
+    fn rem_assign(&mut self, rhs: Self) {
+        self.x.rem_assign(rhs.x);
+        self.y.rem_assign(rhs.y);
+        self.z.rem_assign(rhs.z);
+        self.w.rem_assign(rhs.w);
+    }
+}
+
+impl Rem<u16> for U16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn rem(self, rhs: u16) -> Self {
+        Self {
+            x: self.x.rem(rhs),
+            y: self.y.rem(rhs),
+            z: self.z.rem(rhs),
+            w: self.w.rem(rhs),
+        }
+    }
+}
+
+impl RemAssign<u16> for U16Vec4 {
+    #[inline]
+    fn rem_assign(&mut self, rhs: u16) {
+        self.x.rem_assign(rhs);
+        self.y.rem_assign(rhs);
+        self.z.rem_assign(rhs);
+        self.w.rem_assign(rhs);
+    }
+}
+
+impl Rem<U16Vec4> for u16 {
+    type Output = U16Vec4;
+    #[inline]
+    fn rem(self, rhs: U16Vec4) -> U16Vec4 {
+        U16Vec4 {
+            x: self.rem(rhs.x),
+            y: self.rem(rhs.y),
+            z: self.rem(rhs.z),
+            w: self.rem(rhs.w),
+        }
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl AsRef<[u16; 4]> for U16Vec4 {
+    #[inline]
+    fn as_ref(&self) -> &[u16; 4] {
+        unsafe { &*(self as *const U16Vec4 as *const [u16; 4]) }
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl AsMut<[u16; 4]> for U16Vec4 {
+    #[inline]
+    fn as_mut(&mut self) -> &mut [u16; 4] {
+        unsafe { &mut *(self as *mut U16Vec4 as *mut [u16; 4]) }
+    }
+}
+
+impl Sum for U16Vec4 {
+    #[inline]
+    fn sum<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = Self>,
+    {
+        iter.fold(Self::ZERO, Self::add)
+    }
+}
+
+impl<'a> Sum<&'a Self> for U16Vec4 {
+    #[inline]
+    fn sum<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = &'a Self>,
+    {
+        iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
+    }
+}
+
+impl Product for U16Vec4 {
+    #[inline]
+    fn product<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = Self>,
+    {
+        iter.fold(Self::ONE, Self::mul)
+    }
+}
+
+impl<'a> Product<&'a Self> for U16Vec4 {
+    #[inline]
+    fn product<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = &'a Self>,
+    {
+        iter.fold(Self::ONE, |a, &b| Self::mul(a, b))
+    }
+}
+
+impl Not for U16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn not(self) -> Self::Output {
+        Self {
+            x: self.x.not(),
+            y: self.y.not(),
+            z: self.z.not(),
+            w: self.w.not(),
+        }
+    }
+}
+
+impl BitAnd for U16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn bitand(self, rhs: Self) -> Self::Output {
+        Self {
+            x: self.x.bitand(rhs.x),
+            y: self.y.bitand(rhs.y),
+            z: self.z.bitand(rhs.z),
+            w: self.w.bitand(rhs.w),
+        }
+    }
+}
+
+impl BitOr for U16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn bitor(self, rhs: Self) -> Self::Output {
+        Self {
+            x: self.x.bitor(rhs.x),
+            y: self.y.bitor(rhs.y),
+            z: self.z.bitor(rhs.z),
+            w: self.w.bitor(rhs.w),
+        }
+    }
+}
+
+impl BitXor for U16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn bitxor(self, rhs: Self) -> Self::Output {
+        Self {
+            x: self.x.bitxor(rhs.x),
+            y: self.y.bitxor(rhs.y),
+            z: self.z.bitxor(rhs.z),
+            w: self.w.bitxor(rhs.w),
+        }
+    }
+}
+
+impl BitAnd<u16> for U16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn bitand(self, rhs: u16) -> Self::Output {
+        Self {
+            x: self.x.bitand(rhs),
+            y: self.y.bitand(rhs),
+            z: self.z.bitand(rhs),
+            w: self.w.bitand(rhs),
+        }
+    }
+}
+
+impl BitOr<u16> for U16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn bitor(self, rhs: u16) -> Self::Output {
+        Self {
+            x: self.x.bitor(rhs),
+            y: self.y.bitor(rhs),
+            z: self.z.bitor(rhs),
+            w: self.w.bitor(rhs),
+        }
+    }
+}
+
+impl BitXor<u16> for U16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn bitxor(self, rhs: u16) -> Self::Output {
+        Self {
+            x: self.x.bitxor(rhs),
+            y: self.y.bitxor(rhs),
+            z: self.z.bitxor(rhs),
+            w: self.w.bitxor(rhs),
+        }
+    }
+}
+
+impl Shl<i8> for U16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i8) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+            w: self.w.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i8> for U16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i8) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+            w: self.w.shr(rhs),
+        }
+    }
+}
+
+impl Shl<i16> for U16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i16) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+            w: self.w.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i16> for U16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i16) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+            w: self.w.shr(rhs),
+        }
+    }
+}
+
+impl Shl<i32> for U16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i32) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+            w: self.w.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i32> for U16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i32) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+            w: self.w.shr(rhs),
+        }
+    }
+}
+
+impl Shl<i64> for U16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+            w: self.w.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i64> for U16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+            w: self.w.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u8> for U16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u8) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+            w: self.w.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u8> for U16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u8) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+            w: self.w.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u16> for U16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u16) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+            w: self.w.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u16> for U16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u16) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+            w: self.w.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u32> for U16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u32) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+            w: self.w.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u32> for U16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u32) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+            w: self.w.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u64> for U16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+            w: self.w.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u64> for U16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+            w: self.w.shr(rhs),
+        }
+    }
+}
+
+impl Shl<crate::IVec4> for U16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: crate::IVec4) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs.x),
+            y: self.y.shl(rhs.y),
+            z: self.z.shl(rhs.z),
+            w: self.w.shl(rhs.w),
+        }
+    }
+}
+
+impl Shr<crate::IVec4> for U16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: crate::IVec4) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs.x),
+            y: self.y.shr(rhs.y),
+            z: self.z.shr(rhs.z),
+            w: self.w.shr(rhs.w),
+        }
+    }
+}
+
+impl Shl<crate::UVec4> for U16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: crate::UVec4) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs.x),
+            y: self.y.shl(rhs.y),
+            z: self.z.shl(rhs.z),
+            w: self.w.shl(rhs.w),
+        }
+    }
+}
+
+impl Shr<crate::UVec4> for U16Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: crate::UVec4) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs.x),
+            y: self.y.shr(rhs.y),
+            z: self.z.shr(rhs.z),
+            w: self.w.shr(rhs.w),
+        }
+    }
+}
+
+impl Index<usize> for U16Vec4 {
+    type Output = u16;
+    #[inline]
+    fn index(&self, index: usize) -> &Self::Output {
+        match index {
+            0 => &self.x,
+            1 => &self.y,
+            2 => &self.z,
+            3 => &self.w,
+            _ => panic!("index out of bounds"),
+        }
+    }
+}
+
+impl IndexMut<usize> for U16Vec4 {
+    #[inline]
+    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
+        match index {
+            0 => &mut self.x,
+            1 => &mut self.y,
+            2 => &mut self.z,
+            3 => &mut self.w,
+            _ => panic!("index out of bounds"),
+        }
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl fmt::Display for U16Vec4 {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w)
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl fmt::Debug for U16Vec4 {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt.debug_tuple(stringify!(U16Vec4))
+            .field(&self.x)
+            .field(&self.y)
+            .field(&self.z)
+            .field(&self.w)
+            .finish()
+    }
+}
+
+impl From<[u16; 4]> for U16Vec4 {
+    #[inline]
+    fn from(a: [u16; 4]) -> Self {
+        Self::new(a[0], a[1], a[2], a[3])
+    }
+}
+
+impl From<U16Vec4> for [u16; 4] {
+    #[inline]
+    fn from(v: U16Vec4) -> Self {
+        [v.x, v.y, v.z, v.w]
+    }
+}
+
+impl From<(u16, u16, u16, u16)> for U16Vec4 {
+    #[inline]
+    fn from(t: (u16, u16, u16, u16)) -> Self {
+        Self::new(t.0, t.1, t.2, t.3)
+    }
+}
+
+impl From<U16Vec4> for (u16, u16, u16, u16) {
+    #[inline]
+    fn from(v: U16Vec4) -> Self {
+        (v.x, v.y, v.z, v.w)
+    }
+}
+
+impl From<(U16Vec3, u16)> for U16Vec4 {
+    #[inline]
+    fn from((v, w): (U16Vec3, u16)) -> Self {
+        Self::new(v.x, v.y, v.z, w)
+    }
+}
+
+impl From<(u16, U16Vec3)> for U16Vec4 {
+    #[inline]
+    fn from((x, v): (u16, U16Vec3)) -> Self {
+        Self::new(x, v.x, v.y, v.z)
+    }
+}
+
+impl From<(U16Vec2, u16, u16)> for U16Vec4 {
+    #[inline]
+    fn from((v, z, w): (U16Vec2, u16, u16)) -> Self {
+        Self::new(v.x, v.y, z, w)
+    }
+}
+
+impl From<(U16Vec2, U16Vec2)> for U16Vec4 {
+    #[inline]
+    fn from((v, u): (U16Vec2, U16Vec2)) -> Self {
+        Self::new(v.x, v.y, u.x, u.y)
+    }
+}
+
+impl TryFrom<I16Vec4> for U16Vec4 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: I16Vec4) -> Result<Self, Self::Error> {
+        Ok(Self::new(
+            u16::try_from(v.x)?,
+            u16::try_from(v.y)?,
+            u16::try_from(v.z)?,
+            u16::try_from(v.w)?,
+        ))
+    }
+}
+
+impl TryFrom<IVec4> for U16Vec4 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: IVec4) -> Result<Self, Self::Error> {
+        Ok(Self::new(
+            u16::try_from(v.x)?,
+            u16::try_from(v.y)?,
+            u16::try_from(v.z)?,
+            u16::try_from(v.w)?,
+        ))
+    }
+}
+
+impl TryFrom<UVec4> for U16Vec4 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: UVec4) -> Result<Self, Self::Error> {
+        Ok(Self::new(
+            u16::try_from(v.x)?,
+            u16::try_from(v.y)?,
+            u16::try_from(v.z)?,
+            u16::try_from(v.w)?,
+        ))
+    }
+}
+
+impl TryFrom<I64Vec4> for U16Vec4 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: I64Vec4) -> Result<Self, Self::Error> {
+        Ok(Self::new(
+            u16::try_from(v.x)?,
+            u16::try_from(v.y)?,
+            u16::try_from(v.z)?,
+            u16::try_from(v.w)?,
+        ))
+    }
+}
+
+impl TryFrom<U64Vec4> for U16Vec4 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: U64Vec4) -> Result<Self, Self::Error> {
+        Ok(Self::new(
+            u16::try_from(v.x)?,
+            u16::try_from(v.y)?,
+            u16::try_from(v.z)?,
+            u16::try_from(v.w)?,
+        ))
+    }
+}
diff --git a/src/u32.rs b/src/u32.rs
index 3538c3e..f3c696d 100644
--- a/src/u32.rs
+++ b/src/u32.rs
@@ -10,6 +10,8 @@
 mod test {
     use super::*;
     mod const_test_uvec2 {
+        const_assert_eq!(8, core::mem::size_of::<super::UVec2>());
+
         #[cfg(not(feature = "cuda"))]
         const_assert_eq!(
             core::mem::align_of::<u32>(),
@@ -17,18 +19,20 @@
         );
         #[cfg(feature = "cuda")]
         const_assert_eq!(8, core::mem::align_of::<super::UVec2>());
-        const_assert_eq!(8, core::mem::size_of::<super::UVec2>());
     }
 
     mod const_test_uvec3 {
+        const_assert_eq!(12, core::mem::size_of::<super::UVec3>());
+
         const_assert_eq!(
             core::mem::align_of::<u32>(),
             core::mem::align_of::<super::UVec3>()
         );
-        const_assert_eq!(12, core::mem::size_of::<super::UVec3>());
     }
 
     mod const_test_uvec4 {
+        const_assert_eq!(16, core::mem::size_of::<super::UVec4>());
+
         #[cfg(not(feature = "cuda"))]
         const_assert_eq!(
             core::mem::align_of::<u32>(),
@@ -36,6 +40,5 @@
         );
         #[cfg(feature = "cuda")]
         const_assert_eq!(16, core::mem::align_of::<super::UVec4>());
-        const_assert_eq!(16, core::mem::size_of::<super::UVec4>());
     }
 }
diff --git a/src/u32/uvec2.rs b/src/u32/uvec2.rs
index d0c838e..39fbf9a 100644
--- a/src/u32/uvec2.rs
+++ b/src/u32/uvec2.rs
@@ -1,6 +1,6 @@
 // Generated from vec.rs.tera template. Edit the template, not the generated file.
 
-use crate::{BVec2, UVec3};
+use crate::{BVec2, I16Vec2, I64Vec2, IVec2, U16Vec2, U64Vec2, UVec3};
 
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
@@ -9,6 +9,7 @@
 
 /// Creates a 2-dimensional vector.
 #[inline(always)]
+#[must_use]
 pub const fn uvec2(x: u32, y: u32) -> UVec2 {
     UVec2::new(x, y)
 }
@@ -31,10 +32,16 @@
     /// All ones.
     pub const ONE: Self = Self::splat(1);
 
-    /// A unit-length vector pointing along the positive X axis.
+    /// All `u32::MIN`.
+    pub const MIN: Self = Self::splat(u32::MIN);
+
+    /// All `u32::MAX`.
+    pub const MAX: Self = Self::splat(u32::MAX);
+
+    /// A unit vector pointing along the positive X axis.
     pub const X: Self = Self::new(1, 0);
 
-    /// A unit-length vector pointing along the positive Y axis.
+    /// A unit vector pointing along the positive Y axis.
     pub const Y: Self = Self::new(0, 1);
 
     /// The unit axes.
@@ -42,12 +49,14 @@
 
     /// Creates a new vector.
     #[inline(always)]
+    #[must_use]
     pub const fn new(x: u32, y: u32) -> Self {
         Self { x, y }
     }
 
     /// Creates a vector with all elements set to `v`.
     #[inline]
+    #[must_use]
     pub const fn splat(v: u32) -> Self {
         Self { x: v, y: v }
     }
@@ -58,21 +67,24 @@
     /// A true element in the mask uses the corresponding element from `if_true`, and false
     /// uses the element from `if_false`.
     #[inline]
+    #[must_use]
     pub fn select(mask: BVec2, if_true: Self, if_false: Self) -> Self {
         Self {
-            x: if mask.x { if_true.x } else { if_false.x },
-            y: if mask.y { if_true.y } else { if_false.y },
+            x: if mask.test(0) { if_true.x } else { if_false.x },
+            y: if mask.test(1) { if_true.y } else { if_false.y },
         }
     }
 
     /// Creates a new vector from an array.
     #[inline]
+    #[must_use]
     pub const fn from_array(a: [u32; 2]) -> Self {
         Self::new(a[0], a[1])
     }
 
     /// `[x, y]`
     #[inline]
+    #[must_use]
     pub const fn to_array(&self) -> [u32; 2] {
         [self.x, self.y]
     }
@@ -83,6 +95,7 @@
     ///
     /// Panics if `slice` is less than 2 elements long.
     #[inline]
+    #[must_use]
     pub const fn from_slice(slice: &[u32]) -> Self {
         Self::new(slice[0], slice[1])
     }
@@ -100,18 +113,21 @@
 
     /// Creates a 3D vector from `self` and the given `z` value.
     #[inline]
+    #[must_use]
     pub const fn extend(self, z: u32) -> UVec3 {
         UVec3::new(self.x, self.y, z)
     }
 
     /// Computes the dot product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn dot(self, rhs: Self) -> u32 {
         (self.x * rhs.x) + (self.y * rhs.y)
     }
 
     /// Returns a vector where every component is the dot product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn dot_into_vec(self, rhs: Self) -> Self {
         Self::splat(self.dot(rhs))
     }
@@ -120,6 +136,7 @@
     ///
     /// In other words this computes `[self.x.min(rhs.x), self.y.min(rhs.y), ..]`.
     #[inline]
+    #[must_use]
     pub fn min(self, rhs: Self) -> Self {
         Self {
             x: self.x.min(rhs.x),
@@ -131,6 +148,7 @@
     ///
     /// In other words this computes `[self.x.max(rhs.x), self.y.max(rhs.y), ..]`.
     #[inline]
+    #[must_use]
     pub fn max(self, rhs: Self) -> Self {
         Self {
             x: self.x.max(rhs.x),
@@ -146,6 +164,7 @@
     ///
     /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn clamp(self, min: Self, max: Self) -> Self {
         glam_assert!(min.cmple(max).all(), "clamp: expected min <= max");
         self.max(min).min(max)
@@ -155,6 +174,7 @@
     ///
     /// In other words this computes `min(x, y, ..)`.
     #[inline]
+    #[must_use]
     pub fn min_element(self) -> u32 {
         self.x.min(self.y)
     }
@@ -163,6 +183,7 @@
     ///
     /// In other words this computes `max(x, y, ..)`.
     #[inline]
+    #[must_use]
     pub fn max_element(self) -> u32 {
         self.x.max(self.y)
     }
@@ -173,6 +194,7 @@
     /// In other words, this computes `[self.x == rhs.x, self.y == rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpeq(self, rhs: Self) -> BVec2 {
         BVec2::new(self.x.eq(&rhs.x), self.y.eq(&rhs.y))
     }
@@ -183,6 +205,7 @@
     /// In other words this computes `[self.x != rhs.x, self.y != rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpne(self, rhs: Self) -> BVec2 {
         BVec2::new(self.x.ne(&rhs.x), self.y.ne(&rhs.y))
     }
@@ -193,6 +216,7 @@
     /// In other words this computes `[self.x >= rhs.x, self.y >= rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpge(self, rhs: Self) -> BVec2 {
         BVec2::new(self.x.ge(&rhs.x), self.y.ge(&rhs.y))
     }
@@ -203,6 +227,7 @@
     /// In other words this computes `[self.x > rhs.x, self.y > rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpgt(self, rhs: Self) -> BVec2 {
         BVec2::new(self.x.gt(&rhs.x), self.y.gt(&rhs.y))
     }
@@ -213,6 +238,7 @@
     /// In other words this computes `[self.x <= rhs.x, self.y <= rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmple(self, rhs: Self) -> BVec2 {
         BVec2::new(self.x.le(&rhs.x), self.y.le(&rhs.y))
     }
@@ -223,27 +249,163 @@
     /// In other words this computes `[self.x < rhs.x, self.y < rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmplt(self, rhs: Self) -> BVec2 {
         BVec2::new(self.x.lt(&rhs.x), self.y.lt(&rhs.y))
     }
 
+    /// Computes the squared length of `self`.
+    #[doc(alias = "magnitude2")]
+    #[inline]
+    #[must_use]
+    pub fn length_squared(self) -> u32 {
+        self.dot(self)
+    }
+
     /// Casts all elements of `self` to `f32`.
     #[inline]
+    #[must_use]
     pub fn as_vec2(&self) -> crate::Vec2 {
         crate::Vec2::new(self.x as f32, self.y as f32)
     }
 
     /// Casts all elements of `self` to `f64`.
     #[inline]
+    #[must_use]
     pub fn as_dvec2(&self) -> crate::DVec2 {
         crate::DVec2::new(self.x as f64, self.y as f64)
     }
 
+    /// Casts all elements of `self` to `i16`.
+    #[inline]
+    #[must_use]
+    pub fn as_i16vec2(&self) -> crate::I16Vec2 {
+        crate::I16Vec2::new(self.x as i16, self.y as i16)
+    }
+
+    /// Casts all elements of `self` to `u16`.
+    #[inline]
+    #[must_use]
+    pub fn as_u16vec2(&self) -> crate::U16Vec2 {
+        crate::U16Vec2::new(self.x as u16, self.y as u16)
+    }
+
     /// Casts all elements of `self` to `i32`.
     #[inline]
+    #[must_use]
     pub fn as_ivec2(&self) -> crate::IVec2 {
         crate::IVec2::new(self.x as i32, self.y as i32)
     }
+
+    /// Casts all elements of `self` to `i64`.
+    #[inline]
+    #[must_use]
+    pub fn as_i64vec2(&self) -> crate::I64Vec2 {
+        crate::I64Vec2::new(self.x as i64, self.y as i64)
+    }
+
+    /// Casts all elements of `self` to `u64`.
+    #[inline]
+    #[must_use]
+    pub fn as_u64vec2(&self) -> crate::U64Vec2 {
+        crate::U64Vec2::new(self.x as u64, self.y as u64)
+    }
+
+    /// Returns a vector containing the wrapping addition of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_add(rhs.x), self.y.wrapping_add(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_add(rhs.x),
+            y: self.y.wrapping_add(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the wrapping subtraction of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_sub(rhs.x), self.y.wrapping_sub(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_sub(rhs.x),
+            y: self.y.wrapping_sub(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the wrapping multiplication of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_mul(rhs.x), self.y.wrapping_mul(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_mul(rhs.x),
+            y: self.y.wrapping_mul(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the wrapping division of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_div(rhs.x), self.y.wrapping_div(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_div(rhs.x),
+            y: self.y.wrapping_div(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the saturating addition of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_add(rhs.x), self.y.saturating_add(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_add(rhs.x),
+            y: self.y.saturating_add(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the saturating subtraction of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_sub(rhs.x), self.y.saturating_sub(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_sub(rhs.x),
+            y: self.y.saturating_sub(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the saturating multiplication of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_mul(rhs.x), self.y.saturating_mul(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_mul(rhs.x),
+            y: self.y.saturating_mul(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the saturating division of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_div(rhs.x), self.y.saturating_div(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_div(rhs.x),
+            y: self.y.saturating_div(rhs.y),
+        }
+    }
 }
 
 impl Default for UVec2 {
@@ -697,6 +859,28 @@
     }
 }
 
+impl Shl<i64> for UVec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i64> for UVec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+        }
+    }
+}
+
 impl Shl<u8> for UVec2 {
     type Output = Self;
     #[inline]
@@ -763,6 +947,28 @@
     }
 }
 
+impl Shl<u64> for UVec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u64> for UVec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+        }
+    }
+}
+
 impl Shl<crate::IVec2> for UVec2 {
     type Output = Self;
     #[inline]
@@ -874,3 +1080,46 @@
         (v.x, v.y)
     }
 }
+
+impl From<U16Vec2> for UVec2 {
+    #[inline]
+    fn from(v: U16Vec2) -> Self {
+        Self::new(u32::from(v.x), u32::from(v.y))
+    }
+}
+
+impl TryFrom<I16Vec2> for UVec2 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: I16Vec2) -> Result<Self, Self::Error> {
+        Ok(Self::new(u32::try_from(v.x)?, u32::try_from(v.y)?))
+    }
+}
+
+impl TryFrom<IVec2> for UVec2 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: IVec2) -> Result<Self, Self::Error> {
+        Ok(Self::new(u32::try_from(v.x)?, u32::try_from(v.y)?))
+    }
+}
+
+impl TryFrom<I64Vec2> for UVec2 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: I64Vec2) -> Result<Self, Self::Error> {
+        Ok(Self::new(u32::try_from(v.x)?, u32::try_from(v.y)?))
+    }
+}
+
+impl TryFrom<U64Vec2> for UVec2 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: U64Vec2) -> Result<Self, Self::Error> {
+        Ok(Self::new(u32::try_from(v.x)?, u32::try_from(v.y)?))
+    }
+}
diff --git a/src/u32/uvec3.rs b/src/u32/uvec3.rs
index 040b482..ca06d46 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, UVec2, UVec4};
+use crate::{BVec3, I16Vec3, I64Vec3, IVec3, U16Vec3, U64Vec3, UVec2, UVec4};
 
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
@@ -9,6 +9,7 @@
 
 /// Creates a 3-dimensional vector.
 #[inline(always)]
+#[must_use]
 pub const fn uvec3(x: u32, y: u32, z: u32) -> UVec3 {
     UVec3::new(x, y, z)
 }
@@ -31,13 +32,19 @@
     /// All ones.
     pub const ONE: Self = Self::splat(1);
 
-    /// A unit-length vector pointing along the positive X axis.
+    /// All `u32::MIN`.
+    pub const MIN: Self = Self::splat(u32::MIN);
+
+    /// All `u32::MAX`.
+    pub const MAX: Self = Self::splat(u32::MAX);
+
+    /// A unit vector pointing along the positive X axis.
     pub const X: Self = Self::new(1, 0, 0);
 
-    /// A unit-length vector pointing along the positive Y axis.
+    /// A unit vector pointing along the positive Y axis.
     pub const Y: Self = Self::new(0, 1, 0);
 
-    /// A unit-length vector pointing along the positive Z axis.
+    /// A unit vector pointing along the positive Z axis.
     pub const Z: Self = Self::new(0, 0, 1);
 
     /// The unit axes.
@@ -45,12 +52,14 @@
 
     /// Creates a new vector.
     #[inline(always)]
+    #[must_use]
     pub const fn new(x: u32, y: u32, z: u32) -> Self {
         Self { x, y, z }
     }
 
     /// Creates a vector with all elements set to `v`.
     #[inline]
+    #[must_use]
     pub const fn splat(v: u32) -> Self {
         Self { x: v, y: v, z: v }
     }
@@ -61,22 +70,25 @@
     /// A true element in the mask uses the corresponding element from `if_true`, and false
     /// uses the element from `if_false`.
     #[inline]
+    #[must_use]
     pub fn select(mask: BVec3, if_true: Self, if_false: Self) -> Self {
         Self {
-            x: if mask.x { if_true.x } else { if_false.x },
-            y: if mask.y { if_true.y } else { if_false.y },
-            z: if mask.z { if_true.z } else { if_false.z },
+            x: if mask.test(0) { if_true.x } else { if_false.x },
+            y: if mask.test(1) { if_true.y } else { if_false.y },
+            z: if mask.test(2) { if_true.z } else { if_false.z },
         }
     }
 
     /// Creates a new vector from an array.
     #[inline]
+    #[must_use]
     pub const fn from_array(a: [u32; 3]) -> Self {
         Self::new(a[0], a[1], a[2])
     }
 
     /// `[x, y, z]`
     #[inline]
+    #[must_use]
     pub const fn to_array(&self) -> [u32; 3] {
         [self.x, self.y, self.z]
     }
@@ -87,6 +99,7 @@
     ///
     /// Panics if `slice` is less than 3 elements long.
     #[inline]
+    #[must_use]
     pub const fn from_slice(slice: &[u32]) -> Self {
         Self::new(slice[0], slice[1], slice[2])
     }
@@ -106,6 +119,7 @@
     /// Internal method for creating a 3D vector from a 4D vector, discarding `w`.
     #[allow(dead_code)]
     #[inline]
+    #[must_use]
     pub(crate) fn from_vec4(v: UVec4) -> Self {
         Self {
             x: v.x,
@@ -116,14 +130,16 @@
 
     /// Creates a 4D vector from `self` and the given `w` value.
     #[inline]
+    #[must_use]
     pub fn extend(self, w: u32) -> UVec4 {
         UVec4::new(self.x, self.y, self.z, w)
     }
 
     /// Creates a 2D vector from the `x` and `y` elements of `self`, discarding `z`.
     ///
-    /// Truncation may also be performed by using `self.xy()` or `UVec2::from()`.
+    /// Truncation may also be performed by using [`self.xy()`][crate::swizzles::Vec3Swizzles::xy()].
     #[inline]
+    #[must_use]
     pub fn truncate(self) -> UVec2 {
         use crate::swizzles::Vec3Swizzles;
         self.xy()
@@ -131,18 +147,21 @@
 
     /// Computes the dot product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn dot(self, rhs: Self) -> u32 {
         (self.x * rhs.x) + (self.y * rhs.y) + (self.z * rhs.z)
     }
 
     /// Returns a vector where every component is the dot product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn dot_into_vec(self, rhs: Self) -> Self {
         Self::splat(self.dot(rhs))
     }
 
     /// Computes the cross product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn cross(self, rhs: Self) -> Self {
         Self {
             x: self.y * rhs.z - rhs.y * self.z,
@@ -155,6 +174,7 @@
     ///
     /// In other words this computes `[self.x.min(rhs.x), self.y.min(rhs.y), ..]`.
     #[inline]
+    #[must_use]
     pub fn min(self, rhs: Self) -> Self {
         Self {
             x: self.x.min(rhs.x),
@@ -167,6 +187,7 @@
     ///
     /// In other words this computes `[self.x.max(rhs.x), self.y.max(rhs.y), ..]`.
     #[inline]
+    #[must_use]
     pub fn max(self, rhs: Self) -> Self {
         Self {
             x: self.x.max(rhs.x),
@@ -183,6 +204,7 @@
     ///
     /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn clamp(self, min: Self, max: Self) -> Self {
         glam_assert!(min.cmple(max).all(), "clamp: expected min <= max");
         self.max(min).min(max)
@@ -192,6 +214,7 @@
     ///
     /// In other words this computes `min(x, y, ..)`.
     #[inline]
+    #[must_use]
     pub fn min_element(self) -> u32 {
         self.x.min(self.y.min(self.z))
     }
@@ -200,6 +223,7 @@
     ///
     /// In other words this computes `max(x, y, ..)`.
     #[inline]
+    #[must_use]
     pub fn max_element(self) -> u32 {
         self.x.max(self.y.max(self.z))
     }
@@ -210,6 +234,7 @@
     /// In other words, this computes `[self.x == rhs.x, self.y == rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpeq(self, rhs: Self) -> BVec3 {
         BVec3::new(self.x.eq(&rhs.x), self.y.eq(&rhs.y), self.z.eq(&rhs.z))
     }
@@ -220,6 +245,7 @@
     /// In other words this computes `[self.x != rhs.x, self.y != rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpne(self, rhs: Self) -> BVec3 {
         BVec3::new(self.x.ne(&rhs.x), self.y.ne(&rhs.y), self.z.ne(&rhs.z))
     }
@@ -230,6 +256,7 @@
     /// In other words this computes `[self.x >= rhs.x, self.y >= rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpge(self, rhs: Self) -> BVec3 {
         BVec3::new(self.x.ge(&rhs.x), self.y.ge(&rhs.y), self.z.ge(&rhs.z))
     }
@@ -240,6 +267,7 @@
     /// In other words this computes `[self.x > rhs.x, self.y > rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpgt(self, rhs: Self) -> BVec3 {
         BVec3::new(self.x.gt(&rhs.x), self.y.gt(&rhs.y), self.z.gt(&rhs.z))
     }
@@ -250,6 +278,7 @@
     /// In other words this computes `[self.x <= rhs.x, self.y <= rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmple(self, rhs: Self) -> BVec3 {
         BVec3::new(self.x.le(&rhs.x), self.y.le(&rhs.y), self.z.le(&rhs.z))
     }
@@ -260,33 +289,178 @@
     /// In other words this computes `[self.x < rhs.x, self.y < rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmplt(self, rhs: Self) -> BVec3 {
         BVec3::new(self.x.lt(&rhs.x), self.y.lt(&rhs.y), self.z.lt(&rhs.z))
     }
 
+    /// Computes the squared length of `self`.
+    #[doc(alias = "magnitude2")]
+    #[inline]
+    #[must_use]
+    pub fn length_squared(self) -> u32 {
+        self.dot(self)
+    }
+
     /// Casts all elements of `self` to `f32`.
     #[inline]
+    #[must_use]
     pub fn as_vec3(&self) -> crate::Vec3 {
         crate::Vec3::new(self.x as f32, self.y as f32, self.z as f32)
     }
 
     /// Casts all elements of `self` to `f32`.
     #[inline]
+    #[must_use]
     pub fn as_vec3a(&self) -> crate::Vec3A {
         crate::Vec3A::new(self.x as f32, self.y as f32, self.z as f32)
     }
 
     /// Casts all elements of `self` to `f64`.
     #[inline]
+    #[must_use]
     pub fn as_dvec3(&self) -> crate::DVec3 {
         crate::DVec3::new(self.x as f64, self.y as f64, self.z as f64)
     }
 
+    /// Casts all elements of `self` to `i16`.
+    #[inline]
+    #[must_use]
+    pub fn as_i16vec3(&self) -> crate::I16Vec3 {
+        crate::I16Vec3::new(self.x as i16, self.y as i16, self.z as i16)
+    }
+
+    /// Casts all elements of `self` to `u16`.
+    #[inline]
+    #[must_use]
+    pub fn as_u16vec3(&self) -> crate::U16Vec3 {
+        crate::U16Vec3::new(self.x as u16, self.y as u16, self.z as u16)
+    }
+
     /// Casts all elements of `self` to `i32`.
     #[inline]
+    #[must_use]
     pub fn as_ivec3(&self) -> crate::IVec3 {
         crate::IVec3::new(self.x as i32, self.y as i32, self.z as i32)
     }
+
+    /// Casts all elements of `self` to `i64`.
+    #[inline]
+    #[must_use]
+    pub fn as_i64vec3(&self) -> crate::I64Vec3 {
+        crate::I64Vec3::new(self.x as i64, self.y as i64, self.z as i64)
+    }
+
+    /// Casts all elements of `self` to `u64`.
+    #[inline]
+    #[must_use]
+    pub fn as_u64vec3(&self) -> crate::U64Vec3 {
+        crate::U64Vec3::new(self.x as u64, self.y as u64, self.z as u64)
+    }
+
+    /// Returns a vector containing the wrapping addition of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_add(rhs.x), self.y.wrapping_add(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_add(rhs.x),
+            y: self.y.wrapping_add(rhs.y),
+            z: self.z.wrapping_add(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the wrapping subtraction of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_sub(rhs.x), self.y.wrapping_sub(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_sub(rhs.x),
+            y: self.y.wrapping_sub(rhs.y),
+            z: self.z.wrapping_sub(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the wrapping multiplication of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_mul(rhs.x), self.y.wrapping_mul(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_mul(rhs.x),
+            y: self.y.wrapping_mul(rhs.y),
+            z: self.z.wrapping_mul(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the wrapping division of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_div(rhs.x), self.y.wrapping_div(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_div(rhs.x),
+            y: self.y.wrapping_div(rhs.y),
+            z: self.z.wrapping_div(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the saturating addition of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_add(rhs.x), self.y.saturating_add(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_add(rhs.x),
+            y: self.y.saturating_add(rhs.y),
+            z: self.z.saturating_add(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the saturating subtraction of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_sub(rhs.x), self.y.saturating_sub(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_sub(rhs.x),
+            y: self.y.saturating_sub(rhs.y),
+            z: self.z.saturating_sub(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the saturating multiplication of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_mul(rhs.x), self.y.saturating_mul(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_mul(rhs.x),
+            y: self.y.saturating_mul(rhs.y),
+            z: self.z.saturating_mul(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the saturating division of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_div(rhs.x), self.y.saturating_div(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_div(rhs.x),
+            y: self.y.saturating_div(rhs.y),
+            z: self.z.saturating_div(rhs.z),
+        }
+    }
 }
 
 impl Default for UVec3 {
@@ -778,6 +952,30 @@
     }
 }
 
+impl Shl<i64> for UVec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i64> for UVec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+        }
+    }
+}
+
 impl Shl<u8> for UVec3 {
     type Output = Self;
     #[inline]
@@ -850,6 +1048,30 @@
     }
 }
 
+impl Shl<u64> for UVec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u64> for UVec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+        }
+    }
+}
+
 impl Shl<crate::IVec3> for UVec3 {
     type Output = Self;
     #[inline]
@@ -975,3 +1197,62 @@
         Self::new(v.x, v.y, z)
     }
 }
+
+impl From<U16Vec3> for UVec3 {
+    #[inline]
+    fn from(v: U16Vec3) -> Self {
+        Self::new(u32::from(v.x), u32::from(v.y), u32::from(v.z))
+    }
+}
+
+impl TryFrom<I16Vec3> for UVec3 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: I16Vec3) -> Result<Self, Self::Error> {
+        Ok(Self::new(
+            u32::try_from(v.x)?,
+            u32::try_from(v.y)?,
+            u32::try_from(v.z)?,
+        ))
+    }
+}
+
+impl TryFrom<IVec3> for UVec3 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: IVec3) -> Result<Self, Self::Error> {
+        Ok(Self::new(
+            u32::try_from(v.x)?,
+            u32::try_from(v.y)?,
+            u32::try_from(v.z)?,
+        ))
+    }
+}
+
+impl TryFrom<I64Vec3> for UVec3 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: I64Vec3) -> Result<Self, Self::Error> {
+        Ok(Self::new(
+            u32::try_from(v.x)?,
+            u32::try_from(v.y)?,
+            u32::try_from(v.z)?,
+        ))
+    }
+}
+
+impl TryFrom<U64Vec3> for UVec3 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: U64Vec3) -> Result<Self, Self::Error> {
+        Ok(Self::new(
+            u32::try_from(v.x)?,
+            u32::try_from(v.y)?,
+            u32::try_from(v.z)?,
+        ))
+    }
+}
diff --git a/src/u32/uvec4.rs b/src/u32/uvec4.rs
index e6c43a3..1e64072 100644
--- a/src/u32/uvec4.rs
+++ b/src/u32/uvec4.rs
@@ -1,6 +1,6 @@
 // Generated from vec.rs.tera template. Edit the template, not the generated file.
 
-use crate::{BVec4, UVec2, UVec3};
+use crate::{BVec4, I16Vec4, I64Vec4, IVec4, U16Vec4, U64Vec4, UVec2, UVec3};
 
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
@@ -9,6 +9,7 @@
 
 /// Creates a 4-dimensional vector.
 #[inline(always)]
+#[must_use]
 pub const fn uvec4(x: u32, y: u32, z: u32, w: u32) -> UVec4 {
     UVec4::new(x, y, z, w)
 }
@@ -33,16 +34,22 @@
     /// All ones.
     pub const ONE: Self = Self::splat(1);
 
-    /// A unit-length vector pointing along the positive X axis.
+    /// All `u32::MIN`.
+    pub const MIN: Self = Self::splat(u32::MIN);
+
+    /// All `u32::MAX`.
+    pub const MAX: Self = Self::splat(u32::MAX);
+
+    /// A unit vector pointing along the positive X axis.
     pub const X: Self = Self::new(1, 0, 0, 0);
 
-    /// A unit-length vector pointing along the positive Y axis.
+    /// A unit vector pointing along the positive Y axis.
     pub const Y: Self = Self::new(0, 1, 0, 0);
 
-    /// A unit-length vector pointing along the positive Z axis.
+    /// A unit vector pointing along the positive Z axis.
     pub const Z: Self = Self::new(0, 0, 1, 0);
 
-    /// A unit-length vector pointing along the positive W axis.
+    /// A unit vector pointing along the positive W axis.
     pub const W: Self = Self::new(0, 0, 0, 1);
 
     /// The unit axes.
@@ -50,12 +57,14 @@
 
     /// Creates a new vector.
     #[inline(always)]
+    #[must_use]
     pub const fn new(x: u32, y: u32, z: u32, w: u32) -> Self {
         Self { x, y, z, w }
     }
 
     /// Creates a vector with all elements set to `v`.
     #[inline]
+    #[must_use]
     pub const fn splat(v: u32) -> Self {
         Self {
             x: v,
@@ -74,23 +83,26 @@
     /// A true element in the mask uses the corresponding element from `if_true`, and false
     /// uses the element from `if_false`.
     #[inline]
+    #[must_use]
     pub fn select(mask: BVec4, if_true: Self, if_false: Self) -> Self {
         Self {
-            x: if mask.x { if_true.x } else { if_false.x },
-            y: if mask.y { if_true.y } else { if_false.y },
-            z: if mask.z { if_true.z } else { if_false.z },
-            w: if mask.w { if_true.w } else { if_false.w },
+            x: if mask.test(0) { if_true.x } else { if_false.x },
+            y: if mask.test(1) { if_true.y } else { if_false.y },
+            z: if mask.test(2) { if_true.z } else { if_false.z },
+            w: if mask.test(3) { if_true.w } else { if_false.w },
         }
     }
 
     /// Creates a new vector from an array.
     #[inline]
+    #[must_use]
     pub const fn from_array(a: [u32; 4]) -> Self {
         Self::new(a[0], a[1], a[2], a[3])
     }
 
     /// `[x, y, z, w]`
     #[inline]
+    #[must_use]
     pub const fn to_array(&self) -> [u32; 4] {
         [self.x, self.y, self.z, self.w]
     }
@@ -101,6 +113,7 @@
     ///
     /// Panics if `slice` is less than 4 elements long.
     #[inline]
+    #[must_use]
     pub const fn from_slice(slice: &[u32]) -> Self {
         Self::new(slice[0], slice[1], slice[2], slice[3])
     }
@@ -118,10 +131,11 @@
         slice[3] = self.w;
     }
 
-    /// Creates a 2D vector from the `x`, `y` and `z` elements of `self`, discarding `w`.
+    /// Creates a 3D vector from the `x`, `y` and `z` elements of `self`, discarding `w`.
     ///
-    /// Truncation to `UVec3` may also be performed by using `self.xyz()` or `UVec3::from()`.
+    /// Truncation to [`UVec3`] may also be performed by using [`self.xyz()`][crate::swizzles::Vec4Swizzles::xyz()].
     #[inline]
+    #[must_use]
     pub fn truncate(self) -> UVec3 {
         use crate::swizzles::Vec4Swizzles;
         self.xyz()
@@ -129,12 +143,14 @@
 
     /// Computes the dot product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn dot(self, rhs: Self) -> u32 {
         (self.x * rhs.x) + (self.y * rhs.y) + (self.z * rhs.z) + (self.w * rhs.w)
     }
 
     /// Returns a vector where every component is the dot product of `self` and `rhs`.
     #[inline]
+    #[must_use]
     pub fn dot_into_vec(self, rhs: Self) -> Self {
         Self::splat(self.dot(rhs))
     }
@@ -143,6 +159,7 @@
     ///
     /// In other words this computes `[self.x.min(rhs.x), self.y.min(rhs.y), ..]`.
     #[inline]
+    #[must_use]
     pub fn min(self, rhs: Self) -> Self {
         Self {
             x: self.x.min(rhs.x),
@@ -156,6 +173,7 @@
     ///
     /// In other words this computes `[self.x.max(rhs.x), self.y.max(rhs.y), ..]`.
     #[inline]
+    #[must_use]
     pub fn max(self, rhs: Self) -> Self {
         Self {
             x: self.x.max(rhs.x),
@@ -173,6 +191,7 @@
     ///
     /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
     #[inline]
+    #[must_use]
     pub fn clamp(self, min: Self, max: Self) -> Self {
         glam_assert!(min.cmple(max).all(), "clamp: expected min <= max");
         self.max(min).min(max)
@@ -182,6 +201,7 @@
     ///
     /// In other words this computes `min(x, y, ..)`.
     #[inline]
+    #[must_use]
     pub fn min_element(self) -> u32 {
         self.x.min(self.y.min(self.z.min(self.w)))
     }
@@ -190,6 +210,7 @@
     ///
     /// In other words this computes `max(x, y, ..)`.
     #[inline]
+    #[must_use]
     pub fn max_element(self) -> u32 {
         self.x.max(self.y.max(self.z.max(self.w)))
     }
@@ -200,6 +221,7 @@
     /// In other words, this computes `[self.x == rhs.x, self.y == rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpeq(self, rhs: Self) -> BVec4 {
         BVec4::new(
             self.x.eq(&rhs.x),
@@ -215,6 +237,7 @@
     /// In other words this computes `[self.x != rhs.x, self.y != rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpne(self, rhs: Self) -> BVec4 {
         BVec4::new(
             self.x.ne(&rhs.x),
@@ -230,6 +253,7 @@
     /// In other words this computes `[self.x >= rhs.x, self.y >= rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpge(self, rhs: Self) -> BVec4 {
         BVec4::new(
             self.x.ge(&rhs.x),
@@ -245,6 +269,7 @@
     /// In other words this computes `[self.x > rhs.x, self.y > rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmpgt(self, rhs: Self) -> BVec4 {
         BVec4::new(
             self.x.gt(&rhs.x),
@@ -260,6 +285,7 @@
     /// In other words this computes `[self.x <= rhs.x, self.y <= rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmple(self, rhs: Self) -> BVec4 {
         BVec4::new(
             self.x.le(&rhs.x),
@@ -275,6 +301,7 @@
     /// In other words this computes `[self.x < rhs.x, self.y < rhs.y, ..]` for all
     /// elements.
     #[inline]
+    #[must_use]
     pub fn cmplt(self, rhs: Self) -> BVec4 {
         BVec4::new(
             self.x.lt(&rhs.x),
@@ -284,23 +311,174 @@
         )
     }
 
+    /// Computes the squared length of `self`.
+    #[doc(alias = "magnitude2")]
+    #[inline]
+    #[must_use]
+    pub fn length_squared(self) -> u32 {
+        self.dot(self)
+    }
+
     /// Casts all elements of `self` to `f32`.
     #[inline]
+    #[must_use]
     pub fn as_vec4(&self) -> crate::Vec4 {
         crate::Vec4::new(self.x as f32, self.y as f32, self.z as f32, self.w as f32)
     }
 
     /// Casts all elements of `self` to `f64`.
     #[inline]
+    #[must_use]
     pub fn as_dvec4(&self) -> crate::DVec4 {
         crate::DVec4::new(self.x as f64, self.y as f64, self.z as f64, self.w as f64)
     }
 
+    /// Casts all elements of `self` to `i16`.
+    #[inline]
+    #[must_use]
+    pub fn as_i16vec4(&self) -> crate::I16Vec4 {
+        crate::I16Vec4::new(self.x as i16, self.y as i16, self.z as i16, self.w as i16)
+    }
+
+    /// Casts all elements of `self` to `u16`.
+    #[inline]
+    #[must_use]
+    pub fn as_u16vec4(&self) -> crate::U16Vec4 {
+        crate::U16Vec4::new(self.x as u16, self.y as u16, self.z as u16, self.w as u16)
+    }
+
     /// Casts all elements of `self` to `i32`.
     #[inline]
+    #[must_use]
     pub fn as_ivec4(&self) -> crate::IVec4 {
         crate::IVec4::new(self.x as i32, self.y as i32, self.z as i32, self.w as i32)
     }
+
+    /// Casts all elements of `self` to `i64`.
+    #[inline]
+    #[must_use]
+    pub fn as_i64vec4(&self) -> crate::I64Vec4 {
+        crate::I64Vec4::new(self.x as i64, self.y as i64, self.z as i64, self.w as i64)
+    }
+
+    /// Casts all elements of `self` to `u64`.
+    #[inline]
+    #[must_use]
+    pub fn as_u64vec4(&self) -> crate::U64Vec4 {
+        crate::U64Vec4::new(self.x as u64, self.y as u64, self.z as u64, self.w as u64)
+    }
+
+    /// Returns a vector containing the wrapping addition of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_add(rhs.x), self.y.wrapping_add(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_add(rhs.x),
+            y: self.y.wrapping_add(rhs.y),
+            z: self.z.wrapping_add(rhs.z),
+            w: self.w.wrapping_add(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the wrapping subtraction of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_sub(rhs.x), self.y.wrapping_sub(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_sub(rhs.x),
+            y: self.y.wrapping_sub(rhs.y),
+            z: self.z.wrapping_sub(rhs.z),
+            w: self.w.wrapping_sub(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the wrapping multiplication of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_mul(rhs.x), self.y.wrapping_mul(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_mul(rhs.x),
+            y: self.y.wrapping_mul(rhs.y),
+            z: self.z.wrapping_mul(rhs.z),
+            w: self.w.wrapping_mul(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the wrapping division of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_div(rhs.x), self.y.wrapping_div(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_div(rhs.x),
+            y: self.y.wrapping_div(rhs.y),
+            z: self.z.wrapping_div(rhs.z),
+            w: self.w.wrapping_div(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the saturating addition of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_add(rhs.x), self.y.saturating_add(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_add(rhs.x),
+            y: self.y.saturating_add(rhs.y),
+            z: self.z.saturating_add(rhs.z),
+            w: self.w.saturating_add(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the saturating subtraction of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_sub(rhs.x), self.y.saturating_sub(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_sub(rhs.x),
+            y: self.y.saturating_sub(rhs.y),
+            z: self.z.saturating_sub(rhs.z),
+            w: self.w.saturating_sub(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the saturating multiplication of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_mul(rhs.x), self.y.saturating_mul(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_mul(rhs.x),
+            y: self.y.saturating_mul(rhs.y),
+            z: self.z.saturating_mul(rhs.z),
+            w: self.w.saturating_mul(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the saturating division of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_div(rhs.x), self.y.saturating_div(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_div(rhs.x),
+            y: self.y.saturating_div(rhs.y),
+            z: self.z.saturating_div(rhs.z),
+            w: self.w.saturating_div(rhs.w),
+        }
+    }
 }
 
 impl Default for UVec4 {
@@ -830,6 +1008,32 @@
     }
 }
 
+impl Shl<i64> for UVec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+            w: self.w.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i64> for UVec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+            w: self.w.shr(rhs),
+        }
+    }
+}
+
 impl Shl<u8> for UVec4 {
     type Output = Self;
     #[inline]
@@ -908,6 +1112,32 @@
     }
 }
 
+impl Shl<u64> for UVec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+            w: self.w.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u64> for UVec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+            w: self.w.shr(rhs),
+        }
+    }
+}
+
 impl Shl<crate::IVec4> for UVec4 {
     type Output = Self;
     #[inline]
@@ -1061,3 +1291,71 @@
         Self::new(v.x, v.y, u.x, u.y)
     }
 }
+
+impl From<U16Vec4> for UVec4 {
+    #[inline]
+    fn from(v: U16Vec4) -> Self {
+        Self::new(
+            u32::from(v.x),
+            u32::from(v.y),
+            u32::from(v.z),
+            u32::from(v.w),
+        )
+    }
+}
+
+impl TryFrom<I16Vec4> for UVec4 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: I16Vec4) -> Result<Self, Self::Error> {
+        Ok(Self::new(
+            u32::try_from(v.x)?,
+            u32::try_from(v.y)?,
+            u32::try_from(v.z)?,
+            u32::try_from(v.w)?,
+        ))
+    }
+}
+
+impl TryFrom<IVec4> for UVec4 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: IVec4) -> Result<Self, Self::Error> {
+        Ok(Self::new(
+            u32::try_from(v.x)?,
+            u32::try_from(v.y)?,
+            u32::try_from(v.z)?,
+            u32::try_from(v.w)?,
+        ))
+    }
+}
+
+impl TryFrom<I64Vec4> for UVec4 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: I64Vec4) -> Result<Self, Self::Error> {
+        Ok(Self::new(
+            u32::try_from(v.x)?,
+            u32::try_from(v.y)?,
+            u32::try_from(v.z)?,
+            u32::try_from(v.w)?,
+        ))
+    }
+}
+
+impl TryFrom<U64Vec4> for UVec4 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: U64Vec4) -> Result<Self, Self::Error> {
+        Ok(Self::new(
+            u32::try_from(v.x)?,
+            u32::try_from(v.y)?,
+            u32::try_from(v.z)?,
+            u32::try_from(v.w)?,
+        ))
+    }
+}
diff --git a/src/u64.rs b/src/u64.rs
new file mode 100644
index 0000000..afd2bd2
--- /dev/null
+++ b/src/u64.rs
@@ -0,0 +1,44 @@
+mod u64vec2;
+mod u64vec3;
+mod u64vec4;
+
+pub use u64vec2::{u64vec2, U64Vec2};
+pub use u64vec3::{u64vec3, U64Vec3};
+pub use u64vec4::{u64vec4, U64Vec4};
+
+#[cfg(not(target_arch = "spirv"))]
+mod test {
+    use super::*;
+    mod const_test_u64vec2 {
+        const_assert_eq!(16, core::mem::size_of::<super::U64Vec2>());
+
+        #[cfg(not(feature = "cuda"))]
+        const_assert_eq!(
+            core::mem::align_of::<u64>(),
+            core::mem::align_of::<super::U64Vec2>()
+        );
+        #[cfg(feature = "cuda")]
+        const_assert_eq!(16, core::mem::align_of::<super::U64Vec2>());
+    }
+
+    mod const_test_u64vec3 {
+        const_assert_eq!(24, core::mem::size_of::<super::U64Vec3>());
+
+        const_assert_eq!(
+            core::mem::align_of::<u64>(),
+            core::mem::align_of::<super::U64Vec3>()
+        );
+    }
+
+    mod const_test_u64vec4 {
+        const_assert_eq!(32, core::mem::size_of::<super::U64Vec4>());
+
+        #[cfg(not(feature = "cuda"))]
+        const_assert_eq!(
+            core::mem::align_of::<u64>(),
+            core::mem::align_of::<super::U64Vec4>()
+        );
+        #[cfg(feature = "cuda")]
+        const_assert_eq!(16, core::mem::align_of::<super::U64Vec4>());
+    }
+}
diff --git a/src/u64/u64vec2.rs b/src/u64/u64vec2.rs
new file mode 100644
index 0000000..4f74652
--- /dev/null
+++ b/src/u64/u64vec2.rs
@@ -0,0 +1,1123 @@
+// Generated from vec.rs.tera template. Edit the template, not the generated file.
+
+use crate::{BVec2, I16Vec2, I64Vec2, IVec2, U16Vec2, U64Vec3, UVec2};
+
+#[cfg(not(target_arch = "spirv"))]
+use core::fmt;
+use core::iter::{Product, Sum};
+use core::{f32, ops::*};
+
+/// Creates a 2-dimensional vector.
+#[inline(always)]
+#[must_use]
+pub const fn u64vec2(x: u64, y: u64) -> U64Vec2 {
+    U64Vec2::new(x, y)
+}
+
+/// A 2-dimensional vector.
+#[cfg_attr(not(target_arch = "spirv"), derive(Hash))]
+#[derive(Clone, Copy, PartialEq, Eq)]
+#[cfg_attr(feature = "cuda", repr(align(16)))]
+#[cfg_attr(not(target_arch = "spirv"), repr(C))]
+#[cfg_attr(target_arch = "spirv", repr(simd))]
+pub struct U64Vec2 {
+    pub x: u64,
+    pub y: u64,
+}
+
+impl U64Vec2 {
+    /// All zeroes.
+    pub const ZERO: Self = Self::splat(0);
+
+    /// All ones.
+    pub const ONE: Self = Self::splat(1);
+
+    /// All `u64::MIN`.
+    pub const MIN: Self = Self::splat(u64::MIN);
+
+    /// All `u64::MAX`.
+    pub const MAX: Self = Self::splat(u64::MAX);
+
+    /// A unit vector pointing along the positive X axis.
+    pub const X: Self = Self::new(1, 0);
+
+    /// A unit vector pointing along the positive Y axis.
+    pub const Y: Self = Self::new(0, 1);
+
+    /// The unit axes.
+    pub const AXES: [Self; 2] = [Self::X, Self::Y];
+
+    /// Creates a new vector.
+    #[inline(always)]
+    #[must_use]
+    pub const fn new(x: u64, y: u64) -> Self {
+        Self { x, y }
+    }
+
+    /// Creates a vector with all elements set to `v`.
+    #[inline]
+    #[must_use]
+    pub const fn splat(v: u64) -> Self {
+        Self { x: v, y: v }
+    }
+
+    /// Creates a vector from the elements in `if_true` and `if_false`, selecting which to use
+    /// for each element of `self`.
+    ///
+    /// A true element in the mask uses the corresponding element from `if_true`, and false
+    /// uses the element from `if_false`.
+    #[inline]
+    #[must_use]
+    pub fn select(mask: BVec2, if_true: Self, if_false: Self) -> Self {
+        Self {
+            x: if mask.test(0) { if_true.x } else { if_false.x },
+            y: if mask.test(1) { if_true.y } else { if_false.y },
+        }
+    }
+
+    /// Creates a new vector from an array.
+    #[inline]
+    #[must_use]
+    pub const fn from_array(a: [u64; 2]) -> Self {
+        Self::new(a[0], a[1])
+    }
+
+    /// `[x, y]`
+    #[inline]
+    #[must_use]
+    pub const fn to_array(&self) -> [u64; 2] {
+        [self.x, self.y]
+    }
+
+    /// Creates a vector from the first 2 values in `slice`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `slice` is less than 2 elements long.
+    #[inline]
+    #[must_use]
+    pub const fn from_slice(slice: &[u64]) -> Self {
+        Self::new(slice[0], slice[1])
+    }
+
+    /// Writes the elements of `self` to the first 2 elements in `slice`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `slice` is less than 2 elements long.
+    #[inline]
+    pub fn write_to_slice(self, slice: &mut [u64]) {
+        slice[0] = self.x;
+        slice[1] = self.y;
+    }
+
+    /// Creates a 3D vector from `self` and the given `z` value.
+    #[inline]
+    #[must_use]
+    pub const fn extend(self, z: u64) -> U64Vec3 {
+        U64Vec3::new(self.x, self.y, z)
+    }
+
+    /// Computes the dot product of `self` and `rhs`.
+    #[inline]
+    #[must_use]
+    pub fn dot(self, rhs: Self) -> u64 {
+        (self.x * rhs.x) + (self.y * rhs.y)
+    }
+
+    /// Returns a vector where every component is the dot product of `self` and `rhs`.
+    #[inline]
+    #[must_use]
+    pub fn dot_into_vec(self, rhs: Self) -> Self {
+        Self::splat(self.dot(rhs))
+    }
+
+    /// Returns a vector containing the minimum values for each element of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.min(rhs.x), self.y.min(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub fn min(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.min(rhs.x),
+            y: self.y.min(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the maximum values for each element of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.max(rhs.x), self.y.max(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub fn max(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.max(rhs.x),
+            y: self.y.max(rhs.y),
+        }
+    }
+
+    /// Component-wise clamping of values, similar to [`u64::clamp`].
+    ///
+    /// Each element in `min` must be less-or-equal to the corresponding element in `max`.
+    ///
+    /// # Panics
+    ///
+    /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
+    #[inline]
+    #[must_use]
+    pub fn clamp(self, min: Self, max: Self) -> Self {
+        glam_assert!(min.cmple(max).all(), "clamp: expected min <= max");
+        self.max(min).min(max)
+    }
+
+    /// Returns the horizontal minimum of `self`.
+    ///
+    /// In other words this computes `min(x, y, ..)`.
+    #[inline]
+    #[must_use]
+    pub fn min_element(self) -> u64 {
+        self.x.min(self.y)
+    }
+
+    /// Returns the horizontal maximum of `self`.
+    ///
+    /// In other words this computes `max(x, y, ..)`.
+    #[inline]
+    #[must_use]
+    pub fn max_element(self) -> u64 {
+        self.x.max(self.y)
+    }
+
+    /// Returns a vector mask containing the result of a `==` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words, this computes `[self.x == rhs.x, self.y == rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpeq(self, rhs: Self) -> BVec2 {
+        BVec2::new(self.x.eq(&rhs.x), self.y.eq(&rhs.y))
+    }
+
+    /// Returns a vector mask containing the result of a `!=` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x != rhs.x, self.y != rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpne(self, rhs: Self) -> BVec2 {
+        BVec2::new(self.x.ne(&rhs.x), self.y.ne(&rhs.y))
+    }
+
+    /// Returns a vector mask containing the result of a `>=` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x >= rhs.x, self.y >= rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpge(self, rhs: Self) -> BVec2 {
+        BVec2::new(self.x.ge(&rhs.x), self.y.ge(&rhs.y))
+    }
+
+    /// Returns a vector mask containing the result of a `>` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x > rhs.x, self.y > rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpgt(self, rhs: Self) -> BVec2 {
+        BVec2::new(self.x.gt(&rhs.x), self.y.gt(&rhs.y))
+    }
+
+    /// Returns a vector mask containing the result of a `<=` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x <= rhs.x, self.y <= rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmple(self, rhs: Self) -> BVec2 {
+        BVec2::new(self.x.le(&rhs.x), self.y.le(&rhs.y))
+    }
+
+    /// Returns a vector mask containing the result of a `<` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x < rhs.x, self.y < rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmplt(self, rhs: Self) -> BVec2 {
+        BVec2::new(self.x.lt(&rhs.x), self.y.lt(&rhs.y))
+    }
+
+    /// Computes the squared length of `self`.
+    #[doc(alias = "magnitude2")]
+    #[inline]
+    #[must_use]
+    pub fn length_squared(self) -> u64 {
+        self.dot(self)
+    }
+
+    /// Casts all elements of `self` to `f32`.
+    #[inline]
+    #[must_use]
+    pub fn as_vec2(&self) -> crate::Vec2 {
+        crate::Vec2::new(self.x as f32, self.y as f32)
+    }
+
+    /// Casts all elements of `self` to `f64`.
+    #[inline]
+    #[must_use]
+    pub fn as_dvec2(&self) -> crate::DVec2 {
+        crate::DVec2::new(self.x as f64, self.y as f64)
+    }
+
+    /// Casts all elements of `self` to `i16`.
+    #[inline]
+    #[must_use]
+    pub fn as_i16vec2(&self) -> crate::I16Vec2 {
+        crate::I16Vec2::new(self.x as i16, self.y as i16)
+    }
+
+    /// Casts all elements of `self` to `u16`.
+    #[inline]
+    #[must_use]
+    pub fn as_u16vec2(&self) -> crate::U16Vec2 {
+        crate::U16Vec2::new(self.x as u16, self.y as u16)
+    }
+
+    /// Casts all elements of `self` to `i32`.
+    #[inline]
+    #[must_use]
+    pub fn as_ivec2(&self) -> crate::IVec2 {
+        crate::IVec2::new(self.x as i32, self.y as i32)
+    }
+
+    /// Casts all elements of `self` to `u32`.
+    #[inline]
+    #[must_use]
+    pub fn as_uvec2(&self) -> crate::UVec2 {
+        crate::UVec2::new(self.x as u32, self.y as u32)
+    }
+
+    /// Casts all elements of `self` to `i64`.
+    #[inline]
+    #[must_use]
+    pub fn as_i64vec2(&self) -> crate::I64Vec2 {
+        crate::I64Vec2::new(self.x as i64, self.y as i64)
+    }
+
+    /// Returns a vector containing the wrapping addition of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_add(rhs.x), self.y.wrapping_add(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_add(rhs.x),
+            y: self.y.wrapping_add(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the wrapping subtraction of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_sub(rhs.x), self.y.wrapping_sub(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_sub(rhs.x),
+            y: self.y.wrapping_sub(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the wrapping multiplication of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_mul(rhs.x), self.y.wrapping_mul(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_mul(rhs.x),
+            y: self.y.wrapping_mul(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the wrapping division of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_div(rhs.x), self.y.wrapping_div(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_div(rhs.x),
+            y: self.y.wrapping_div(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the saturating addition of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_add(rhs.x), self.y.saturating_add(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_add(rhs.x),
+            y: self.y.saturating_add(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the saturating subtraction of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_sub(rhs.x), self.y.saturating_sub(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_sub(rhs.x),
+            y: self.y.saturating_sub(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the saturating multiplication of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_mul(rhs.x), self.y.saturating_mul(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_mul(rhs.x),
+            y: self.y.saturating_mul(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the saturating division of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_div(rhs.x), self.y.saturating_div(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_div(rhs.x),
+            y: self.y.saturating_div(rhs.y),
+        }
+    }
+}
+
+impl Default for U64Vec2 {
+    #[inline(always)]
+    fn default() -> Self {
+        Self::ZERO
+    }
+}
+
+impl Div<U64Vec2> for U64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.div(rhs.x),
+            y: self.y.div(rhs.y),
+        }
+    }
+}
+
+impl DivAssign<U64Vec2> for U64Vec2 {
+    #[inline]
+    fn div_assign(&mut self, rhs: Self) {
+        self.x.div_assign(rhs.x);
+        self.y.div_assign(rhs.y);
+    }
+}
+
+impl Div<u64> for U64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn div(self, rhs: u64) -> Self {
+        Self {
+            x: self.x.div(rhs),
+            y: self.y.div(rhs),
+        }
+    }
+}
+
+impl DivAssign<u64> for U64Vec2 {
+    #[inline]
+    fn div_assign(&mut self, rhs: u64) {
+        self.x.div_assign(rhs);
+        self.y.div_assign(rhs);
+    }
+}
+
+impl Div<U64Vec2> for u64 {
+    type Output = U64Vec2;
+    #[inline]
+    fn div(self, rhs: U64Vec2) -> U64Vec2 {
+        U64Vec2 {
+            x: self.div(rhs.x),
+            y: self.div(rhs.y),
+        }
+    }
+}
+
+impl Mul<U64Vec2> for U64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.mul(rhs.x),
+            y: self.y.mul(rhs.y),
+        }
+    }
+}
+
+impl MulAssign<U64Vec2> for U64Vec2 {
+    #[inline]
+    fn mul_assign(&mut self, rhs: Self) {
+        self.x.mul_assign(rhs.x);
+        self.y.mul_assign(rhs.y);
+    }
+}
+
+impl Mul<u64> for U64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn mul(self, rhs: u64) -> Self {
+        Self {
+            x: self.x.mul(rhs),
+            y: self.y.mul(rhs),
+        }
+    }
+}
+
+impl MulAssign<u64> for U64Vec2 {
+    #[inline]
+    fn mul_assign(&mut self, rhs: u64) {
+        self.x.mul_assign(rhs);
+        self.y.mul_assign(rhs);
+    }
+}
+
+impl Mul<U64Vec2> for u64 {
+    type Output = U64Vec2;
+    #[inline]
+    fn mul(self, rhs: U64Vec2) -> U64Vec2 {
+        U64Vec2 {
+            x: self.mul(rhs.x),
+            y: self.mul(rhs.y),
+        }
+    }
+}
+
+impl Add<U64Vec2> for U64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.add(rhs.x),
+            y: self.y.add(rhs.y),
+        }
+    }
+}
+
+impl AddAssign<U64Vec2> for U64Vec2 {
+    #[inline]
+    fn add_assign(&mut self, rhs: Self) {
+        self.x.add_assign(rhs.x);
+        self.y.add_assign(rhs.y);
+    }
+}
+
+impl Add<u64> for U64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn add(self, rhs: u64) -> Self {
+        Self {
+            x: self.x.add(rhs),
+            y: self.y.add(rhs),
+        }
+    }
+}
+
+impl AddAssign<u64> for U64Vec2 {
+    #[inline]
+    fn add_assign(&mut self, rhs: u64) {
+        self.x.add_assign(rhs);
+        self.y.add_assign(rhs);
+    }
+}
+
+impl Add<U64Vec2> for u64 {
+    type Output = U64Vec2;
+    #[inline]
+    fn add(self, rhs: U64Vec2) -> U64Vec2 {
+        U64Vec2 {
+            x: self.add(rhs.x),
+            y: self.add(rhs.y),
+        }
+    }
+}
+
+impl Sub<U64Vec2> for U64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.sub(rhs.x),
+            y: self.y.sub(rhs.y),
+        }
+    }
+}
+
+impl SubAssign<U64Vec2> for U64Vec2 {
+    #[inline]
+    fn sub_assign(&mut self, rhs: U64Vec2) {
+        self.x.sub_assign(rhs.x);
+        self.y.sub_assign(rhs.y);
+    }
+}
+
+impl Sub<u64> for U64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn sub(self, rhs: u64) -> Self {
+        Self {
+            x: self.x.sub(rhs),
+            y: self.y.sub(rhs),
+        }
+    }
+}
+
+impl SubAssign<u64> for U64Vec2 {
+    #[inline]
+    fn sub_assign(&mut self, rhs: u64) {
+        self.x.sub_assign(rhs);
+        self.y.sub_assign(rhs);
+    }
+}
+
+impl Sub<U64Vec2> for u64 {
+    type Output = U64Vec2;
+    #[inline]
+    fn sub(self, rhs: U64Vec2) -> U64Vec2 {
+        U64Vec2 {
+            x: self.sub(rhs.x),
+            y: self.sub(rhs.y),
+        }
+    }
+}
+
+impl Rem<U64Vec2> for U64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn rem(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.rem(rhs.x),
+            y: self.y.rem(rhs.y),
+        }
+    }
+}
+
+impl RemAssign<U64Vec2> for U64Vec2 {
+    #[inline]
+    fn rem_assign(&mut self, rhs: Self) {
+        self.x.rem_assign(rhs.x);
+        self.y.rem_assign(rhs.y);
+    }
+}
+
+impl Rem<u64> for U64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn rem(self, rhs: u64) -> Self {
+        Self {
+            x: self.x.rem(rhs),
+            y: self.y.rem(rhs),
+        }
+    }
+}
+
+impl RemAssign<u64> for U64Vec2 {
+    #[inline]
+    fn rem_assign(&mut self, rhs: u64) {
+        self.x.rem_assign(rhs);
+        self.y.rem_assign(rhs);
+    }
+}
+
+impl Rem<U64Vec2> for u64 {
+    type Output = U64Vec2;
+    #[inline]
+    fn rem(self, rhs: U64Vec2) -> U64Vec2 {
+        U64Vec2 {
+            x: self.rem(rhs.x),
+            y: self.rem(rhs.y),
+        }
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl AsRef<[u64; 2]> for U64Vec2 {
+    #[inline]
+    fn as_ref(&self) -> &[u64; 2] {
+        unsafe { &*(self as *const U64Vec2 as *const [u64; 2]) }
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl AsMut<[u64; 2]> for U64Vec2 {
+    #[inline]
+    fn as_mut(&mut self) -> &mut [u64; 2] {
+        unsafe { &mut *(self as *mut U64Vec2 as *mut [u64; 2]) }
+    }
+}
+
+impl Sum for U64Vec2 {
+    #[inline]
+    fn sum<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = Self>,
+    {
+        iter.fold(Self::ZERO, Self::add)
+    }
+}
+
+impl<'a> Sum<&'a Self> for U64Vec2 {
+    #[inline]
+    fn sum<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = &'a Self>,
+    {
+        iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
+    }
+}
+
+impl Product for U64Vec2 {
+    #[inline]
+    fn product<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = Self>,
+    {
+        iter.fold(Self::ONE, Self::mul)
+    }
+}
+
+impl<'a> Product<&'a Self> for U64Vec2 {
+    #[inline]
+    fn product<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = &'a Self>,
+    {
+        iter.fold(Self::ONE, |a, &b| Self::mul(a, b))
+    }
+}
+
+impl Not for U64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn not(self) -> Self::Output {
+        Self {
+            x: self.x.not(),
+            y: self.y.not(),
+        }
+    }
+}
+
+impl BitAnd for U64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn bitand(self, rhs: Self) -> Self::Output {
+        Self {
+            x: self.x.bitand(rhs.x),
+            y: self.y.bitand(rhs.y),
+        }
+    }
+}
+
+impl BitOr for U64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn bitor(self, rhs: Self) -> Self::Output {
+        Self {
+            x: self.x.bitor(rhs.x),
+            y: self.y.bitor(rhs.y),
+        }
+    }
+}
+
+impl BitXor for U64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn bitxor(self, rhs: Self) -> Self::Output {
+        Self {
+            x: self.x.bitxor(rhs.x),
+            y: self.y.bitxor(rhs.y),
+        }
+    }
+}
+
+impl BitAnd<u64> for U64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn bitand(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.bitand(rhs),
+            y: self.y.bitand(rhs),
+        }
+    }
+}
+
+impl BitOr<u64> for U64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn bitor(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.bitor(rhs),
+            y: self.y.bitor(rhs),
+        }
+    }
+}
+
+impl BitXor<u64> for U64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn bitxor(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.bitxor(rhs),
+            y: self.y.bitxor(rhs),
+        }
+    }
+}
+
+impl Shl<i8> for U64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i8) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i8> for U64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i8) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+        }
+    }
+}
+
+impl Shl<i16> for U64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i16) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i16> for U64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i16) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+        }
+    }
+}
+
+impl Shl<i32> for U64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i32) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i32> for U64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i32) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+        }
+    }
+}
+
+impl Shl<i64> for U64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i64> for U64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u8> for U64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u8) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u8> for U64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u8) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u16> for U64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u16) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u16> for U64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u16) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u32> for U64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u32) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u32> for U64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u32) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u64> for U64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u64> for U64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+        }
+    }
+}
+
+impl Shl<crate::IVec2> for U64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: crate::IVec2) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs.x),
+            y: self.y.shl(rhs.y),
+        }
+    }
+}
+
+impl Shr<crate::IVec2> for U64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: crate::IVec2) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs.x),
+            y: self.y.shr(rhs.y),
+        }
+    }
+}
+
+impl Shl<crate::UVec2> for U64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: crate::UVec2) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs.x),
+            y: self.y.shl(rhs.y),
+        }
+    }
+}
+
+impl Shr<crate::UVec2> for U64Vec2 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: crate::UVec2) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs.x),
+            y: self.y.shr(rhs.y),
+        }
+    }
+}
+
+impl Index<usize> for U64Vec2 {
+    type Output = u64;
+    #[inline]
+    fn index(&self, index: usize) -> &Self::Output {
+        match index {
+            0 => &self.x,
+            1 => &self.y,
+            _ => panic!("index out of bounds"),
+        }
+    }
+}
+
+impl IndexMut<usize> for U64Vec2 {
+    #[inline]
+    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
+        match index {
+            0 => &mut self.x,
+            1 => &mut self.y,
+            _ => panic!("index out of bounds"),
+        }
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl fmt::Display for U64Vec2 {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "[{}, {}]", self.x, self.y)
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl fmt::Debug for U64Vec2 {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt.debug_tuple(stringify!(U64Vec2))
+            .field(&self.x)
+            .field(&self.y)
+            .finish()
+    }
+}
+
+impl From<[u64; 2]> for U64Vec2 {
+    #[inline]
+    fn from(a: [u64; 2]) -> Self {
+        Self::new(a[0], a[1])
+    }
+}
+
+impl From<U64Vec2> for [u64; 2] {
+    #[inline]
+    fn from(v: U64Vec2) -> Self {
+        [v.x, v.y]
+    }
+}
+
+impl From<(u64, u64)> for U64Vec2 {
+    #[inline]
+    fn from(t: (u64, u64)) -> Self {
+        Self::new(t.0, t.1)
+    }
+}
+
+impl From<U64Vec2> for (u64, u64) {
+    #[inline]
+    fn from(v: U64Vec2) -> Self {
+        (v.x, v.y)
+    }
+}
+
+impl From<U16Vec2> for U64Vec2 {
+    #[inline]
+    fn from(v: U16Vec2) -> Self {
+        Self::new(u64::from(v.x), u64::from(v.y))
+    }
+}
+
+impl From<UVec2> for U64Vec2 {
+    #[inline]
+    fn from(v: UVec2) -> Self {
+        Self::new(u64::from(v.x), u64::from(v.y))
+    }
+}
+
+impl TryFrom<I16Vec2> for U64Vec2 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: I16Vec2) -> Result<Self, Self::Error> {
+        Ok(Self::new(u64::try_from(v.x)?, u64::try_from(v.y)?))
+    }
+}
+
+impl TryFrom<IVec2> for U64Vec2 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: IVec2) -> Result<Self, Self::Error> {
+        Ok(Self::new(u64::try_from(v.x)?, u64::try_from(v.y)?))
+    }
+}
+
+impl TryFrom<I64Vec2> for U64Vec2 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: I64Vec2) -> Result<Self, Self::Error> {
+        Ok(Self::new(u64::try_from(v.x)?, u64::try_from(v.y)?))
+    }
+}
diff --git a/src/u64/u64vec3.rs b/src/u64/u64vec3.rs
new file mode 100644
index 0000000..7411bff
--- /dev/null
+++ b/src/u64/u64vec3.rs
@@ -0,0 +1,1252 @@
+// Generated from vec.rs.tera template. Edit the template, not the generated file.
+
+use crate::{BVec3, I16Vec3, I64Vec3, IVec3, U16Vec3, U64Vec2, U64Vec4, UVec3};
+
+#[cfg(not(target_arch = "spirv"))]
+use core::fmt;
+use core::iter::{Product, Sum};
+use core::{f32, ops::*};
+
+/// Creates a 3-dimensional vector.
+#[inline(always)]
+#[must_use]
+pub const fn u64vec3(x: u64, y: u64, z: u64) -> U64Vec3 {
+    U64Vec3::new(x, y, z)
+}
+
+/// A 3-dimensional vector.
+#[cfg_attr(not(target_arch = "spirv"), derive(Hash))]
+#[derive(Clone, Copy, PartialEq, Eq)]
+#[cfg_attr(not(target_arch = "spirv"), repr(C))]
+#[cfg_attr(target_arch = "spirv", repr(simd))]
+pub struct U64Vec3 {
+    pub x: u64,
+    pub y: u64,
+    pub z: u64,
+}
+
+impl U64Vec3 {
+    /// All zeroes.
+    pub const ZERO: Self = Self::splat(0);
+
+    /// All ones.
+    pub const ONE: Self = Self::splat(1);
+
+    /// All `u64::MIN`.
+    pub const MIN: Self = Self::splat(u64::MIN);
+
+    /// All `u64::MAX`.
+    pub const MAX: Self = Self::splat(u64::MAX);
+
+    /// A unit vector pointing along the positive X axis.
+    pub const X: Self = Self::new(1, 0, 0);
+
+    /// A unit vector pointing along the positive Y axis.
+    pub const Y: Self = Self::new(0, 1, 0);
+
+    /// A unit vector pointing along the positive Z axis.
+    pub const Z: Self = Self::new(0, 0, 1);
+
+    /// The unit axes.
+    pub const AXES: [Self; 3] = [Self::X, Self::Y, Self::Z];
+
+    /// Creates a new vector.
+    #[inline(always)]
+    #[must_use]
+    pub const fn new(x: u64, y: u64, z: u64) -> Self {
+        Self { x, y, z }
+    }
+
+    /// Creates a vector with all elements set to `v`.
+    #[inline]
+    #[must_use]
+    pub const fn splat(v: u64) -> Self {
+        Self { x: v, y: v, z: v }
+    }
+
+    /// Creates a vector from the elements in `if_true` and `if_false`, selecting which to use
+    /// for each element of `self`.
+    ///
+    /// A true element in the mask uses the corresponding element from `if_true`, and false
+    /// uses the element from `if_false`.
+    #[inline]
+    #[must_use]
+    pub fn select(mask: BVec3, if_true: Self, if_false: Self) -> Self {
+        Self {
+            x: if mask.test(0) { if_true.x } else { if_false.x },
+            y: if mask.test(1) { if_true.y } else { if_false.y },
+            z: if mask.test(2) { if_true.z } else { if_false.z },
+        }
+    }
+
+    /// Creates a new vector from an array.
+    #[inline]
+    #[must_use]
+    pub const fn from_array(a: [u64; 3]) -> Self {
+        Self::new(a[0], a[1], a[2])
+    }
+
+    /// `[x, y, z]`
+    #[inline]
+    #[must_use]
+    pub const fn to_array(&self) -> [u64; 3] {
+        [self.x, self.y, self.z]
+    }
+
+    /// Creates a vector from the first 3 values in `slice`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `slice` is less than 3 elements long.
+    #[inline]
+    #[must_use]
+    pub const fn from_slice(slice: &[u64]) -> Self {
+        Self::new(slice[0], slice[1], slice[2])
+    }
+
+    /// Writes the elements of `self` to the first 3 elements in `slice`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `slice` is less than 3 elements long.
+    #[inline]
+    pub fn write_to_slice(self, slice: &mut [u64]) {
+        slice[0] = self.x;
+        slice[1] = self.y;
+        slice[2] = self.z;
+    }
+
+    /// Internal method for creating a 3D vector from a 4D vector, discarding `w`.
+    #[allow(dead_code)]
+    #[inline]
+    #[must_use]
+    pub(crate) fn from_vec4(v: U64Vec4) -> Self {
+        Self {
+            x: v.x,
+            y: v.y,
+            z: v.z,
+        }
+    }
+
+    /// Creates a 4D vector from `self` and the given `w` value.
+    #[inline]
+    #[must_use]
+    pub fn extend(self, w: u64) -> U64Vec4 {
+        U64Vec4::new(self.x, self.y, self.z, w)
+    }
+
+    /// Creates a 2D vector from the `x` and `y` elements of `self`, discarding `z`.
+    ///
+    /// Truncation may also be performed by using [`self.xy()`][crate::swizzles::Vec3Swizzles::xy()].
+    #[inline]
+    #[must_use]
+    pub fn truncate(self) -> U64Vec2 {
+        use crate::swizzles::Vec3Swizzles;
+        self.xy()
+    }
+
+    /// Computes the dot product of `self` and `rhs`.
+    #[inline]
+    #[must_use]
+    pub fn dot(self, rhs: Self) -> u64 {
+        (self.x * rhs.x) + (self.y * rhs.y) + (self.z * rhs.z)
+    }
+
+    /// Returns a vector where every component is the dot product of `self` and `rhs`.
+    #[inline]
+    #[must_use]
+    pub fn dot_into_vec(self, rhs: Self) -> Self {
+        Self::splat(self.dot(rhs))
+    }
+
+    /// Computes the cross product of `self` and `rhs`.
+    #[inline]
+    #[must_use]
+    pub fn cross(self, rhs: Self) -> Self {
+        Self {
+            x: self.y * rhs.z - rhs.y * self.z,
+            y: self.z * rhs.x - rhs.z * self.x,
+            z: self.x * rhs.y - rhs.x * self.y,
+        }
+    }
+
+    /// Returns a vector containing the minimum values for each element of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.min(rhs.x), self.y.min(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub fn min(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.min(rhs.x),
+            y: self.y.min(rhs.y),
+            z: self.z.min(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the maximum values for each element of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.max(rhs.x), self.y.max(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub fn max(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.max(rhs.x),
+            y: self.y.max(rhs.y),
+            z: self.z.max(rhs.z),
+        }
+    }
+
+    /// Component-wise clamping of values, similar to [`u64::clamp`].
+    ///
+    /// Each element in `min` must be less-or-equal to the corresponding element in `max`.
+    ///
+    /// # Panics
+    ///
+    /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
+    #[inline]
+    #[must_use]
+    pub fn clamp(self, min: Self, max: Self) -> Self {
+        glam_assert!(min.cmple(max).all(), "clamp: expected min <= max");
+        self.max(min).min(max)
+    }
+
+    /// Returns the horizontal minimum of `self`.
+    ///
+    /// In other words this computes `min(x, y, ..)`.
+    #[inline]
+    #[must_use]
+    pub fn min_element(self) -> u64 {
+        self.x.min(self.y.min(self.z))
+    }
+
+    /// Returns the horizontal maximum of `self`.
+    ///
+    /// In other words this computes `max(x, y, ..)`.
+    #[inline]
+    #[must_use]
+    pub fn max_element(self) -> u64 {
+        self.x.max(self.y.max(self.z))
+    }
+
+    /// Returns a vector mask containing the result of a `==` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words, this computes `[self.x == rhs.x, self.y == rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpeq(self, rhs: Self) -> BVec3 {
+        BVec3::new(self.x.eq(&rhs.x), self.y.eq(&rhs.y), self.z.eq(&rhs.z))
+    }
+
+    /// Returns a vector mask containing the result of a `!=` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x != rhs.x, self.y != rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpne(self, rhs: Self) -> BVec3 {
+        BVec3::new(self.x.ne(&rhs.x), self.y.ne(&rhs.y), self.z.ne(&rhs.z))
+    }
+
+    /// Returns a vector mask containing the result of a `>=` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x >= rhs.x, self.y >= rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpge(self, rhs: Self) -> BVec3 {
+        BVec3::new(self.x.ge(&rhs.x), self.y.ge(&rhs.y), self.z.ge(&rhs.z))
+    }
+
+    /// Returns a vector mask containing the result of a `>` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x > rhs.x, self.y > rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpgt(self, rhs: Self) -> BVec3 {
+        BVec3::new(self.x.gt(&rhs.x), self.y.gt(&rhs.y), self.z.gt(&rhs.z))
+    }
+
+    /// Returns a vector mask containing the result of a `<=` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x <= rhs.x, self.y <= rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmple(self, rhs: Self) -> BVec3 {
+        BVec3::new(self.x.le(&rhs.x), self.y.le(&rhs.y), self.z.le(&rhs.z))
+    }
+
+    /// Returns a vector mask containing the result of a `<` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x < rhs.x, self.y < rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmplt(self, rhs: Self) -> BVec3 {
+        BVec3::new(self.x.lt(&rhs.x), self.y.lt(&rhs.y), self.z.lt(&rhs.z))
+    }
+
+    /// Computes the squared length of `self`.
+    #[doc(alias = "magnitude2")]
+    #[inline]
+    #[must_use]
+    pub fn length_squared(self) -> u64 {
+        self.dot(self)
+    }
+
+    /// Casts all elements of `self` to `f32`.
+    #[inline]
+    #[must_use]
+    pub fn as_vec3(&self) -> crate::Vec3 {
+        crate::Vec3::new(self.x as f32, self.y as f32, self.z as f32)
+    }
+
+    /// Casts all elements of `self` to `f32`.
+    #[inline]
+    #[must_use]
+    pub fn as_vec3a(&self) -> crate::Vec3A {
+        crate::Vec3A::new(self.x as f32, self.y as f32, self.z as f32)
+    }
+
+    /// Casts all elements of `self` to `f64`.
+    #[inline]
+    #[must_use]
+    pub fn as_dvec3(&self) -> crate::DVec3 {
+        crate::DVec3::new(self.x as f64, self.y as f64, self.z as f64)
+    }
+
+    /// Casts all elements of `self` to `i16`.
+    #[inline]
+    #[must_use]
+    pub fn as_i16vec3(&self) -> crate::I16Vec3 {
+        crate::I16Vec3::new(self.x as i16, self.y as i16, self.z as i16)
+    }
+
+    /// Casts all elements of `self` to `u16`.
+    #[inline]
+    #[must_use]
+    pub fn as_u16vec3(&self) -> crate::U16Vec3 {
+        crate::U16Vec3::new(self.x as u16, self.y as u16, self.z as u16)
+    }
+
+    /// Casts all elements of `self` to `i32`.
+    #[inline]
+    #[must_use]
+    pub fn as_ivec3(&self) -> crate::IVec3 {
+        crate::IVec3::new(self.x as i32, self.y as i32, self.z as i32)
+    }
+
+    /// Casts all elements of `self` to `u32`.
+    #[inline]
+    #[must_use]
+    pub fn as_uvec3(&self) -> crate::UVec3 {
+        crate::UVec3::new(self.x as u32, self.y as u32, self.z as u32)
+    }
+
+    /// Casts all elements of `self` to `i64`.
+    #[inline]
+    #[must_use]
+    pub fn as_i64vec3(&self) -> crate::I64Vec3 {
+        crate::I64Vec3::new(self.x as i64, self.y as i64, self.z as i64)
+    }
+
+    /// Returns a vector containing the wrapping addition of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_add(rhs.x), self.y.wrapping_add(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_add(rhs.x),
+            y: self.y.wrapping_add(rhs.y),
+            z: self.z.wrapping_add(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the wrapping subtraction of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_sub(rhs.x), self.y.wrapping_sub(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_sub(rhs.x),
+            y: self.y.wrapping_sub(rhs.y),
+            z: self.z.wrapping_sub(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the wrapping multiplication of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_mul(rhs.x), self.y.wrapping_mul(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_mul(rhs.x),
+            y: self.y.wrapping_mul(rhs.y),
+            z: self.z.wrapping_mul(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the wrapping division of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_div(rhs.x), self.y.wrapping_div(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_div(rhs.x),
+            y: self.y.wrapping_div(rhs.y),
+            z: self.z.wrapping_div(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the saturating addition of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_add(rhs.x), self.y.saturating_add(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_add(rhs.x),
+            y: self.y.saturating_add(rhs.y),
+            z: self.z.saturating_add(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the saturating subtraction of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_sub(rhs.x), self.y.saturating_sub(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_sub(rhs.x),
+            y: self.y.saturating_sub(rhs.y),
+            z: self.z.saturating_sub(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the saturating multiplication of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_mul(rhs.x), self.y.saturating_mul(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_mul(rhs.x),
+            y: self.y.saturating_mul(rhs.y),
+            z: self.z.saturating_mul(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the saturating division of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_div(rhs.x), self.y.saturating_div(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_div(rhs.x),
+            y: self.y.saturating_div(rhs.y),
+            z: self.z.saturating_div(rhs.z),
+        }
+    }
+}
+
+impl Default for U64Vec3 {
+    #[inline(always)]
+    fn default() -> Self {
+        Self::ZERO
+    }
+}
+
+impl Div<U64Vec3> for U64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.div(rhs.x),
+            y: self.y.div(rhs.y),
+            z: self.z.div(rhs.z),
+        }
+    }
+}
+
+impl DivAssign<U64Vec3> for U64Vec3 {
+    #[inline]
+    fn div_assign(&mut self, rhs: Self) {
+        self.x.div_assign(rhs.x);
+        self.y.div_assign(rhs.y);
+        self.z.div_assign(rhs.z);
+    }
+}
+
+impl Div<u64> for U64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn div(self, rhs: u64) -> Self {
+        Self {
+            x: self.x.div(rhs),
+            y: self.y.div(rhs),
+            z: self.z.div(rhs),
+        }
+    }
+}
+
+impl DivAssign<u64> for U64Vec3 {
+    #[inline]
+    fn div_assign(&mut self, rhs: u64) {
+        self.x.div_assign(rhs);
+        self.y.div_assign(rhs);
+        self.z.div_assign(rhs);
+    }
+}
+
+impl Div<U64Vec3> for u64 {
+    type Output = U64Vec3;
+    #[inline]
+    fn div(self, rhs: U64Vec3) -> U64Vec3 {
+        U64Vec3 {
+            x: self.div(rhs.x),
+            y: self.div(rhs.y),
+            z: self.div(rhs.z),
+        }
+    }
+}
+
+impl Mul<U64Vec3> for U64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.mul(rhs.x),
+            y: self.y.mul(rhs.y),
+            z: self.z.mul(rhs.z),
+        }
+    }
+}
+
+impl MulAssign<U64Vec3> for U64Vec3 {
+    #[inline]
+    fn mul_assign(&mut self, rhs: Self) {
+        self.x.mul_assign(rhs.x);
+        self.y.mul_assign(rhs.y);
+        self.z.mul_assign(rhs.z);
+    }
+}
+
+impl Mul<u64> for U64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn mul(self, rhs: u64) -> Self {
+        Self {
+            x: self.x.mul(rhs),
+            y: self.y.mul(rhs),
+            z: self.z.mul(rhs),
+        }
+    }
+}
+
+impl MulAssign<u64> for U64Vec3 {
+    #[inline]
+    fn mul_assign(&mut self, rhs: u64) {
+        self.x.mul_assign(rhs);
+        self.y.mul_assign(rhs);
+        self.z.mul_assign(rhs);
+    }
+}
+
+impl Mul<U64Vec3> for u64 {
+    type Output = U64Vec3;
+    #[inline]
+    fn mul(self, rhs: U64Vec3) -> U64Vec3 {
+        U64Vec3 {
+            x: self.mul(rhs.x),
+            y: self.mul(rhs.y),
+            z: self.mul(rhs.z),
+        }
+    }
+}
+
+impl Add<U64Vec3> for U64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.add(rhs.x),
+            y: self.y.add(rhs.y),
+            z: self.z.add(rhs.z),
+        }
+    }
+}
+
+impl AddAssign<U64Vec3> for U64Vec3 {
+    #[inline]
+    fn add_assign(&mut self, rhs: Self) {
+        self.x.add_assign(rhs.x);
+        self.y.add_assign(rhs.y);
+        self.z.add_assign(rhs.z);
+    }
+}
+
+impl Add<u64> for U64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn add(self, rhs: u64) -> Self {
+        Self {
+            x: self.x.add(rhs),
+            y: self.y.add(rhs),
+            z: self.z.add(rhs),
+        }
+    }
+}
+
+impl AddAssign<u64> for U64Vec3 {
+    #[inline]
+    fn add_assign(&mut self, rhs: u64) {
+        self.x.add_assign(rhs);
+        self.y.add_assign(rhs);
+        self.z.add_assign(rhs);
+    }
+}
+
+impl Add<U64Vec3> for u64 {
+    type Output = U64Vec3;
+    #[inline]
+    fn add(self, rhs: U64Vec3) -> U64Vec3 {
+        U64Vec3 {
+            x: self.add(rhs.x),
+            y: self.add(rhs.y),
+            z: self.add(rhs.z),
+        }
+    }
+}
+
+impl Sub<U64Vec3> for U64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.sub(rhs.x),
+            y: self.y.sub(rhs.y),
+            z: self.z.sub(rhs.z),
+        }
+    }
+}
+
+impl SubAssign<U64Vec3> for U64Vec3 {
+    #[inline]
+    fn sub_assign(&mut self, rhs: U64Vec3) {
+        self.x.sub_assign(rhs.x);
+        self.y.sub_assign(rhs.y);
+        self.z.sub_assign(rhs.z);
+    }
+}
+
+impl Sub<u64> for U64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn sub(self, rhs: u64) -> Self {
+        Self {
+            x: self.x.sub(rhs),
+            y: self.y.sub(rhs),
+            z: self.z.sub(rhs),
+        }
+    }
+}
+
+impl SubAssign<u64> for U64Vec3 {
+    #[inline]
+    fn sub_assign(&mut self, rhs: u64) {
+        self.x.sub_assign(rhs);
+        self.y.sub_assign(rhs);
+        self.z.sub_assign(rhs);
+    }
+}
+
+impl Sub<U64Vec3> for u64 {
+    type Output = U64Vec3;
+    #[inline]
+    fn sub(self, rhs: U64Vec3) -> U64Vec3 {
+        U64Vec3 {
+            x: self.sub(rhs.x),
+            y: self.sub(rhs.y),
+            z: self.sub(rhs.z),
+        }
+    }
+}
+
+impl Rem<U64Vec3> for U64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn rem(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.rem(rhs.x),
+            y: self.y.rem(rhs.y),
+            z: self.z.rem(rhs.z),
+        }
+    }
+}
+
+impl RemAssign<U64Vec3> for U64Vec3 {
+    #[inline]
+    fn rem_assign(&mut self, rhs: Self) {
+        self.x.rem_assign(rhs.x);
+        self.y.rem_assign(rhs.y);
+        self.z.rem_assign(rhs.z);
+    }
+}
+
+impl Rem<u64> for U64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn rem(self, rhs: u64) -> Self {
+        Self {
+            x: self.x.rem(rhs),
+            y: self.y.rem(rhs),
+            z: self.z.rem(rhs),
+        }
+    }
+}
+
+impl RemAssign<u64> for U64Vec3 {
+    #[inline]
+    fn rem_assign(&mut self, rhs: u64) {
+        self.x.rem_assign(rhs);
+        self.y.rem_assign(rhs);
+        self.z.rem_assign(rhs);
+    }
+}
+
+impl Rem<U64Vec3> for u64 {
+    type Output = U64Vec3;
+    #[inline]
+    fn rem(self, rhs: U64Vec3) -> U64Vec3 {
+        U64Vec3 {
+            x: self.rem(rhs.x),
+            y: self.rem(rhs.y),
+            z: self.rem(rhs.z),
+        }
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl AsRef<[u64; 3]> for U64Vec3 {
+    #[inline]
+    fn as_ref(&self) -> &[u64; 3] {
+        unsafe { &*(self as *const U64Vec3 as *const [u64; 3]) }
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl AsMut<[u64; 3]> for U64Vec3 {
+    #[inline]
+    fn as_mut(&mut self) -> &mut [u64; 3] {
+        unsafe { &mut *(self as *mut U64Vec3 as *mut [u64; 3]) }
+    }
+}
+
+impl Sum for U64Vec3 {
+    #[inline]
+    fn sum<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = Self>,
+    {
+        iter.fold(Self::ZERO, Self::add)
+    }
+}
+
+impl<'a> Sum<&'a Self> for U64Vec3 {
+    #[inline]
+    fn sum<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = &'a Self>,
+    {
+        iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
+    }
+}
+
+impl Product for U64Vec3 {
+    #[inline]
+    fn product<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = Self>,
+    {
+        iter.fold(Self::ONE, Self::mul)
+    }
+}
+
+impl<'a> Product<&'a Self> for U64Vec3 {
+    #[inline]
+    fn product<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = &'a Self>,
+    {
+        iter.fold(Self::ONE, |a, &b| Self::mul(a, b))
+    }
+}
+
+impl Not for U64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn not(self) -> Self::Output {
+        Self {
+            x: self.x.not(),
+            y: self.y.not(),
+            z: self.z.not(),
+        }
+    }
+}
+
+impl BitAnd for U64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn bitand(self, rhs: Self) -> Self::Output {
+        Self {
+            x: self.x.bitand(rhs.x),
+            y: self.y.bitand(rhs.y),
+            z: self.z.bitand(rhs.z),
+        }
+    }
+}
+
+impl BitOr for U64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn bitor(self, rhs: Self) -> Self::Output {
+        Self {
+            x: self.x.bitor(rhs.x),
+            y: self.y.bitor(rhs.y),
+            z: self.z.bitor(rhs.z),
+        }
+    }
+}
+
+impl BitXor for U64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn bitxor(self, rhs: Self) -> Self::Output {
+        Self {
+            x: self.x.bitxor(rhs.x),
+            y: self.y.bitxor(rhs.y),
+            z: self.z.bitxor(rhs.z),
+        }
+    }
+}
+
+impl BitAnd<u64> for U64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn bitand(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.bitand(rhs),
+            y: self.y.bitand(rhs),
+            z: self.z.bitand(rhs),
+        }
+    }
+}
+
+impl BitOr<u64> for U64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn bitor(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.bitor(rhs),
+            y: self.y.bitor(rhs),
+            z: self.z.bitor(rhs),
+        }
+    }
+}
+
+impl BitXor<u64> for U64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn bitxor(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.bitxor(rhs),
+            y: self.y.bitxor(rhs),
+            z: self.z.bitxor(rhs),
+        }
+    }
+}
+
+impl Shl<i8> for U64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i8) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i8> for U64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i8) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+        }
+    }
+}
+
+impl Shl<i16> for U64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i16) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i16> for U64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i16) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+        }
+    }
+}
+
+impl Shl<i32> for U64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i32) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i32> for U64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i32) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+        }
+    }
+}
+
+impl Shl<i64> for U64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i64> for U64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u8> for U64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u8) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u8> for U64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u8) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u16> for U64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u16) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u16> for U64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u16) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u32> for U64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u32) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u32> for U64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u32) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u64> for U64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u64> for U64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+        }
+    }
+}
+
+impl Shl<crate::IVec3> for U64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: crate::IVec3) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs.x),
+            y: self.y.shl(rhs.y),
+            z: self.z.shl(rhs.z),
+        }
+    }
+}
+
+impl Shr<crate::IVec3> for U64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: crate::IVec3) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs.x),
+            y: self.y.shr(rhs.y),
+            z: self.z.shr(rhs.z),
+        }
+    }
+}
+
+impl Shl<crate::UVec3> for U64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: crate::UVec3) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs.x),
+            y: self.y.shl(rhs.y),
+            z: self.z.shl(rhs.z),
+        }
+    }
+}
+
+impl Shr<crate::UVec3> for U64Vec3 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: crate::UVec3) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs.x),
+            y: self.y.shr(rhs.y),
+            z: self.z.shr(rhs.z),
+        }
+    }
+}
+
+impl Index<usize> for U64Vec3 {
+    type Output = u64;
+    #[inline]
+    fn index(&self, index: usize) -> &Self::Output {
+        match index {
+            0 => &self.x,
+            1 => &self.y,
+            2 => &self.z,
+            _ => panic!("index out of bounds"),
+        }
+    }
+}
+
+impl IndexMut<usize> for U64Vec3 {
+    #[inline]
+    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
+        match index {
+            0 => &mut self.x,
+            1 => &mut self.y,
+            2 => &mut self.z,
+            _ => panic!("index out of bounds"),
+        }
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl fmt::Display for U64Vec3 {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "[{}, {}, {}]", self.x, self.y, self.z)
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl fmt::Debug for U64Vec3 {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt.debug_tuple(stringify!(U64Vec3))
+            .field(&self.x)
+            .field(&self.y)
+            .field(&self.z)
+            .finish()
+    }
+}
+
+impl From<[u64; 3]> for U64Vec3 {
+    #[inline]
+    fn from(a: [u64; 3]) -> Self {
+        Self::new(a[0], a[1], a[2])
+    }
+}
+
+impl From<U64Vec3> for [u64; 3] {
+    #[inline]
+    fn from(v: U64Vec3) -> Self {
+        [v.x, v.y, v.z]
+    }
+}
+
+impl From<(u64, u64, u64)> for U64Vec3 {
+    #[inline]
+    fn from(t: (u64, u64, u64)) -> Self {
+        Self::new(t.0, t.1, t.2)
+    }
+}
+
+impl From<U64Vec3> for (u64, u64, u64) {
+    #[inline]
+    fn from(v: U64Vec3) -> Self {
+        (v.x, v.y, v.z)
+    }
+}
+
+impl From<(U64Vec2, u64)> for U64Vec3 {
+    #[inline]
+    fn from((v, z): (U64Vec2, u64)) -> Self {
+        Self::new(v.x, v.y, z)
+    }
+}
+
+impl From<U16Vec3> for U64Vec3 {
+    #[inline]
+    fn from(v: U16Vec3) -> Self {
+        Self::new(u64::from(v.x), u64::from(v.y), u64::from(v.z))
+    }
+}
+
+impl From<UVec3> for U64Vec3 {
+    #[inline]
+    fn from(v: UVec3) -> Self {
+        Self::new(u64::from(v.x), u64::from(v.y), u64::from(v.z))
+    }
+}
+
+impl TryFrom<I16Vec3> for U64Vec3 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: I16Vec3) -> Result<Self, Self::Error> {
+        Ok(Self::new(
+            u64::try_from(v.x)?,
+            u64::try_from(v.y)?,
+            u64::try_from(v.z)?,
+        ))
+    }
+}
+
+impl TryFrom<IVec3> for U64Vec3 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: IVec3) -> Result<Self, Self::Error> {
+        Ok(Self::new(
+            u64::try_from(v.x)?,
+            u64::try_from(v.y)?,
+            u64::try_from(v.z)?,
+        ))
+    }
+}
+
+impl TryFrom<I64Vec3> for U64Vec3 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: I64Vec3) -> Result<Self, Self::Error> {
+        Ok(Self::new(
+            u64::try_from(v.x)?,
+            u64::try_from(v.y)?,
+            u64::try_from(v.z)?,
+        ))
+    }
+}
diff --git a/src/u64/u64vec4.rs b/src/u64/u64vec4.rs
new file mode 100644
index 0000000..91df699
--- /dev/null
+++ b/src/u64/u64vec4.rs
@@ -0,0 +1,1359 @@
+// Generated from vec.rs.tera template. Edit the template, not the generated file.
+
+use crate::{BVec4, I16Vec4, I64Vec4, IVec4, U16Vec4, U64Vec2, U64Vec3, UVec4};
+
+#[cfg(not(target_arch = "spirv"))]
+use core::fmt;
+use core::iter::{Product, Sum};
+use core::{f32, ops::*};
+
+/// Creates a 4-dimensional vector.
+#[inline(always)]
+#[must_use]
+pub const fn u64vec4(x: u64, y: u64, z: u64, w: u64) -> U64Vec4 {
+    U64Vec4::new(x, y, z, w)
+}
+
+/// A 4-dimensional vector.
+#[cfg_attr(not(target_arch = "spirv"), derive(Hash))]
+#[derive(Clone, Copy, PartialEq, Eq)]
+#[cfg_attr(feature = "cuda", repr(align(16)))]
+#[cfg_attr(not(target_arch = "spirv"), repr(C))]
+#[cfg_attr(target_arch = "spirv", repr(simd))]
+pub struct U64Vec4 {
+    pub x: u64,
+    pub y: u64,
+    pub z: u64,
+    pub w: u64,
+}
+
+impl U64Vec4 {
+    /// All zeroes.
+    pub const ZERO: Self = Self::splat(0);
+
+    /// All ones.
+    pub const ONE: Self = Self::splat(1);
+
+    /// All `u64::MIN`.
+    pub const MIN: Self = Self::splat(u64::MIN);
+
+    /// All `u64::MAX`.
+    pub const MAX: Self = Self::splat(u64::MAX);
+
+    /// A unit vector pointing along the positive X axis.
+    pub const X: Self = Self::new(1, 0, 0, 0);
+
+    /// A unit vector pointing along the positive Y axis.
+    pub const Y: Self = Self::new(0, 1, 0, 0);
+
+    /// A unit vector pointing along the positive Z axis.
+    pub const Z: Self = Self::new(0, 0, 1, 0);
+
+    /// A unit vector pointing along the positive W axis.
+    pub const W: Self = Self::new(0, 0, 0, 1);
+
+    /// The unit axes.
+    pub const AXES: [Self; 4] = [Self::X, Self::Y, Self::Z, Self::W];
+
+    /// Creates a new vector.
+    #[inline(always)]
+    #[must_use]
+    pub const fn new(x: u64, y: u64, z: u64, w: u64) -> Self {
+        Self { x, y, z, w }
+    }
+
+    /// Creates a vector with all elements set to `v`.
+    #[inline]
+    #[must_use]
+    pub const fn splat(v: u64) -> Self {
+        Self {
+            x: v,
+
+            y: v,
+
+            z: v,
+
+            w: v,
+        }
+    }
+
+    /// Creates a vector from the elements in `if_true` and `if_false`, selecting which to use
+    /// for each element of `self`.
+    ///
+    /// A true element in the mask uses the corresponding element from `if_true`, and false
+    /// uses the element from `if_false`.
+    #[inline]
+    #[must_use]
+    pub fn select(mask: BVec4, if_true: Self, if_false: Self) -> Self {
+        Self {
+            x: if mask.test(0) { if_true.x } else { if_false.x },
+            y: if mask.test(1) { if_true.y } else { if_false.y },
+            z: if mask.test(2) { if_true.z } else { if_false.z },
+            w: if mask.test(3) { if_true.w } else { if_false.w },
+        }
+    }
+
+    /// Creates a new vector from an array.
+    #[inline]
+    #[must_use]
+    pub const fn from_array(a: [u64; 4]) -> Self {
+        Self::new(a[0], a[1], a[2], a[3])
+    }
+
+    /// `[x, y, z, w]`
+    #[inline]
+    #[must_use]
+    pub const fn to_array(&self) -> [u64; 4] {
+        [self.x, self.y, self.z, self.w]
+    }
+
+    /// Creates a vector from the first 4 values in `slice`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `slice` is less than 4 elements long.
+    #[inline]
+    #[must_use]
+    pub const fn from_slice(slice: &[u64]) -> Self {
+        Self::new(slice[0], slice[1], slice[2], slice[3])
+    }
+
+    /// Writes the elements of `self` to the first 4 elements in `slice`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `slice` is less than 4 elements long.
+    #[inline]
+    pub fn write_to_slice(self, slice: &mut [u64]) {
+        slice[0] = self.x;
+        slice[1] = self.y;
+        slice[2] = self.z;
+        slice[3] = self.w;
+    }
+
+    /// Creates a 3D vector from the `x`, `y` and `z` elements of `self`, discarding `w`.
+    ///
+    /// Truncation to [`U64Vec3`] may also be performed by using [`self.xyz()`][crate::swizzles::Vec4Swizzles::xyz()].
+    #[inline]
+    #[must_use]
+    pub fn truncate(self) -> U64Vec3 {
+        use crate::swizzles::Vec4Swizzles;
+        self.xyz()
+    }
+
+    /// Computes the dot product of `self` and `rhs`.
+    #[inline]
+    #[must_use]
+    pub fn dot(self, rhs: Self) -> u64 {
+        (self.x * rhs.x) + (self.y * rhs.y) + (self.z * rhs.z) + (self.w * rhs.w)
+    }
+
+    /// Returns a vector where every component is the dot product of `self` and `rhs`.
+    #[inline]
+    #[must_use]
+    pub fn dot_into_vec(self, rhs: Self) -> Self {
+        Self::splat(self.dot(rhs))
+    }
+
+    /// Returns a vector containing the minimum values for each element of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.min(rhs.x), self.y.min(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub fn min(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.min(rhs.x),
+            y: self.y.min(rhs.y),
+            z: self.z.min(rhs.z),
+            w: self.w.min(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the maximum values for each element of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.max(rhs.x), self.y.max(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub fn max(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.max(rhs.x),
+            y: self.y.max(rhs.y),
+            z: self.z.max(rhs.z),
+            w: self.w.max(rhs.w),
+        }
+    }
+
+    /// Component-wise clamping of values, similar to [`u64::clamp`].
+    ///
+    /// Each element in `min` must be less-or-equal to the corresponding element in `max`.
+    ///
+    /// # Panics
+    ///
+    /// Will panic if `min` is greater than `max` when `glam_assert` is enabled.
+    #[inline]
+    #[must_use]
+    pub fn clamp(self, min: Self, max: Self) -> Self {
+        glam_assert!(min.cmple(max).all(), "clamp: expected min <= max");
+        self.max(min).min(max)
+    }
+
+    /// Returns the horizontal minimum of `self`.
+    ///
+    /// In other words this computes `min(x, y, ..)`.
+    #[inline]
+    #[must_use]
+    pub fn min_element(self) -> u64 {
+        self.x.min(self.y.min(self.z.min(self.w)))
+    }
+
+    /// Returns the horizontal maximum of `self`.
+    ///
+    /// In other words this computes `max(x, y, ..)`.
+    #[inline]
+    #[must_use]
+    pub fn max_element(self) -> u64 {
+        self.x.max(self.y.max(self.z.max(self.w)))
+    }
+
+    /// Returns a vector mask containing the result of a `==` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words, this computes `[self.x == rhs.x, self.y == rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpeq(self, rhs: Self) -> BVec4 {
+        BVec4::new(
+            self.x.eq(&rhs.x),
+            self.y.eq(&rhs.y),
+            self.z.eq(&rhs.z),
+            self.w.eq(&rhs.w),
+        )
+    }
+
+    /// Returns a vector mask containing the result of a `!=` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x != rhs.x, self.y != rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpne(self, rhs: Self) -> BVec4 {
+        BVec4::new(
+            self.x.ne(&rhs.x),
+            self.y.ne(&rhs.y),
+            self.z.ne(&rhs.z),
+            self.w.ne(&rhs.w),
+        )
+    }
+
+    /// Returns a vector mask containing the result of a `>=` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x >= rhs.x, self.y >= rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpge(self, rhs: Self) -> BVec4 {
+        BVec4::new(
+            self.x.ge(&rhs.x),
+            self.y.ge(&rhs.y),
+            self.z.ge(&rhs.z),
+            self.w.ge(&rhs.w),
+        )
+    }
+
+    /// Returns a vector mask containing the result of a `>` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x > rhs.x, self.y > rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmpgt(self, rhs: Self) -> BVec4 {
+        BVec4::new(
+            self.x.gt(&rhs.x),
+            self.y.gt(&rhs.y),
+            self.z.gt(&rhs.z),
+            self.w.gt(&rhs.w),
+        )
+    }
+
+    /// Returns a vector mask containing the result of a `<=` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x <= rhs.x, self.y <= rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmple(self, rhs: Self) -> BVec4 {
+        BVec4::new(
+            self.x.le(&rhs.x),
+            self.y.le(&rhs.y),
+            self.z.le(&rhs.z),
+            self.w.le(&rhs.w),
+        )
+    }
+
+    /// Returns a vector mask containing the result of a `<` comparison for each element of
+    /// `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x < rhs.x, self.y < rhs.y, ..]` for all
+    /// elements.
+    #[inline]
+    #[must_use]
+    pub fn cmplt(self, rhs: Self) -> BVec4 {
+        BVec4::new(
+            self.x.lt(&rhs.x),
+            self.y.lt(&rhs.y),
+            self.z.lt(&rhs.z),
+            self.w.lt(&rhs.w),
+        )
+    }
+
+    /// Computes the squared length of `self`.
+    #[doc(alias = "magnitude2")]
+    #[inline]
+    #[must_use]
+    pub fn length_squared(self) -> u64 {
+        self.dot(self)
+    }
+
+    /// Casts all elements of `self` to `f32`.
+    #[inline]
+    #[must_use]
+    pub fn as_vec4(&self) -> crate::Vec4 {
+        crate::Vec4::new(self.x as f32, self.y as f32, self.z as f32, self.w as f32)
+    }
+
+    /// Casts all elements of `self` to `f64`.
+    #[inline]
+    #[must_use]
+    pub fn as_dvec4(&self) -> crate::DVec4 {
+        crate::DVec4::new(self.x as f64, self.y as f64, self.z as f64, self.w as f64)
+    }
+
+    /// Casts all elements of `self` to `i16`.
+    #[inline]
+    #[must_use]
+    pub fn as_i16vec4(&self) -> crate::I16Vec4 {
+        crate::I16Vec4::new(self.x as i16, self.y as i16, self.z as i16, self.w as i16)
+    }
+
+    /// Casts all elements of `self` to `u16`.
+    #[inline]
+    #[must_use]
+    pub fn as_u16vec4(&self) -> crate::U16Vec4 {
+        crate::U16Vec4::new(self.x as u16, self.y as u16, self.z as u16, self.w as u16)
+    }
+
+    /// Casts all elements of `self` to `i32`.
+    #[inline]
+    #[must_use]
+    pub fn as_ivec4(&self) -> crate::IVec4 {
+        crate::IVec4::new(self.x as i32, self.y as i32, self.z as i32, self.w as i32)
+    }
+
+    /// Casts all elements of `self` to `u32`.
+    #[inline]
+    #[must_use]
+    pub fn as_uvec4(&self) -> crate::UVec4 {
+        crate::UVec4::new(self.x as u32, self.y as u32, self.z as u32, self.w as u32)
+    }
+
+    /// Casts all elements of `self` to `i64`.
+    #[inline]
+    #[must_use]
+    pub fn as_i64vec4(&self) -> crate::I64Vec4 {
+        crate::I64Vec4::new(self.x as i64, self.y as i64, self.z as i64, self.w as i64)
+    }
+
+    /// Returns a vector containing the wrapping addition of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_add(rhs.x), self.y.wrapping_add(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_add(rhs.x),
+            y: self.y.wrapping_add(rhs.y),
+            z: self.z.wrapping_add(rhs.z),
+            w: self.w.wrapping_add(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the wrapping subtraction of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_sub(rhs.x), self.y.wrapping_sub(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_sub(rhs.x),
+            y: self.y.wrapping_sub(rhs.y),
+            z: self.z.wrapping_sub(rhs.z),
+            w: self.w.wrapping_sub(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the wrapping multiplication of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_mul(rhs.x), self.y.wrapping_mul(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_mul(rhs.x),
+            y: self.y.wrapping_mul(rhs.y),
+            z: self.z.wrapping_mul(rhs.z),
+            w: self.w.wrapping_mul(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the wrapping division of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_div(rhs.x), self.y.wrapping_div(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.wrapping_div(rhs.x),
+            y: self.y.wrapping_div(rhs.y),
+            z: self.z.wrapping_div(rhs.z),
+            w: self.w.wrapping_div(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the saturating addition of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_add(rhs.x), self.y.saturating_add(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_add(rhs.x),
+            y: self.y.saturating_add(rhs.y),
+            z: self.z.saturating_add(rhs.z),
+            w: self.w.saturating_add(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the saturating subtraction of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_sub(rhs.x), self.y.saturating_sub(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_sub(rhs.x),
+            y: self.y.saturating_sub(rhs.y),
+            z: self.z.saturating_sub(rhs.z),
+            w: self.w.saturating_sub(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the saturating multiplication of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_mul(rhs.x), self.y.saturating_mul(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_mul(rhs.x),
+            y: self.y.saturating_mul(rhs.y),
+            z: self.z.saturating_mul(rhs.z),
+            w: self.w.saturating_mul(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the saturating division of `self` and `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_div(rhs.x), self.y.saturating_div(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.saturating_div(rhs.x),
+            y: self.y.saturating_div(rhs.y),
+            z: self.z.saturating_div(rhs.z),
+            w: self.w.saturating_div(rhs.w),
+        }
+    }
+}
+
+impl Default for U64Vec4 {
+    #[inline(always)]
+    fn default() -> Self {
+        Self::ZERO
+    }
+}
+
+impl Div<U64Vec4> for U64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn div(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.div(rhs.x),
+            y: self.y.div(rhs.y),
+            z: self.z.div(rhs.z),
+            w: self.w.div(rhs.w),
+        }
+    }
+}
+
+impl DivAssign<U64Vec4> for U64Vec4 {
+    #[inline]
+    fn div_assign(&mut self, rhs: Self) {
+        self.x.div_assign(rhs.x);
+        self.y.div_assign(rhs.y);
+        self.z.div_assign(rhs.z);
+        self.w.div_assign(rhs.w);
+    }
+}
+
+impl Div<u64> for U64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn div(self, rhs: u64) -> Self {
+        Self {
+            x: self.x.div(rhs),
+            y: self.y.div(rhs),
+            z: self.z.div(rhs),
+            w: self.w.div(rhs),
+        }
+    }
+}
+
+impl DivAssign<u64> for U64Vec4 {
+    #[inline]
+    fn div_assign(&mut self, rhs: u64) {
+        self.x.div_assign(rhs);
+        self.y.div_assign(rhs);
+        self.z.div_assign(rhs);
+        self.w.div_assign(rhs);
+    }
+}
+
+impl Div<U64Vec4> for u64 {
+    type Output = U64Vec4;
+    #[inline]
+    fn div(self, rhs: U64Vec4) -> U64Vec4 {
+        U64Vec4 {
+            x: self.div(rhs.x),
+            y: self.div(rhs.y),
+            z: self.div(rhs.z),
+            w: self.div(rhs.w),
+        }
+    }
+}
+
+impl Mul<U64Vec4> for U64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn mul(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.mul(rhs.x),
+            y: self.y.mul(rhs.y),
+            z: self.z.mul(rhs.z),
+            w: self.w.mul(rhs.w),
+        }
+    }
+}
+
+impl MulAssign<U64Vec4> for U64Vec4 {
+    #[inline]
+    fn mul_assign(&mut self, rhs: Self) {
+        self.x.mul_assign(rhs.x);
+        self.y.mul_assign(rhs.y);
+        self.z.mul_assign(rhs.z);
+        self.w.mul_assign(rhs.w);
+    }
+}
+
+impl Mul<u64> for U64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn mul(self, rhs: u64) -> Self {
+        Self {
+            x: self.x.mul(rhs),
+            y: self.y.mul(rhs),
+            z: self.z.mul(rhs),
+            w: self.w.mul(rhs),
+        }
+    }
+}
+
+impl MulAssign<u64> for U64Vec4 {
+    #[inline]
+    fn mul_assign(&mut self, rhs: u64) {
+        self.x.mul_assign(rhs);
+        self.y.mul_assign(rhs);
+        self.z.mul_assign(rhs);
+        self.w.mul_assign(rhs);
+    }
+}
+
+impl Mul<U64Vec4> for u64 {
+    type Output = U64Vec4;
+    #[inline]
+    fn mul(self, rhs: U64Vec4) -> U64Vec4 {
+        U64Vec4 {
+            x: self.mul(rhs.x),
+            y: self.mul(rhs.y),
+            z: self.mul(rhs.z),
+            w: self.mul(rhs.w),
+        }
+    }
+}
+
+impl Add<U64Vec4> for U64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn add(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.add(rhs.x),
+            y: self.y.add(rhs.y),
+            z: self.z.add(rhs.z),
+            w: self.w.add(rhs.w),
+        }
+    }
+}
+
+impl AddAssign<U64Vec4> for U64Vec4 {
+    #[inline]
+    fn add_assign(&mut self, rhs: Self) {
+        self.x.add_assign(rhs.x);
+        self.y.add_assign(rhs.y);
+        self.z.add_assign(rhs.z);
+        self.w.add_assign(rhs.w);
+    }
+}
+
+impl Add<u64> for U64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn add(self, rhs: u64) -> Self {
+        Self {
+            x: self.x.add(rhs),
+            y: self.y.add(rhs),
+            z: self.z.add(rhs),
+            w: self.w.add(rhs),
+        }
+    }
+}
+
+impl AddAssign<u64> for U64Vec4 {
+    #[inline]
+    fn add_assign(&mut self, rhs: u64) {
+        self.x.add_assign(rhs);
+        self.y.add_assign(rhs);
+        self.z.add_assign(rhs);
+        self.w.add_assign(rhs);
+    }
+}
+
+impl Add<U64Vec4> for u64 {
+    type Output = U64Vec4;
+    #[inline]
+    fn add(self, rhs: U64Vec4) -> U64Vec4 {
+        U64Vec4 {
+            x: self.add(rhs.x),
+            y: self.add(rhs.y),
+            z: self.add(rhs.z),
+            w: self.add(rhs.w),
+        }
+    }
+}
+
+impl Sub<U64Vec4> for U64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn sub(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.sub(rhs.x),
+            y: self.y.sub(rhs.y),
+            z: self.z.sub(rhs.z),
+            w: self.w.sub(rhs.w),
+        }
+    }
+}
+
+impl SubAssign<U64Vec4> for U64Vec4 {
+    #[inline]
+    fn sub_assign(&mut self, rhs: U64Vec4) {
+        self.x.sub_assign(rhs.x);
+        self.y.sub_assign(rhs.y);
+        self.z.sub_assign(rhs.z);
+        self.w.sub_assign(rhs.w);
+    }
+}
+
+impl Sub<u64> for U64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn sub(self, rhs: u64) -> Self {
+        Self {
+            x: self.x.sub(rhs),
+            y: self.y.sub(rhs),
+            z: self.z.sub(rhs),
+            w: self.w.sub(rhs),
+        }
+    }
+}
+
+impl SubAssign<u64> for U64Vec4 {
+    #[inline]
+    fn sub_assign(&mut self, rhs: u64) {
+        self.x.sub_assign(rhs);
+        self.y.sub_assign(rhs);
+        self.z.sub_assign(rhs);
+        self.w.sub_assign(rhs);
+    }
+}
+
+impl Sub<U64Vec4> for u64 {
+    type Output = U64Vec4;
+    #[inline]
+    fn sub(self, rhs: U64Vec4) -> U64Vec4 {
+        U64Vec4 {
+            x: self.sub(rhs.x),
+            y: self.sub(rhs.y),
+            z: self.sub(rhs.z),
+            w: self.sub(rhs.w),
+        }
+    }
+}
+
+impl Rem<U64Vec4> for U64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn rem(self, rhs: Self) -> Self {
+        Self {
+            x: self.x.rem(rhs.x),
+            y: self.y.rem(rhs.y),
+            z: self.z.rem(rhs.z),
+            w: self.w.rem(rhs.w),
+        }
+    }
+}
+
+impl RemAssign<U64Vec4> for U64Vec4 {
+    #[inline]
+    fn rem_assign(&mut self, rhs: Self) {
+        self.x.rem_assign(rhs.x);
+        self.y.rem_assign(rhs.y);
+        self.z.rem_assign(rhs.z);
+        self.w.rem_assign(rhs.w);
+    }
+}
+
+impl Rem<u64> for U64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn rem(self, rhs: u64) -> Self {
+        Self {
+            x: self.x.rem(rhs),
+            y: self.y.rem(rhs),
+            z: self.z.rem(rhs),
+            w: self.w.rem(rhs),
+        }
+    }
+}
+
+impl RemAssign<u64> for U64Vec4 {
+    #[inline]
+    fn rem_assign(&mut self, rhs: u64) {
+        self.x.rem_assign(rhs);
+        self.y.rem_assign(rhs);
+        self.z.rem_assign(rhs);
+        self.w.rem_assign(rhs);
+    }
+}
+
+impl Rem<U64Vec4> for u64 {
+    type Output = U64Vec4;
+    #[inline]
+    fn rem(self, rhs: U64Vec4) -> U64Vec4 {
+        U64Vec4 {
+            x: self.rem(rhs.x),
+            y: self.rem(rhs.y),
+            z: self.rem(rhs.z),
+            w: self.rem(rhs.w),
+        }
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl AsRef<[u64; 4]> for U64Vec4 {
+    #[inline]
+    fn as_ref(&self) -> &[u64; 4] {
+        unsafe { &*(self as *const U64Vec4 as *const [u64; 4]) }
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl AsMut<[u64; 4]> for U64Vec4 {
+    #[inline]
+    fn as_mut(&mut self) -> &mut [u64; 4] {
+        unsafe { &mut *(self as *mut U64Vec4 as *mut [u64; 4]) }
+    }
+}
+
+impl Sum for U64Vec4 {
+    #[inline]
+    fn sum<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = Self>,
+    {
+        iter.fold(Self::ZERO, Self::add)
+    }
+}
+
+impl<'a> Sum<&'a Self> for U64Vec4 {
+    #[inline]
+    fn sum<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = &'a Self>,
+    {
+        iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
+    }
+}
+
+impl Product for U64Vec4 {
+    #[inline]
+    fn product<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = Self>,
+    {
+        iter.fold(Self::ONE, Self::mul)
+    }
+}
+
+impl<'a> Product<&'a Self> for U64Vec4 {
+    #[inline]
+    fn product<I>(iter: I) -> Self
+    where
+        I: Iterator<Item = &'a Self>,
+    {
+        iter.fold(Self::ONE, |a, &b| Self::mul(a, b))
+    }
+}
+
+impl Not for U64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn not(self) -> Self::Output {
+        Self {
+            x: self.x.not(),
+            y: self.y.not(),
+            z: self.z.not(),
+            w: self.w.not(),
+        }
+    }
+}
+
+impl BitAnd for U64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn bitand(self, rhs: Self) -> Self::Output {
+        Self {
+            x: self.x.bitand(rhs.x),
+            y: self.y.bitand(rhs.y),
+            z: self.z.bitand(rhs.z),
+            w: self.w.bitand(rhs.w),
+        }
+    }
+}
+
+impl BitOr for U64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn bitor(self, rhs: Self) -> Self::Output {
+        Self {
+            x: self.x.bitor(rhs.x),
+            y: self.y.bitor(rhs.y),
+            z: self.z.bitor(rhs.z),
+            w: self.w.bitor(rhs.w),
+        }
+    }
+}
+
+impl BitXor for U64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn bitxor(self, rhs: Self) -> Self::Output {
+        Self {
+            x: self.x.bitxor(rhs.x),
+            y: self.y.bitxor(rhs.y),
+            z: self.z.bitxor(rhs.z),
+            w: self.w.bitxor(rhs.w),
+        }
+    }
+}
+
+impl BitAnd<u64> for U64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn bitand(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.bitand(rhs),
+            y: self.y.bitand(rhs),
+            z: self.z.bitand(rhs),
+            w: self.w.bitand(rhs),
+        }
+    }
+}
+
+impl BitOr<u64> for U64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn bitor(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.bitor(rhs),
+            y: self.y.bitor(rhs),
+            z: self.z.bitor(rhs),
+            w: self.w.bitor(rhs),
+        }
+    }
+}
+
+impl BitXor<u64> for U64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn bitxor(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.bitxor(rhs),
+            y: self.y.bitxor(rhs),
+            z: self.z.bitxor(rhs),
+            w: self.w.bitxor(rhs),
+        }
+    }
+}
+
+impl Shl<i8> for U64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i8) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+            w: self.w.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i8> for U64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i8) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+            w: self.w.shr(rhs),
+        }
+    }
+}
+
+impl Shl<i16> for U64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i16) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+            w: self.w.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i16> for U64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i16) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+            w: self.w.shr(rhs),
+        }
+    }
+}
+
+impl Shl<i32> for U64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i32) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+            w: self.w.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i32> for U64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i32) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+            w: self.w.shr(rhs),
+        }
+    }
+}
+
+impl Shl<i64> for U64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+            w: self.w.shl(rhs),
+        }
+    }
+}
+
+impl Shr<i64> for U64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: i64) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+            w: self.w.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u8> for U64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u8) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+            w: self.w.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u8> for U64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u8) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+            w: self.w.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u16> for U64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u16) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+            w: self.w.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u16> for U64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u16) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+            w: self.w.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u32> for U64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u32) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+            w: self.w.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u32> for U64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u32) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+            w: self.w.shr(rhs),
+        }
+    }
+}
+
+impl Shl<u64> for U64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs),
+            y: self.y.shl(rhs),
+            z: self.z.shl(rhs),
+            w: self.w.shl(rhs),
+        }
+    }
+}
+
+impl Shr<u64> for U64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: u64) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs),
+            y: self.y.shr(rhs),
+            z: self.z.shr(rhs),
+            w: self.w.shr(rhs),
+        }
+    }
+}
+
+impl Shl<crate::IVec4> for U64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: crate::IVec4) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs.x),
+            y: self.y.shl(rhs.y),
+            z: self.z.shl(rhs.z),
+            w: self.w.shl(rhs.w),
+        }
+    }
+}
+
+impl Shr<crate::IVec4> for U64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: crate::IVec4) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs.x),
+            y: self.y.shr(rhs.y),
+            z: self.z.shr(rhs.z),
+            w: self.w.shr(rhs.w),
+        }
+    }
+}
+
+impl Shl<crate::UVec4> for U64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shl(self, rhs: crate::UVec4) -> Self::Output {
+        Self {
+            x: self.x.shl(rhs.x),
+            y: self.y.shl(rhs.y),
+            z: self.z.shl(rhs.z),
+            w: self.w.shl(rhs.w),
+        }
+    }
+}
+
+impl Shr<crate::UVec4> for U64Vec4 {
+    type Output = Self;
+    #[inline]
+    fn shr(self, rhs: crate::UVec4) -> Self::Output {
+        Self {
+            x: self.x.shr(rhs.x),
+            y: self.y.shr(rhs.y),
+            z: self.z.shr(rhs.z),
+            w: self.w.shr(rhs.w),
+        }
+    }
+}
+
+impl Index<usize> for U64Vec4 {
+    type Output = u64;
+    #[inline]
+    fn index(&self, index: usize) -> &Self::Output {
+        match index {
+            0 => &self.x,
+            1 => &self.y,
+            2 => &self.z,
+            3 => &self.w,
+            _ => panic!("index out of bounds"),
+        }
+    }
+}
+
+impl IndexMut<usize> for U64Vec4 {
+    #[inline]
+    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
+        match index {
+            0 => &mut self.x,
+            1 => &mut self.y,
+            2 => &mut self.z,
+            3 => &mut self.w,
+            _ => panic!("index out of bounds"),
+        }
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl fmt::Display for U64Vec4 {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w)
+    }
+}
+
+#[cfg(not(target_arch = "spirv"))]
+impl fmt::Debug for U64Vec4 {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt.debug_tuple(stringify!(U64Vec4))
+            .field(&self.x)
+            .field(&self.y)
+            .field(&self.z)
+            .field(&self.w)
+            .finish()
+    }
+}
+
+impl From<[u64; 4]> for U64Vec4 {
+    #[inline]
+    fn from(a: [u64; 4]) -> Self {
+        Self::new(a[0], a[1], a[2], a[3])
+    }
+}
+
+impl From<U64Vec4> for [u64; 4] {
+    #[inline]
+    fn from(v: U64Vec4) -> Self {
+        [v.x, v.y, v.z, v.w]
+    }
+}
+
+impl From<(u64, u64, u64, u64)> for U64Vec4 {
+    #[inline]
+    fn from(t: (u64, u64, u64, u64)) -> Self {
+        Self::new(t.0, t.1, t.2, t.3)
+    }
+}
+
+impl From<U64Vec4> for (u64, u64, u64, u64) {
+    #[inline]
+    fn from(v: U64Vec4) -> Self {
+        (v.x, v.y, v.z, v.w)
+    }
+}
+
+impl From<(U64Vec3, u64)> for U64Vec4 {
+    #[inline]
+    fn from((v, w): (U64Vec3, u64)) -> Self {
+        Self::new(v.x, v.y, v.z, w)
+    }
+}
+
+impl From<(u64, U64Vec3)> for U64Vec4 {
+    #[inline]
+    fn from((x, v): (u64, U64Vec3)) -> Self {
+        Self::new(x, v.x, v.y, v.z)
+    }
+}
+
+impl From<(U64Vec2, u64, u64)> for U64Vec4 {
+    #[inline]
+    fn from((v, z, w): (U64Vec2, u64, u64)) -> Self {
+        Self::new(v.x, v.y, z, w)
+    }
+}
+
+impl From<(U64Vec2, U64Vec2)> for U64Vec4 {
+    #[inline]
+    fn from((v, u): (U64Vec2, U64Vec2)) -> Self {
+        Self::new(v.x, v.y, u.x, u.y)
+    }
+}
+
+impl From<U16Vec4> for U64Vec4 {
+    #[inline]
+    fn from(v: U16Vec4) -> Self {
+        Self::new(
+            u64::from(v.x),
+            u64::from(v.y),
+            u64::from(v.z),
+            u64::from(v.w),
+        )
+    }
+}
+
+impl From<UVec4> for U64Vec4 {
+    #[inline]
+    fn from(v: UVec4) -> Self {
+        Self::new(
+            u64::from(v.x),
+            u64::from(v.y),
+            u64::from(v.z),
+            u64::from(v.w),
+        )
+    }
+}
+
+impl TryFrom<I16Vec4> for U64Vec4 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: I16Vec4) -> Result<Self, Self::Error> {
+        Ok(Self::new(
+            u64::try_from(v.x)?,
+            u64::try_from(v.y)?,
+            u64::try_from(v.z)?,
+            u64::try_from(v.w)?,
+        ))
+    }
+}
+
+impl TryFrom<IVec4> for U64Vec4 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: IVec4) -> Result<Self, Self::Error> {
+        Ok(Self::new(
+            u64::try_from(v.x)?,
+            u64::try_from(v.y)?,
+            u64::try_from(v.z)?,
+            u64::try_from(v.w)?,
+        ))
+    }
+}
+
+impl TryFrom<I64Vec4> for U64Vec4 {
+    type Error = core::num::TryFromIntError;
+
+    #[inline]
+    fn try_from(v: I64Vec4) -> Result<Self, Self::Error> {
+        Ok(Self::new(
+            u64::try_from(v.x)?,
+            u64::try_from(v.y)?,
+            u64::try_from(v.z)?,
+            u64::try_from(v.w)?,
+        ))
+    }
+}
diff --git a/tests/affine2.rs b/tests/affine2.rs
index e547dbb..205caa4 100644
--- a/tests/affine2.rs
+++ b/tests/affine2.rs
@@ -147,11 +147,83 @@
             should_glam_assert!({ $affine2::ZERO.inverse() });
         });
 
+        glam_test!(test_affine2_decompose, {
+            // identity
+            let (out_scale, out_rotation, out_translation) =
+                $affine2::IDENTITY.to_scale_angle_translation();
+            assert_approx_eq!($vec2::ONE, out_scale);
+            assert_eq!(out_rotation, 0.0);
+            assert_approx_eq!($vec2::ZERO, out_translation);
+
+            // no scale
+            let in_scale = $vec2::ONE;
+            let in_translation = $vec2::new(-2.0, 4.0);
+            let in_rotation = $t::to_radians(-45.0);
+            let in_mat =
+                $affine2::from_scale_angle_translation(in_scale, in_rotation, in_translation);
+            let (out_scale, out_rotation, out_translation) = in_mat.to_scale_angle_translation();
+            assert_approx_eq!(in_scale, out_scale, 1e-6);
+            assert_approx_eq!(in_rotation, out_rotation);
+            assert_approx_eq!(in_translation, out_translation);
+            assert_approx_eq!(
+                in_mat,
+                $affine2::from_scale_angle_translation(out_scale, out_rotation, out_translation),
+                1e-6
+            );
+
+            // positive scale
+            let in_scale = $vec2::new(1.0, 2.0);
+            let in_mat =
+                $affine2::from_scale_angle_translation(in_scale, in_rotation, in_translation);
+            let (out_scale, out_rotation, out_translation) = in_mat.to_scale_angle_translation();
+            assert_approx_eq!(in_scale, out_scale, 1e-6);
+            assert_approx_eq!(in_rotation, out_rotation);
+            assert_approx_eq!(in_translation, out_translation);
+            assert_approx_eq!(
+                in_mat,
+                $affine2::from_scale_angle_translation(out_scale, out_rotation, out_translation),
+                1e-5
+            );
+
+            // negative scale
+            let in_scale = $vec2::new(-4.0, 1.0);
+            let in_mat =
+                $affine2::from_scale_angle_translation(in_scale, in_rotation, in_translation);
+            let (out_scale, out_rotation, out_translation) = in_mat.to_scale_angle_translation();
+            assert_approx_eq!(in_scale, out_scale, 1e-6);
+            assert_approx_eq!(in_rotation, out_rotation);
+            assert_approx_eq!(in_translation, out_translation);
+            assert_approx_eq!(
+                in_mat,
+                $affine2::from_scale_angle_translation(out_scale, out_rotation, out_translation),
+                1e-5
+            );
+
+            // negative scale
+            let in_scale = $vec2::new(4.0, -1.0);
+            let in_mat =
+                $affine2::from_scale_angle_translation(in_scale, in_rotation, in_translation);
+            let (out_scale, out_rotation, out_translation) = in_mat.to_scale_angle_translation();
+            // out_scale and out_rotation are different but they produce the same matrix
+            // assert_approx_eq!(in_scale, out_scale, 1e-6);
+            // assert_approx_eq!(in_rotation, out_rotation);
+            assert_approx_eq!(in_translation, out_translation);
+            assert_approx_eq!(
+                in_mat,
+                $affine2::from_scale_angle_translation(out_scale, out_rotation, out_translation),
+                1e-6
+            );
+        });
+
         glam_test!(test_affine2_ops, {
             let m0 = $affine2::from_cols_array_2d(&MATRIX2D);
             assert_approx_eq!(m0, m0 * $affine2::IDENTITY);
             assert_approx_eq!(m0, $affine2::IDENTITY * m0);
 
+            let mut m1 = m0;
+            m1 *= $affine2::IDENTITY;
+            assert_approx_eq!(m1, m0);
+
             let mat3 = $mat3::from(m0);
             assert_approx_eq!(mat3, $affine2::IDENTITY * mat3);
             assert_approx_eq!(mat3, mat3 * $affine2::IDENTITY);
@@ -181,10 +253,7 @@
 
         glam_test!(test_product, {
             let ident = $affine2::IDENTITY;
-            assert_eq!(
-                vec![ident, ident].iter().product::<$affine2>(),
-                ident * ident
-            );
+            assert_eq!([ident, ident].iter().product::<$affine2>(), ident * ident);
         });
 
         glam_test!(test_affine2_is_finite, {
diff --git a/tests/affine3.rs b/tests/affine3.rs
index 86d5a53..49c4391 100644
--- a/tests/affine3.rs
+++ b/tests/affine3.rs
@@ -294,6 +294,10 @@
             assert_approx_eq!(m0, m0 * $affine3::IDENTITY);
             assert_approx_eq!(m0, $affine3::IDENTITY * m0);
 
+            let mut m1 = m0;
+            m1 *= $affine3::IDENTITY;
+            assert_approx_eq!(m1, m0);
+
             let mat4 = $mat4::from(m0);
             assert_approx_eq!(mat4, $affine3::IDENTITY * mat4);
             assert_approx_eq!(mat4, mat4 * $affine3::IDENTITY);
@@ -331,10 +335,7 @@
 
         glam_test!(test_product, {
             let ident = $affine3::IDENTITY;
-            assert_eq!(
-                vec![ident, ident].iter().product::<$affine3>(),
-                ident * ident
-            );
+            assert_eq!([ident, ident].iter().product::<$affine3>(), ident * ident);
         });
 
         glam_test!(test_affine3_is_finite, {
diff --git a/tests/euler.rs b/tests/euler.rs
index dc4de53..b2d0726 100644
--- a/tests/euler.rs
+++ b/tests/euler.rs
@@ -1,47 +1,53 @@
 #[macro_use]
 mod support;
 
-/// Helper to calculate the inner angle in the range [0, 2*PI)
-trait AngleDiff {
-    type Output;
-    fn angle_diff(self, other: Self) -> Self::Output;
+/// Helper to get the 'canonical' version of a `Quat`. We define the canonical of quat `q` as:
+/// * `q`, if q.w > epsilon
+/// * `-q`, if q.w < -epsilon
+/// * `(0, 0, 0, 1)` otherwise
+/// The rationale is that q and -q represent the same rotation, and any (_, _, _, 0) respresent no rotation at all.
+trait CanonicalQuat: Copy {
+    fn canonical(self) -> Self;
 }
 
-macro_rules! impl_angle_diff {
-    ($t:ty, $pi:expr) => {
-        impl AngleDiff for $t {
-            type Output = $t;
-            fn angle_diff(self, other: $t) -> $t {
-                const PI2: $t = $pi + $pi;
-                let s = self.rem_euclid(PI2);
-                let o = other.rem_euclid(PI2);
-                if s > o {
-                    (s - o).min(PI2 + o - s)
-                } else {
-                    (o - s).min(PI2 + s - o)
+macro_rules! impl_canonical_quat {
+    ($t:ty) => {
+        impl CanonicalQuat for $t {
+            fn canonical(self) -> Self {
+                match self {
+                    _ if self.w >= 1e-5 => self,
+                    _ if self.w <= -1e-5 => -self,
+                    _ => <$t>::from_xyzw(0.0, 0.0, 0.0, 1.0),
                 }
             }
         }
     };
 }
-impl_angle_diff!(f32, std::f32::consts::PI);
-impl_angle_diff!(f64, std::f64::consts::PI);
 
-macro_rules! assert_approx_angle {
-    ($a:expr, $b:expr, $eps:expr) => {{
-        let (a, b) = ($a, $b);
-        let eps = $eps;
-        let diff = a.angle_diff(b);
-        assert!(
-            diff < $eps,
-            "assertion failed: `(left !== right)` \
-             (left: `{:?}`, right: `{:?}`, expect diff: `{:?}`, real diff: `{:?}`)",
-            a,
-            b,
-            eps,
-            diff
-        );
-    }};
+impl_canonical_quat!(glam::Quat);
+impl_canonical_quat!(glam::DQuat);
+
+/// Helper to set some alternative epsilons based on the floating point type used
+trait EulerEpsilon {
+    /// epsilon for comparing quaterions built from eulers and axis-angles
+    const Q_EPS: f32;
+
+    /// epsilon for comparing quaternion round-tripped through eulers (quat -> euler -> quat)
+    const E_EPS: f32;
+}
+impl EulerEpsilon for f32 {
+    const Q_EPS: f32 = 1e-5;
+
+    // The scalar-math and wasm paths seems to use a particularly bad implementation of the trig functions
+    #[cfg(any(feature = "scalar-math", target_arch = "wasm32"))]
+    const E_EPS: f32 = 2e-4;
+
+    #[cfg(not(any(feature = "scalar-math", target_arch = "wasm32")))]
+    const E_EPS: f32 = 1e-5;
+}
+impl EulerEpsilon for f64 {
+    const Q_EPS: f32 = 1e-8;
+    const E_EPS: f32 = 1e-8;
 }
 
 macro_rules! impl_3axis_test {
@@ -49,9 +55,9 @@
         glam_test!($name, {
             let euler = $euler;
             assert!($U != $W); // First and last axis must be different for three axis
-            for u in (-176..=176).step_by(44) {
-                for v in (-88..=88).step_by(44) {
-                    for w in (-176..=176).step_by(44) {
+            for u in (-180..=180).step_by(15) {
+                for v in (-180..=180).step_by(15) {
+                    for w in (-180..=180).step_by(15) {
                         let u1 = (u as $t).to_radians();
                         let v1 = (v as $t).to_radians();
                         let w1 = (w as $t).to_radians();
@@ -63,19 +69,21 @@
 
                         // Test if the rotation is the expected
                         let q2: $quat = $quat::from_euler(euler, u1, v1, w1).normalize();
-                        assert_approx_eq!(q1, q2, 1e-5);
+                        assert_approx_eq!(q1.canonical(), q2.canonical(), <$t>::Q_EPS);
 
-                        // Test angle reconstruction
-                        let (u2, v2, w2) = q1.to_euler(euler);
+                        // Test quat reconstruction from angles
+                        let (u2, v2, w2) = q2.to_euler(euler);
                         let q3 = $quat::from_euler(euler, u2, v2, w2).normalize();
-
-                        assert_approx_angle!(u1, u2, 1e-4 as $t);
-                        assert_approx_angle!(v1, v2, 1e-4 as $t);
-                        assert_approx_angle!(w1, w2, 1e-4 as $t);
-
-                        assert_approx_eq!(q1 * $vec::X, q3 * $vec::X, 1e-4);
-                        assert_approx_eq!(q1 * $vec::Y, q3 * $vec::Y, 1e-4);
-                        assert_approx_eq!(q1 * $vec::Z, q3 * $vec::Z, 1e-4);
+                        assert_approx_eq!(
+                            q2.canonical(),
+                            q3.canonical(),
+                            <$t>::E_EPS,
+                            format!(
+                                "angles {:?} -> {:?}",
+                                (u, v, w),
+                                (u2.to_degrees(), v2.to_degrees(), w2.to_degrees())
+                            )
+                        );
                     }
                 }
             }
@@ -95,7 +103,7 @@
 }
 
 mod euler {
-    use super::AngleDiff;
+    use super::{CanonicalQuat, EulerEpsilon};
     use glam::*;
     type ER = EulerRot;
 
diff --git a/tests/float.rs b/tests/float.rs
new file mode 100644
index 0000000..f19f9c7
--- /dev/null
+++ b/tests/float.rs
@@ -0,0 +1,48 @@
+#[macro_use]
+mod support;
+
+macro_rules! impl_float_tests {
+    ($t:ident) => {
+        glam_test!(test_lerp, {
+            let a = 0.;
+            let b = 10.;
+            assert_eq!($t::lerp(a, b, 0.), a);
+            assert_eq!($t::lerp(a, b, 0.5), 5.);
+            assert_eq!($t::lerp(a, b, 1.), b);
+            assert_eq!($t::lerp(a, a, 0.), a);
+            assert_eq!($t::lerp(a, a, 1.), a);
+        });
+
+        glam_test!(test_inverse_lerp, {
+            let a = 0.;
+            let b = 10.;
+            assert_eq!($t::inverse_lerp(a, b, 0.), 0.);
+            assert_eq!($t::inverse_lerp(a, b, 5.), 0.5);
+            assert_eq!($t::inverse_lerp(a, b, 10.), 1.);
+            assert_eq!($t::inverse_lerp(a, b, 15.), 1.5);
+            assert!($t::inverse_lerp(a, a, 0.).is_nan());
+            assert!($t::inverse_lerp(a, a, 1.).is_infinite());
+        });
+
+        glam_test!(test_remap, {
+            assert_eq!($t::remap(0., 0., 2., 0., 20.), 0.);
+            assert_eq!($t::remap(1., 0., 2., 0., 20.), 10.);
+            assert_eq!($t::remap(2., 0., 2., 0., 20.), 20.);
+            assert_eq!($t::remap(-5., -10., 30., 60., 20.), 55.);
+            assert!($t::remap(0., 0., 0., 0., 1.).is_nan());
+            assert!($t::remap(1., 0., 0., 0., 1.).is_infinite());
+        });
+    };
+}
+
+mod float32 {
+    use glam::FloatExt;
+
+    impl_float_tests!(f32);
+}
+
+mod float64 {
+    use glam::FloatExt;
+
+    impl_float_tests!(f64);
+}
diff --git a/tests/mat2.rs b/tests/mat2.rs
index a19eb7d..9d579e4 100644
--- a/tests/mat2.rs
+++ b/tests/mat2.rs
@@ -202,14 +202,14 @@
 
         glam_test!(test_sum, {
             let id = $mat2::IDENTITY;
-            assert_eq!(vec![id, id].iter().sum::<$mat2>(), id + id);
-            assert_eq!(vec![id, id].into_iter().sum::<$mat2>(), id + id);
+            assert_eq!([id, id].iter().sum::<$mat2>(), id + id);
+            assert_eq!([id, id].into_iter().sum::<$mat2>(), id + id);
         });
 
         glam_test!(test_product, {
             let two = $mat2::IDENTITY + $mat2::IDENTITY;
-            assert_eq!(vec![two, two].iter().product::<$mat2>(), two * two);
-            assert_eq!(vec![two, two].into_iter().product::<$mat2>(), two * two);
+            assert_eq!([two, two].iter().product::<$mat2>(), two * two);
+            assert_eq!([two, two].into_iter().product::<$mat2>(), two * two);
         });
 
         glam_test!(test_mat2_is_finite, {
diff --git a/tests/mat3.rs b/tests/mat3.rs
index baf1e42..36a8d38 100644
--- a/tests/mat3.rs
+++ b/tests/mat3.rs
@@ -193,7 +193,7 @@
 
             let yx0 = y0 * x0;
             let yx1 = $mat3::from_euler(EulerRot::YXZ, yaw, pitch, zero);
-            assert_approx_eq!(yx0, yx1);
+            assert_approx_eq!(yx0, yx1, 1e-6);
 
             let yxz0 = y0 * x0 * z0;
             let yxz1 = $mat3::from_euler(EulerRot::YXZ, yaw, pitch, roll);
@@ -341,14 +341,14 @@
 
         glam_test!(test_sum, {
             let id = $mat3::IDENTITY;
-            assert_eq!(vec![id, id].iter().sum::<$mat3>(), id + id);
-            assert_eq!(vec![id, id].into_iter().sum::<$mat3>(), id + id);
+            assert_eq!([id, id].iter().sum::<$mat3>(), id + id);
+            assert_eq!([id, id].into_iter().sum::<$mat3>(), id + id);
         });
 
         glam_test!(test_product, {
             let two = $mat3::IDENTITY + $mat3::IDENTITY;
-            assert_eq!(vec![two, two].iter().product::<$mat3>(), two * two);
-            assert_eq!(vec![two, two].into_iter().product::<$mat3>(), two * two);
+            assert_eq!([two, two].iter().product::<$mat3>(), two * two);
+            assert_eq!([two, two].into_iter().product::<$mat3>(), two * two);
         });
 
         glam_test!(test_mat3_is_finite, {
diff --git a/tests/mat4.rs b/tests/mat4.rs
index 164bdd6..d3b9031 100644
--- a/tests/mat4.rs
+++ b/tests/mat4.rs
@@ -242,7 +242,7 @@
 
             let yx0 = y0 * x0;
             let yx1 = $mat4::from_euler(EulerRot::YXZ, yaw, pitch, zero);
-            assert_approx_eq!(yx0, yx1);
+            assert_approx_eq!(yx0, yx1, 1e-6);
 
             let yxz0 = y0 * x0 * z0;
             let yxz1 = $mat4::from_euler(EulerRot::YXZ, yaw, pitch, roll);
@@ -647,14 +647,14 @@
 
         glam_test!(test_sum, {
             let id = $mat4::IDENTITY;
-            assert_eq!(vec![id, id].iter().sum::<$mat4>(), id + id);
-            assert_eq!(vec![id, id].into_iter().sum::<$mat4>(), id + id);
+            assert_eq!([id, id].iter().sum::<$mat4>(), id + id);
+            assert_eq!([id, id].into_iter().sum::<$mat4>(), id + id);
         });
 
         glam_test!(test_product, {
             let two = $mat4::IDENTITY + $mat4::IDENTITY;
-            assert_eq!(vec![two, two].iter().product::<$mat4>(), two * two);
-            assert_eq!(vec![two, two].into_iter().product::<$mat4>(), two * two);
+            assert_eq!([two, two].iter().product::<$mat4>(), two * two);
+            assert_eq!([two, two].into_iter().product::<$mat4>(), two * two);
         });
 
         glam_test!(test_mat4_is_finite, {
diff --git a/tests/quat.rs b/tests/quat.rs
index 1a6f6e3..dfa7afa 100644
--- a/tests/quat.rs
+++ b/tests/quat.rs
@@ -407,14 +407,14 @@
 
         glam_test!(test_sum, {
             let two = $new(2.0, 2.0, 2.0, 2.0);
-            assert_eq!(vec![two, two].iter().sum::<$quat>(), two + two);
-            assert_eq!(vec![two, two].into_iter().sum::<$quat>(), two + two);
+            assert_eq!([two, two].iter().sum::<$quat>(), two + two);
+            assert_eq!([two, two].into_iter().sum::<$quat>(), two + two);
         });
 
         glam_test!(test_product, {
             let two = $new(2.0, 2.0, 2.0, 2.0).normalize();
-            assert_eq!(vec![two, two].iter().product::<$quat>(), two * two);
-            assert_eq!(vec![two, two].into_iter().product::<$quat>(), two * two);
+            assert_eq!([two, two].iter().product::<$quat>(), two * two);
+            assert_eq!([two, two].into_iter().product::<$quat>(), two * two);
         });
 
         glam_test!(test_is_finite, {
@@ -507,6 +507,47 @@
         glam_test!(test_to_array, {
             assert!($new(1.0, 2.0, 3.0, 4.0).to_array() == [1.0, 2.0, 3.0, 4.0]);
         });
+
+        glam_test!(test_to_axis_angle, {
+            {
+                let q = $quat::from_xyzw(
+                    5.28124762e-08,
+                    -5.12559303e-03,
+                    8.29266140e-08,
+                    9.99986828e-01,
+                );
+                assert!(q.is_normalized());
+                let (axis, angle) = q.to_axis_angle();
+                assert!(axis.is_normalized());
+                let q2 = $quat::from_axis_angle(axis, angle);
+                assert!((q.dot(q2) - 1.0).abs() < 1e-6);
+            }
+            {
+                let q = $quat::IDENTITY;
+                let (axis, angle) = q.to_axis_angle();
+                assert!(axis.is_normalized());
+                let q2 = $quat::from_axis_angle(axis, angle);
+                assert!((q.dot(q2) - 1.0).abs() < 1e-6);
+            }
+            {
+                let q = $quat::from_xyzw(0.0, 1.0, 0.0, 0.0);
+                assert!(q.is_normalized());
+                let (axis, angle) = q.to_axis_angle();
+                assert!(axis.is_normalized());
+                let q2 = $quat::from_axis_angle(axis, angle);
+                assert!((q.dot(q2) - 1.0).abs() < 1e-6);
+            }
+            {
+                let axis = $vec3::Z;
+                let angle = core::$t::consts::PI * 0.25;
+                let q = $quat::from_axis_angle(axis, angle);
+                assert!(q.is_normalized());
+                let (axis2, angle2) = q.to_axis_angle();
+                assert!(axis.is_normalized());
+                assert_approx_eq!(axis, axis2);
+                assert_approx_eq!(angle, angle2);
+            }
+        });
     };
 }
 
@@ -600,11 +641,11 @@
         use glam::DQuat;
         assert_approx_eq!(
             DQuat::from_euler(EulerRot::YXZ, 1.0, 2.0, 3.0),
-            Quat::from_euler(EulerRot::YXZ, 1.0, 2.0, 3.0).as_f64()
+            Quat::from_euler(EulerRot::YXZ, 1.0, 2.0, 3.0).as_dquat()
         );
         assert_approx_eq!(
             Quat::from_euler(EulerRot::YXZ, 1.0, 2.0, 3.0),
-            DQuat::from_euler(EulerRot::YXZ, 1.0, 2.0, 3.0).as_f32()
+            DQuat::from_euler(EulerRot::YXZ, 1.0, 2.0, 3.0).as_quat()
         );
     });
 
diff --git a/tests/support/macros.rs b/tests/support/macros.rs
index 9801902..e7fadd1 100644
--- a/tests/support/macros.rs
+++ b/tests/support/macros.rs
@@ -56,6 +56,22 @@
             a.abs_diff(b)
         );
     }};
+    ($a:expr, $b:expr, $eps:expr, $ctx:expr) => {{
+        use $crate::support::FloatCompare;
+        let (a, b) = (&$a, &$b);
+        let eps = $eps;
+        assert!(
+            a.approx_eq(b, $eps),
+            "assertion failed: `(left !== right)` \
+             (left: `{:?}`, right: `{:?}`, expect diff: `{:?}`, real diff: `{:?}`), \
+             additional context: {}",
+            *a,
+            *b,
+            eps,
+            a.abs_diff(b),
+            $ctx
+        );
+    }};
 }
 
 /// Test vector normalization for float vector
diff --git a/tests/swizzles_i16.rs b/tests/swizzles_i16.rs
new file mode 100644
index 0000000..7aaeb69
--- /dev/null
+++ b/tests/swizzles_i16.rs
@@ -0,0 +1,497 @@
+// Generated by swizzlegen. Do not edit.
+#[macro_use]
+mod support;
+use glam::*;
+
+glam_test!(test_i16vec4_swizzles, {
+    let v = i16vec4(1_i16, 2_i16, 3_i16, 4_i16);
+    assert_eq!(v, v.xyzw());
+    assert_eq!(v.xxxx(), i16vec4(1_i16, 1_i16, 1_i16, 1_i16));
+    assert_eq!(v.xxxy(), i16vec4(1_i16, 1_i16, 1_i16, 2_i16));
+    assert_eq!(v.xxxz(), i16vec4(1_i16, 1_i16, 1_i16, 3_i16));
+    assert_eq!(v.xxxw(), i16vec4(1_i16, 1_i16, 1_i16, 4_i16));
+    assert_eq!(v.xxyx(), i16vec4(1_i16, 1_i16, 2_i16, 1_i16));
+    assert_eq!(v.xxyy(), i16vec4(1_i16, 1_i16, 2_i16, 2_i16));
+    assert_eq!(v.xxyz(), i16vec4(1_i16, 1_i16, 2_i16, 3_i16));
+    assert_eq!(v.xxyw(), i16vec4(1_i16, 1_i16, 2_i16, 4_i16));
+    assert_eq!(v.xxzx(), i16vec4(1_i16, 1_i16, 3_i16, 1_i16));
+    assert_eq!(v.xxzy(), i16vec4(1_i16, 1_i16, 3_i16, 2_i16));
+    assert_eq!(v.xxzz(), i16vec4(1_i16, 1_i16, 3_i16, 3_i16));
+    assert_eq!(v.xxzw(), i16vec4(1_i16, 1_i16, 3_i16, 4_i16));
+    assert_eq!(v.xxwx(), i16vec4(1_i16, 1_i16, 4_i16, 1_i16));
+    assert_eq!(v.xxwy(), i16vec4(1_i16, 1_i16, 4_i16, 2_i16));
+    assert_eq!(v.xxwz(), i16vec4(1_i16, 1_i16, 4_i16, 3_i16));
+    assert_eq!(v.xxww(), i16vec4(1_i16, 1_i16, 4_i16, 4_i16));
+    assert_eq!(v.xyxx(), i16vec4(1_i16, 2_i16, 1_i16, 1_i16));
+    assert_eq!(v.xyxy(), i16vec4(1_i16, 2_i16, 1_i16, 2_i16));
+    assert_eq!(v.xyxz(), i16vec4(1_i16, 2_i16, 1_i16, 3_i16));
+    assert_eq!(v.xyxw(), i16vec4(1_i16, 2_i16, 1_i16, 4_i16));
+    assert_eq!(v.xyyx(), i16vec4(1_i16, 2_i16, 2_i16, 1_i16));
+    assert_eq!(v.xyyy(), i16vec4(1_i16, 2_i16, 2_i16, 2_i16));
+    assert_eq!(v.xyyz(), i16vec4(1_i16, 2_i16, 2_i16, 3_i16));
+    assert_eq!(v.xyyw(), i16vec4(1_i16, 2_i16, 2_i16, 4_i16));
+    assert_eq!(v.xyzx(), i16vec4(1_i16, 2_i16, 3_i16, 1_i16));
+    assert_eq!(v.xyzy(), i16vec4(1_i16, 2_i16, 3_i16, 2_i16));
+    assert_eq!(v.xyzz(), i16vec4(1_i16, 2_i16, 3_i16, 3_i16));
+    assert_eq!(v.xywx(), i16vec4(1_i16, 2_i16, 4_i16, 1_i16));
+    assert_eq!(v.xywy(), i16vec4(1_i16, 2_i16, 4_i16, 2_i16));
+    assert_eq!(v.xywz(), i16vec4(1_i16, 2_i16, 4_i16, 3_i16));
+    assert_eq!(v.xyww(), i16vec4(1_i16, 2_i16, 4_i16, 4_i16));
+    assert_eq!(v.xzxx(), i16vec4(1_i16, 3_i16, 1_i16, 1_i16));
+    assert_eq!(v.xzxy(), i16vec4(1_i16, 3_i16, 1_i16, 2_i16));
+    assert_eq!(v.xzxz(), i16vec4(1_i16, 3_i16, 1_i16, 3_i16));
+    assert_eq!(v.xzxw(), i16vec4(1_i16, 3_i16, 1_i16, 4_i16));
+    assert_eq!(v.xzyx(), i16vec4(1_i16, 3_i16, 2_i16, 1_i16));
+    assert_eq!(v.xzyy(), i16vec4(1_i16, 3_i16, 2_i16, 2_i16));
+    assert_eq!(v.xzyz(), i16vec4(1_i16, 3_i16, 2_i16, 3_i16));
+    assert_eq!(v.xzyw(), i16vec4(1_i16, 3_i16, 2_i16, 4_i16));
+    assert_eq!(v.xzzx(), i16vec4(1_i16, 3_i16, 3_i16, 1_i16));
+    assert_eq!(v.xzzy(), i16vec4(1_i16, 3_i16, 3_i16, 2_i16));
+    assert_eq!(v.xzzz(), i16vec4(1_i16, 3_i16, 3_i16, 3_i16));
+    assert_eq!(v.xzzw(), i16vec4(1_i16, 3_i16, 3_i16, 4_i16));
+    assert_eq!(v.xzwx(), i16vec4(1_i16, 3_i16, 4_i16, 1_i16));
+    assert_eq!(v.xzwy(), i16vec4(1_i16, 3_i16, 4_i16, 2_i16));
+    assert_eq!(v.xzwz(), i16vec4(1_i16, 3_i16, 4_i16, 3_i16));
+    assert_eq!(v.xzww(), i16vec4(1_i16, 3_i16, 4_i16, 4_i16));
+    assert_eq!(v.xwxx(), i16vec4(1_i16, 4_i16, 1_i16, 1_i16));
+    assert_eq!(v.xwxy(), i16vec4(1_i16, 4_i16, 1_i16, 2_i16));
+    assert_eq!(v.xwxz(), i16vec4(1_i16, 4_i16, 1_i16, 3_i16));
+    assert_eq!(v.xwxw(), i16vec4(1_i16, 4_i16, 1_i16, 4_i16));
+    assert_eq!(v.xwyx(), i16vec4(1_i16, 4_i16, 2_i16, 1_i16));
+    assert_eq!(v.xwyy(), i16vec4(1_i16, 4_i16, 2_i16, 2_i16));
+    assert_eq!(v.xwyz(), i16vec4(1_i16, 4_i16, 2_i16, 3_i16));
+    assert_eq!(v.xwyw(), i16vec4(1_i16, 4_i16, 2_i16, 4_i16));
+    assert_eq!(v.xwzx(), i16vec4(1_i16, 4_i16, 3_i16, 1_i16));
+    assert_eq!(v.xwzy(), i16vec4(1_i16, 4_i16, 3_i16, 2_i16));
+    assert_eq!(v.xwzz(), i16vec4(1_i16, 4_i16, 3_i16, 3_i16));
+    assert_eq!(v.xwzw(), i16vec4(1_i16, 4_i16, 3_i16, 4_i16));
+    assert_eq!(v.xwwx(), i16vec4(1_i16, 4_i16, 4_i16, 1_i16));
+    assert_eq!(v.xwwy(), i16vec4(1_i16, 4_i16, 4_i16, 2_i16));
+    assert_eq!(v.xwwz(), i16vec4(1_i16, 4_i16, 4_i16, 3_i16));
+    assert_eq!(v.xwww(), i16vec4(1_i16, 4_i16, 4_i16, 4_i16));
+    assert_eq!(v.yxxx(), i16vec4(2_i16, 1_i16, 1_i16, 1_i16));
+    assert_eq!(v.yxxy(), i16vec4(2_i16, 1_i16, 1_i16, 2_i16));
+    assert_eq!(v.yxxz(), i16vec4(2_i16, 1_i16, 1_i16, 3_i16));
+    assert_eq!(v.yxxw(), i16vec4(2_i16, 1_i16, 1_i16, 4_i16));
+    assert_eq!(v.yxyx(), i16vec4(2_i16, 1_i16, 2_i16, 1_i16));
+    assert_eq!(v.yxyy(), i16vec4(2_i16, 1_i16, 2_i16, 2_i16));
+    assert_eq!(v.yxyz(), i16vec4(2_i16, 1_i16, 2_i16, 3_i16));
+    assert_eq!(v.yxyw(), i16vec4(2_i16, 1_i16, 2_i16, 4_i16));
+    assert_eq!(v.yxzx(), i16vec4(2_i16, 1_i16, 3_i16, 1_i16));
+    assert_eq!(v.yxzy(), i16vec4(2_i16, 1_i16, 3_i16, 2_i16));
+    assert_eq!(v.yxzz(), i16vec4(2_i16, 1_i16, 3_i16, 3_i16));
+    assert_eq!(v.yxzw(), i16vec4(2_i16, 1_i16, 3_i16, 4_i16));
+    assert_eq!(v.yxwx(), i16vec4(2_i16, 1_i16, 4_i16, 1_i16));
+    assert_eq!(v.yxwy(), i16vec4(2_i16, 1_i16, 4_i16, 2_i16));
+    assert_eq!(v.yxwz(), i16vec4(2_i16, 1_i16, 4_i16, 3_i16));
+    assert_eq!(v.yxww(), i16vec4(2_i16, 1_i16, 4_i16, 4_i16));
+    assert_eq!(v.yyxx(), i16vec4(2_i16, 2_i16, 1_i16, 1_i16));
+    assert_eq!(v.yyxy(), i16vec4(2_i16, 2_i16, 1_i16, 2_i16));
+    assert_eq!(v.yyxz(), i16vec4(2_i16, 2_i16, 1_i16, 3_i16));
+    assert_eq!(v.yyxw(), i16vec4(2_i16, 2_i16, 1_i16, 4_i16));
+    assert_eq!(v.yyyx(), i16vec4(2_i16, 2_i16, 2_i16, 1_i16));
+    assert_eq!(v.yyyy(), i16vec4(2_i16, 2_i16, 2_i16, 2_i16));
+    assert_eq!(v.yyyz(), i16vec4(2_i16, 2_i16, 2_i16, 3_i16));
+    assert_eq!(v.yyyw(), i16vec4(2_i16, 2_i16, 2_i16, 4_i16));
+    assert_eq!(v.yyzx(), i16vec4(2_i16, 2_i16, 3_i16, 1_i16));
+    assert_eq!(v.yyzy(), i16vec4(2_i16, 2_i16, 3_i16, 2_i16));
+    assert_eq!(v.yyzz(), i16vec4(2_i16, 2_i16, 3_i16, 3_i16));
+    assert_eq!(v.yyzw(), i16vec4(2_i16, 2_i16, 3_i16, 4_i16));
+    assert_eq!(v.yywx(), i16vec4(2_i16, 2_i16, 4_i16, 1_i16));
+    assert_eq!(v.yywy(), i16vec4(2_i16, 2_i16, 4_i16, 2_i16));
+    assert_eq!(v.yywz(), i16vec4(2_i16, 2_i16, 4_i16, 3_i16));
+    assert_eq!(v.yyww(), i16vec4(2_i16, 2_i16, 4_i16, 4_i16));
+    assert_eq!(v.yzxx(), i16vec4(2_i16, 3_i16, 1_i16, 1_i16));
+    assert_eq!(v.yzxy(), i16vec4(2_i16, 3_i16, 1_i16, 2_i16));
+    assert_eq!(v.yzxz(), i16vec4(2_i16, 3_i16, 1_i16, 3_i16));
+    assert_eq!(v.yzxw(), i16vec4(2_i16, 3_i16, 1_i16, 4_i16));
+    assert_eq!(v.yzyx(), i16vec4(2_i16, 3_i16, 2_i16, 1_i16));
+    assert_eq!(v.yzyy(), i16vec4(2_i16, 3_i16, 2_i16, 2_i16));
+    assert_eq!(v.yzyz(), i16vec4(2_i16, 3_i16, 2_i16, 3_i16));
+    assert_eq!(v.yzyw(), i16vec4(2_i16, 3_i16, 2_i16, 4_i16));
+    assert_eq!(v.yzzx(), i16vec4(2_i16, 3_i16, 3_i16, 1_i16));
+    assert_eq!(v.yzzy(), i16vec4(2_i16, 3_i16, 3_i16, 2_i16));
+    assert_eq!(v.yzzz(), i16vec4(2_i16, 3_i16, 3_i16, 3_i16));
+    assert_eq!(v.yzzw(), i16vec4(2_i16, 3_i16, 3_i16, 4_i16));
+    assert_eq!(v.yzwx(), i16vec4(2_i16, 3_i16, 4_i16, 1_i16));
+    assert_eq!(v.yzwy(), i16vec4(2_i16, 3_i16, 4_i16, 2_i16));
+    assert_eq!(v.yzwz(), i16vec4(2_i16, 3_i16, 4_i16, 3_i16));
+    assert_eq!(v.yzww(), i16vec4(2_i16, 3_i16, 4_i16, 4_i16));
+    assert_eq!(v.ywxx(), i16vec4(2_i16, 4_i16, 1_i16, 1_i16));
+    assert_eq!(v.ywxy(), i16vec4(2_i16, 4_i16, 1_i16, 2_i16));
+    assert_eq!(v.ywxz(), i16vec4(2_i16, 4_i16, 1_i16, 3_i16));
+    assert_eq!(v.ywxw(), i16vec4(2_i16, 4_i16, 1_i16, 4_i16));
+    assert_eq!(v.ywyx(), i16vec4(2_i16, 4_i16, 2_i16, 1_i16));
+    assert_eq!(v.ywyy(), i16vec4(2_i16, 4_i16, 2_i16, 2_i16));
+    assert_eq!(v.ywyz(), i16vec4(2_i16, 4_i16, 2_i16, 3_i16));
+    assert_eq!(v.ywyw(), i16vec4(2_i16, 4_i16, 2_i16, 4_i16));
+    assert_eq!(v.ywzx(), i16vec4(2_i16, 4_i16, 3_i16, 1_i16));
+    assert_eq!(v.ywzy(), i16vec4(2_i16, 4_i16, 3_i16, 2_i16));
+    assert_eq!(v.ywzz(), i16vec4(2_i16, 4_i16, 3_i16, 3_i16));
+    assert_eq!(v.ywzw(), i16vec4(2_i16, 4_i16, 3_i16, 4_i16));
+    assert_eq!(v.ywwx(), i16vec4(2_i16, 4_i16, 4_i16, 1_i16));
+    assert_eq!(v.ywwy(), i16vec4(2_i16, 4_i16, 4_i16, 2_i16));
+    assert_eq!(v.ywwz(), i16vec4(2_i16, 4_i16, 4_i16, 3_i16));
+    assert_eq!(v.ywww(), i16vec4(2_i16, 4_i16, 4_i16, 4_i16));
+    assert_eq!(v.zxxx(), i16vec4(3_i16, 1_i16, 1_i16, 1_i16));
+    assert_eq!(v.zxxy(), i16vec4(3_i16, 1_i16, 1_i16, 2_i16));
+    assert_eq!(v.zxxz(), i16vec4(3_i16, 1_i16, 1_i16, 3_i16));
+    assert_eq!(v.zxxw(), i16vec4(3_i16, 1_i16, 1_i16, 4_i16));
+    assert_eq!(v.zxyx(), i16vec4(3_i16, 1_i16, 2_i16, 1_i16));
+    assert_eq!(v.zxyy(), i16vec4(3_i16, 1_i16, 2_i16, 2_i16));
+    assert_eq!(v.zxyz(), i16vec4(3_i16, 1_i16, 2_i16, 3_i16));
+    assert_eq!(v.zxyw(), i16vec4(3_i16, 1_i16, 2_i16, 4_i16));
+    assert_eq!(v.zxzx(), i16vec4(3_i16, 1_i16, 3_i16, 1_i16));
+    assert_eq!(v.zxzy(), i16vec4(3_i16, 1_i16, 3_i16, 2_i16));
+    assert_eq!(v.zxzz(), i16vec4(3_i16, 1_i16, 3_i16, 3_i16));
+    assert_eq!(v.zxzw(), i16vec4(3_i16, 1_i16, 3_i16, 4_i16));
+    assert_eq!(v.zxwx(), i16vec4(3_i16, 1_i16, 4_i16, 1_i16));
+    assert_eq!(v.zxwy(), i16vec4(3_i16, 1_i16, 4_i16, 2_i16));
+    assert_eq!(v.zxwz(), i16vec4(3_i16, 1_i16, 4_i16, 3_i16));
+    assert_eq!(v.zxww(), i16vec4(3_i16, 1_i16, 4_i16, 4_i16));
+    assert_eq!(v.zyxx(), i16vec4(3_i16, 2_i16, 1_i16, 1_i16));
+    assert_eq!(v.zyxy(), i16vec4(3_i16, 2_i16, 1_i16, 2_i16));
+    assert_eq!(v.zyxz(), i16vec4(3_i16, 2_i16, 1_i16, 3_i16));
+    assert_eq!(v.zyxw(), i16vec4(3_i16, 2_i16, 1_i16, 4_i16));
+    assert_eq!(v.zyyx(), i16vec4(3_i16, 2_i16, 2_i16, 1_i16));
+    assert_eq!(v.zyyy(), i16vec4(3_i16, 2_i16, 2_i16, 2_i16));
+    assert_eq!(v.zyyz(), i16vec4(3_i16, 2_i16, 2_i16, 3_i16));
+    assert_eq!(v.zyyw(), i16vec4(3_i16, 2_i16, 2_i16, 4_i16));
+    assert_eq!(v.zyzx(), i16vec4(3_i16, 2_i16, 3_i16, 1_i16));
+    assert_eq!(v.zyzy(), i16vec4(3_i16, 2_i16, 3_i16, 2_i16));
+    assert_eq!(v.zyzz(), i16vec4(3_i16, 2_i16, 3_i16, 3_i16));
+    assert_eq!(v.zyzw(), i16vec4(3_i16, 2_i16, 3_i16, 4_i16));
+    assert_eq!(v.zywx(), i16vec4(3_i16, 2_i16, 4_i16, 1_i16));
+    assert_eq!(v.zywy(), i16vec4(3_i16, 2_i16, 4_i16, 2_i16));
+    assert_eq!(v.zywz(), i16vec4(3_i16, 2_i16, 4_i16, 3_i16));
+    assert_eq!(v.zyww(), i16vec4(3_i16, 2_i16, 4_i16, 4_i16));
+    assert_eq!(v.zzxx(), i16vec4(3_i16, 3_i16, 1_i16, 1_i16));
+    assert_eq!(v.zzxy(), i16vec4(3_i16, 3_i16, 1_i16, 2_i16));
+    assert_eq!(v.zzxz(), i16vec4(3_i16, 3_i16, 1_i16, 3_i16));
+    assert_eq!(v.zzxw(), i16vec4(3_i16, 3_i16, 1_i16, 4_i16));
+    assert_eq!(v.zzyx(), i16vec4(3_i16, 3_i16, 2_i16, 1_i16));
+    assert_eq!(v.zzyy(), i16vec4(3_i16, 3_i16, 2_i16, 2_i16));
+    assert_eq!(v.zzyz(), i16vec4(3_i16, 3_i16, 2_i16, 3_i16));
+    assert_eq!(v.zzyw(), i16vec4(3_i16, 3_i16, 2_i16, 4_i16));
+    assert_eq!(v.zzzx(), i16vec4(3_i16, 3_i16, 3_i16, 1_i16));
+    assert_eq!(v.zzzy(), i16vec4(3_i16, 3_i16, 3_i16, 2_i16));
+    assert_eq!(v.zzzz(), i16vec4(3_i16, 3_i16, 3_i16, 3_i16));
+    assert_eq!(v.zzzw(), i16vec4(3_i16, 3_i16, 3_i16, 4_i16));
+    assert_eq!(v.zzwx(), i16vec4(3_i16, 3_i16, 4_i16, 1_i16));
+    assert_eq!(v.zzwy(), i16vec4(3_i16, 3_i16, 4_i16, 2_i16));
+    assert_eq!(v.zzwz(), i16vec4(3_i16, 3_i16, 4_i16, 3_i16));
+    assert_eq!(v.zzww(), i16vec4(3_i16, 3_i16, 4_i16, 4_i16));
+    assert_eq!(v.zwxx(), i16vec4(3_i16, 4_i16, 1_i16, 1_i16));
+    assert_eq!(v.zwxy(), i16vec4(3_i16, 4_i16, 1_i16, 2_i16));
+    assert_eq!(v.zwxz(), i16vec4(3_i16, 4_i16, 1_i16, 3_i16));
+    assert_eq!(v.zwxw(), i16vec4(3_i16, 4_i16, 1_i16, 4_i16));
+    assert_eq!(v.zwyx(), i16vec4(3_i16, 4_i16, 2_i16, 1_i16));
+    assert_eq!(v.zwyy(), i16vec4(3_i16, 4_i16, 2_i16, 2_i16));
+    assert_eq!(v.zwyz(), i16vec4(3_i16, 4_i16, 2_i16, 3_i16));
+    assert_eq!(v.zwyw(), i16vec4(3_i16, 4_i16, 2_i16, 4_i16));
+    assert_eq!(v.zwzx(), i16vec4(3_i16, 4_i16, 3_i16, 1_i16));
+    assert_eq!(v.zwzy(), i16vec4(3_i16, 4_i16, 3_i16, 2_i16));
+    assert_eq!(v.zwzz(), i16vec4(3_i16, 4_i16, 3_i16, 3_i16));
+    assert_eq!(v.zwzw(), i16vec4(3_i16, 4_i16, 3_i16, 4_i16));
+    assert_eq!(v.zwwx(), i16vec4(3_i16, 4_i16, 4_i16, 1_i16));
+    assert_eq!(v.zwwy(), i16vec4(3_i16, 4_i16, 4_i16, 2_i16));
+    assert_eq!(v.zwwz(), i16vec4(3_i16, 4_i16, 4_i16, 3_i16));
+    assert_eq!(v.zwww(), i16vec4(3_i16, 4_i16, 4_i16, 4_i16));
+    assert_eq!(v.wxxx(), i16vec4(4_i16, 1_i16, 1_i16, 1_i16));
+    assert_eq!(v.wxxy(), i16vec4(4_i16, 1_i16, 1_i16, 2_i16));
+    assert_eq!(v.wxxz(), i16vec4(4_i16, 1_i16, 1_i16, 3_i16));
+    assert_eq!(v.wxxw(), i16vec4(4_i16, 1_i16, 1_i16, 4_i16));
+    assert_eq!(v.wxyx(), i16vec4(4_i16, 1_i16, 2_i16, 1_i16));
+    assert_eq!(v.wxyy(), i16vec4(4_i16, 1_i16, 2_i16, 2_i16));
+    assert_eq!(v.wxyz(), i16vec4(4_i16, 1_i16, 2_i16, 3_i16));
+    assert_eq!(v.wxyw(), i16vec4(4_i16, 1_i16, 2_i16, 4_i16));
+    assert_eq!(v.wxzx(), i16vec4(4_i16, 1_i16, 3_i16, 1_i16));
+    assert_eq!(v.wxzy(), i16vec4(4_i16, 1_i16, 3_i16, 2_i16));
+    assert_eq!(v.wxzz(), i16vec4(4_i16, 1_i16, 3_i16, 3_i16));
+    assert_eq!(v.wxzw(), i16vec4(4_i16, 1_i16, 3_i16, 4_i16));
+    assert_eq!(v.wxwx(), i16vec4(4_i16, 1_i16, 4_i16, 1_i16));
+    assert_eq!(v.wxwy(), i16vec4(4_i16, 1_i16, 4_i16, 2_i16));
+    assert_eq!(v.wxwz(), i16vec4(4_i16, 1_i16, 4_i16, 3_i16));
+    assert_eq!(v.wxww(), i16vec4(4_i16, 1_i16, 4_i16, 4_i16));
+    assert_eq!(v.wyxx(), i16vec4(4_i16, 2_i16, 1_i16, 1_i16));
+    assert_eq!(v.wyxy(), i16vec4(4_i16, 2_i16, 1_i16, 2_i16));
+    assert_eq!(v.wyxz(), i16vec4(4_i16, 2_i16, 1_i16, 3_i16));
+    assert_eq!(v.wyxw(), i16vec4(4_i16, 2_i16, 1_i16, 4_i16));
+    assert_eq!(v.wyyx(), i16vec4(4_i16, 2_i16, 2_i16, 1_i16));
+    assert_eq!(v.wyyy(), i16vec4(4_i16, 2_i16, 2_i16, 2_i16));
+    assert_eq!(v.wyyz(), i16vec4(4_i16, 2_i16, 2_i16, 3_i16));
+    assert_eq!(v.wyyw(), i16vec4(4_i16, 2_i16, 2_i16, 4_i16));
+    assert_eq!(v.wyzx(), i16vec4(4_i16, 2_i16, 3_i16, 1_i16));
+    assert_eq!(v.wyzy(), i16vec4(4_i16, 2_i16, 3_i16, 2_i16));
+    assert_eq!(v.wyzz(), i16vec4(4_i16, 2_i16, 3_i16, 3_i16));
+    assert_eq!(v.wyzw(), i16vec4(4_i16, 2_i16, 3_i16, 4_i16));
+    assert_eq!(v.wywx(), i16vec4(4_i16, 2_i16, 4_i16, 1_i16));
+    assert_eq!(v.wywy(), i16vec4(4_i16, 2_i16, 4_i16, 2_i16));
+    assert_eq!(v.wywz(), i16vec4(4_i16, 2_i16, 4_i16, 3_i16));
+    assert_eq!(v.wyww(), i16vec4(4_i16, 2_i16, 4_i16, 4_i16));
+    assert_eq!(v.wzxx(), i16vec4(4_i16, 3_i16, 1_i16, 1_i16));
+    assert_eq!(v.wzxy(), i16vec4(4_i16, 3_i16, 1_i16, 2_i16));
+    assert_eq!(v.wzxz(), i16vec4(4_i16, 3_i16, 1_i16, 3_i16));
+    assert_eq!(v.wzxw(), i16vec4(4_i16, 3_i16, 1_i16, 4_i16));
+    assert_eq!(v.wzyx(), i16vec4(4_i16, 3_i16, 2_i16, 1_i16));
+    assert_eq!(v.wzyy(), i16vec4(4_i16, 3_i16, 2_i16, 2_i16));
+    assert_eq!(v.wzyz(), i16vec4(4_i16, 3_i16, 2_i16, 3_i16));
+    assert_eq!(v.wzyw(), i16vec4(4_i16, 3_i16, 2_i16, 4_i16));
+    assert_eq!(v.wzzx(), i16vec4(4_i16, 3_i16, 3_i16, 1_i16));
+    assert_eq!(v.wzzy(), i16vec4(4_i16, 3_i16, 3_i16, 2_i16));
+    assert_eq!(v.wzzz(), i16vec4(4_i16, 3_i16, 3_i16, 3_i16));
+    assert_eq!(v.wzzw(), i16vec4(4_i16, 3_i16, 3_i16, 4_i16));
+    assert_eq!(v.wzwx(), i16vec4(4_i16, 3_i16, 4_i16, 1_i16));
+    assert_eq!(v.wzwy(), i16vec4(4_i16, 3_i16, 4_i16, 2_i16));
+    assert_eq!(v.wzwz(), i16vec4(4_i16, 3_i16, 4_i16, 3_i16));
+    assert_eq!(v.wzww(), i16vec4(4_i16, 3_i16, 4_i16, 4_i16));
+    assert_eq!(v.wwxx(), i16vec4(4_i16, 4_i16, 1_i16, 1_i16));
+    assert_eq!(v.wwxy(), i16vec4(4_i16, 4_i16, 1_i16, 2_i16));
+    assert_eq!(v.wwxz(), i16vec4(4_i16, 4_i16, 1_i16, 3_i16));
+    assert_eq!(v.wwxw(), i16vec4(4_i16, 4_i16, 1_i16, 4_i16));
+    assert_eq!(v.wwyx(), i16vec4(4_i16, 4_i16, 2_i16, 1_i16));
+    assert_eq!(v.wwyy(), i16vec4(4_i16, 4_i16, 2_i16, 2_i16));
+    assert_eq!(v.wwyz(), i16vec4(4_i16, 4_i16, 2_i16, 3_i16));
+    assert_eq!(v.wwyw(), i16vec4(4_i16, 4_i16, 2_i16, 4_i16));
+    assert_eq!(v.wwzx(), i16vec4(4_i16, 4_i16, 3_i16, 1_i16));
+    assert_eq!(v.wwzy(), i16vec4(4_i16, 4_i16, 3_i16, 2_i16));
+    assert_eq!(v.wwzz(), i16vec4(4_i16, 4_i16, 3_i16, 3_i16));
+    assert_eq!(v.wwzw(), i16vec4(4_i16, 4_i16, 3_i16, 4_i16));
+    assert_eq!(v.wwwx(), i16vec4(4_i16, 4_i16, 4_i16, 1_i16));
+    assert_eq!(v.wwwy(), i16vec4(4_i16, 4_i16, 4_i16, 2_i16));
+    assert_eq!(v.wwwz(), i16vec4(4_i16, 4_i16, 4_i16, 3_i16));
+    assert_eq!(v.wwww(), i16vec4(4_i16, 4_i16, 4_i16, 4_i16));
+    assert_eq!(v.xxx(), i16vec3(1_i16, 1_i16, 1_i16));
+    assert_eq!(v.xxy(), i16vec3(1_i16, 1_i16, 2_i16));
+    assert_eq!(v.xxz(), i16vec3(1_i16, 1_i16, 3_i16));
+    assert_eq!(v.xxw(), i16vec3(1_i16, 1_i16, 4_i16));
+    assert_eq!(v.xyx(), i16vec3(1_i16, 2_i16, 1_i16));
+    assert_eq!(v.xyy(), i16vec3(1_i16, 2_i16, 2_i16));
+    assert_eq!(v.xyz(), i16vec3(1_i16, 2_i16, 3_i16));
+    assert_eq!(v.xyw(), i16vec3(1_i16, 2_i16, 4_i16));
+    assert_eq!(v.xzx(), i16vec3(1_i16, 3_i16, 1_i16));
+    assert_eq!(v.xzy(), i16vec3(1_i16, 3_i16, 2_i16));
+    assert_eq!(v.xzz(), i16vec3(1_i16, 3_i16, 3_i16));
+    assert_eq!(v.xzw(), i16vec3(1_i16, 3_i16, 4_i16));
+    assert_eq!(v.xwx(), i16vec3(1_i16, 4_i16, 1_i16));
+    assert_eq!(v.xwy(), i16vec3(1_i16, 4_i16, 2_i16));
+    assert_eq!(v.xwz(), i16vec3(1_i16, 4_i16, 3_i16));
+    assert_eq!(v.xww(), i16vec3(1_i16, 4_i16, 4_i16));
+    assert_eq!(v.yxx(), i16vec3(2_i16, 1_i16, 1_i16));
+    assert_eq!(v.yxy(), i16vec3(2_i16, 1_i16, 2_i16));
+    assert_eq!(v.yxz(), i16vec3(2_i16, 1_i16, 3_i16));
+    assert_eq!(v.yxw(), i16vec3(2_i16, 1_i16, 4_i16));
+    assert_eq!(v.yyx(), i16vec3(2_i16, 2_i16, 1_i16));
+    assert_eq!(v.yyy(), i16vec3(2_i16, 2_i16, 2_i16));
+    assert_eq!(v.yyz(), i16vec3(2_i16, 2_i16, 3_i16));
+    assert_eq!(v.yyw(), i16vec3(2_i16, 2_i16, 4_i16));
+    assert_eq!(v.yzx(), i16vec3(2_i16, 3_i16, 1_i16));
+    assert_eq!(v.yzy(), i16vec3(2_i16, 3_i16, 2_i16));
+    assert_eq!(v.yzz(), i16vec3(2_i16, 3_i16, 3_i16));
+    assert_eq!(v.yzw(), i16vec3(2_i16, 3_i16, 4_i16));
+    assert_eq!(v.ywx(), i16vec3(2_i16, 4_i16, 1_i16));
+    assert_eq!(v.ywy(), i16vec3(2_i16, 4_i16, 2_i16));
+    assert_eq!(v.ywz(), i16vec3(2_i16, 4_i16, 3_i16));
+    assert_eq!(v.yww(), i16vec3(2_i16, 4_i16, 4_i16));
+    assert_eq!(v.zxx(), i16vec3(3_i16, 1_i16, 1_i16));
+    assert_eq!(v.zxy(), i16vec3(3_i16, 1_i16, 2_i16));
+    assert_eq!(v.zxz(), i16vec3(3_i16, 1_i16, 3_i16));
+    assert_eq!(v.zxw(), i16vec3(3_i16, 1_i16, 4_i16));
+    assert_eq!(v.zyx(), i16vec3(3_i16, 2_i16, 1_i16));
+    assert_eq!(v.zyy(), i16vec3(3_i16, 2_i16, 2_i16));
+    assert_eq!(v.zyz(), i16vec3(3_i16, 2_i16, 3_i16));
+    assert_eq!(v.zyw(), i16vec3(3_i16, 2_i16, 4_i16));
+    assert_eq!(v.zzx(), i16vec3(3_i16, 3_i16, 1_i16));
+    assert_eq!(v.zzy(), i16vec3(3_i16, 3_i16, 2_i16));
+    assert_eq!(v.zzz(), i16vec3(3_i16, 3_i16, 3_i16));
+    assert_eq!(v.zzw(), i16vec3(3_i16, 3_i16, 4_i16));
+    assert_eq!(v.zwx(), i16vec3(3_i16, 4_i16, 1_i16));
+    assert_eq!(v.zwy(), i16vec3(3_i16, 4_i16, 2_i16));
+    assert_eq!(v.zwz(), i16vec3(3_i16, 4_i16, 3_i16));
+    assert_eq!(v.zww(), i16vec3(3_i16, 4_i16, 4_i16));
+    assert_eq!(v.wxx(), i16vec3(4_i16, 1_i16, 1_i16));
+    assert_eq!(v.wxy(), i16vec3(4_i16, 1_i16, 2_i16));
+    assert_eq!(v.wxz(), i16vec3(4_i16, 1_i16, 3_i16));
+    assert_eq!(v.wxw(), i16vec3(4_i16, 1_i16, 4_i16));
+    assert_eq!(v.wyx(), i16vec3(4_i16, 2_i16, 1_i16));
+    assert_eq!(v.wyy(), i16vec3(4_i16, 2_i16, 2_i16));
+    assert_eq!(v.wyz(), i16vec3(4_i16, 2_i16, 3_i16));
+    assert_eq!(v.wyw(), i16vec3(4_i16, 2_i16, 4_i16));
+    assert_eq!(v.wzx(), i16vec3(4_i16, 3_i16, 1_i16));
+    assert_eq!(v.wzy(), i16vec3(4_i16, 3_i16, 2_i16));
+    assert_eq!(v.wzz(), i16vec3(4_i16, 3_i16, 3_i16));
+    assert_eq!(v.wzw(), i16vec3(4_i16, 3_i16, 4_i16));
+    assert_eq!(v.wwx(), i16vec3(4_i16, 4_i16, 1_i16));
+    assert_eq!(v.wwy(), i16vec3(4_i16, 4_i16, 2_i16));
+    assert_eq!(v.wwz(), i16vec3(4_i16, 4_i16, 3_i16));
+    assert_eq!(v.www(), i16vec3(4_i16, 4_i16, 4_i16));
+    assert_eq!(v.xx(), i16vec2(1_i16, 1_i16));
+    assert_eq!(v.xy(), i16vec2(1_i16, 2_i16));
+    assert_eq!(v.xz(), i16vec2(1_i16, 3_i16));
+    assert_eq!(v.xw(), i16vec2(1_i16, 4_i16));
+    assert_eq!(v.yx(), i16vec2(2_i16, 1_i16));
+    assert_eq!(v.yy(), i16vec2(2_i16, 2_i16));
+    assert_eq!(v.yz(), i16vec2(2_i16, 3_i16));
+    assert_eq!(v.yw(), i16vec2(2_i16, 4_i16));
+    assert_eq!(v.zx(), i16vec2(3_i16, 1_i16));
+    assert_eq!(v.zy(), i16vec2(3_i16, 2_i16));
+    assert_eq!(v.zz(), i16vec2(3_i16, 3_i16));
+    assert_eq!(v.zw(), i16vec2(3_i16, 4_i16));
+    assert_eq!(v.wx(), i16vec2(4_i16, 1_i16));
+    assert_eq!(v.wy(), i16vec2(4_i16, 2_i16));
+    assert_eq!(v.wz(), i16vec2(4_i16, 3_i16));
+    assert_eq!(v.ww(), i16vec2(4_i16, 4_i16));
+});
+
+glam_test!(test_i16vec3_swizzles, {
+    let v = i16vec3(1_i16, 2_i16, 3_i16);
+    assert_eq!(v, v.xyz());
+    assert_eq!(v.xxxx(), i16vec4(1_i16, 1_i16, 1_i16, 1_i16));
+    assert_eq!(v.xxxy(), i16vec4(1_i16, 1_i16, 1_i16, 2_i16));
+    assert_eq!(v.xxxz(), i16vec4(1_i16, 1_i16, 1_i16, 3_i16));
+    assert_eq!(v.xxyx(), i16vec4(1_i16, 1_i16, 2_i16, 1_i16));
+    assert_eq!(v.xxyy(), i16vec4(1_i16, 1_i16, 2_i16, 2_i16));
+    assert_eq!(v.xxyz(), i16vec4(1_i16, 1_i16, 2_i16, 3_i16));
+    assert_eq!(v.xxzx(), i16vec4(1_i16, 1_i16, 3_i16, 1_i16));
+    assert_eq!(v.xxzy(), i16vec4(1_i16, 1_i16, 3_i16, 2_i16));
+    assert_eq!(v.xxzz(), i16vec4(1_i16, 1_i16, 3_i16, 3_i16));
+    assert_eq!(v.xyxx(), i16vec4(1_i16, 2_i16, 1_i16, 1_i16));
+    assert_eq!(v.xyxy(), i16vec4(1_i16, 2_i16, 1_i16, 2_i16));
+    assert_eq!(v.xyxz(), i16vec4(1_i16, 2_i16, 1_i16, 3_i16));
+    assert_eq!(v.xyyx(), i16vec4(1_i16, 2_i16, 2_i16, 1_i16));
+    assert_eq!(v.xyyy(), i16vec4(1_i16, 2_i16, 2_i16, 2_i16));
+    assert_eq!(v.xyyz(), i16vec4(1_i16, 2_i16, 2_i16, 3_i16));
+    assert_eq!(v.xyzx(), i16vec4(1_i16, 2_i16, 3_i16, 1_i16));
+    assert_eq!(v.xyzy(), i16vec4(1_i16, 2_i16, 3_i16, 2_i16));
+    assert_eq!(v.xyzz(), i16vec4(1_i16, 2_i16, 3_i16, 3_i16));
+    assert_eq!(v.xzxx(), i16vec4(1_i16, 3_i16, 1_i16, 1_i16));
+    assert_eq!(v.xzxy(), i16vec4(1_i16, 3_i16, 1_i16, 2_i16));
+    assert_eq!(v.xzxz(), i16vec4(1_i16, 3_i16, 1_i16, 3_i16));
+    assert_eq!(v.xzyx(), i16vec4(1_i16, 3_i16, 2_i16, 1_i16));
+    assert_eq!(v.xzyy(), i16vec4(1_i16, 3_i16, 2_i16, 2_i16));
+    assert_eq!(v.xzyz(), i16vec4(1_i16, 3_i16, 2_i16, 3_i16));
+    assert_eq!(v.xzzx(), i16vec4(1_i16, 3_i16, 3_i16, 1_i16));
+    assert_eq!(v.xzzy(), i16vec4(1_i16, 3_i16, 3_i16, 2_i16));
+    assert_eq!(v.xzzz(), i16vec4(1_i16, 3_i16, 3_i16, 3_i16));
+    assert_eq!(v.yxxx(), i16vec4(2_i16, 1_i16, 1_i16, 1_i16));
+    assert_eq!(v.yxxy(), i16vec4(2_i16, 1_i16, 1_i16, 2_i16));
+    assert_eq!(v.yxxz(), i16vec4(2_i16, 1_i16, 1_i16, 3_i16));
+    assert_eq!(v.yxyx(), i16vec4(2_i16, 1_i16, 2_i16, 1_i16));
+    assert_eq!(v.yxyy(), i16vec4(2_i16, 1_i16, 2_i16, 2_i16));
+    assert_eq!(v.yxyz(), i16vec4(2_i16, 1_i16, 2_i16, 3_i16));
+    assert_eq!(v.yxzx(), i16vec4(2_i16, 1_i16, 3_i16, 1_i16));
+    assert_eq!(v.yxzy(), i16vec4(2_i16, 1_i16, 3_i16, 2_i16));
+    assert_eq!(v.yxzz(), i16vec4(2_i16, 1_i16, 3_i16, 3_i16));
+    assert_eq!(v.yyxx(), i16vec4(2_i16, 2_i16, 1_i16, 1_i16));
+    assert_eq!(v.yyxy(), i16vec4(2_i16, 2_i16, 1_i16, 2_i16));
+    assert_eq!(v.yyxz(), i16vec4(2_i16, 2_i16, 1_i16, 3_i16));
+    assert_eq!(v.yyyx(), i16vec4(2_i16, 2_i16, 2_i16, 1_i16));
+    assert_eq!(v.yyyy(), i16vec4(2_i16, 2_i16, 2_i16, 2_i16));
+    assert_eq!(v.yyyz(), i16vec4(2_i16, 2_i16, 2_i16, 3_i16));
+    assert_eq!(v.yyzx(), i16vec4(2_i16, 2_i16, 3_i16, 1_i16));
+    assert_eq!(v.yyzy(), i16vec4(2_i16, 2_i16, 3_i16, 2_i16));
+    assert_eq!(v.yyzz(), i16vec4(2_i16, 2_i16, 3_i16, 3_i16));
+    assert_eq!(v.yzxx(), i16vec4(2_i16, 3_i16, 1_i16, 1_i16));
+    assert_eq!(v.yzxy(), i16vec4(2_i16, 3_i16, 1_i16, 2_i16));
+    assert_eq!(v.yzxz(), i16vec4(2_i16, 3_i16, 1_i16, 3_i16));
+    assert_eq!(v.yzyx(), i16vec4(2_i16, 3_i16, 2_i16, 1_i16));
+    assert_eq!(v.yzyy(), i16vec4(2_i16, 3_i16, 2_i16, 2_i16));
+    assert_eq!(v.yzyz(), i16vec4(2_i16, 3_i16, 2_i16, 3_i16));
+    assert_eq!(v.yzzx(), i16vec4(2_i16, 3_i16, 3_i16, 1_i16));
+    assert_eq!(v.yzzy(), i16vec4(2_i16, 3_i16, 3_i16, 2_i16));
+    assert_eq!(v.yzzz(), i16vec4(2_i16, 3_i16, 3_i16, 3_i16));
+    assert_eq!(v.zxxx(), i16vec4(3_i16, 1_i16, 1_i16, 1_i16));
+    assert_eq!(v.zxxy(), i16vec4(3_i16, 1_i16, 1_i16, 2_i16));
+    assert_eq!(v.zxxz(), i16vec4(3_i16, 1_i16, 1_i16, 3_i16));
+    assert_eq!(v.zxyx(), i16vec4(3_i16, 1_i16, 2_i16, 1_i16));
+    assert_eq!(v.zxyy(), i16vec4(3_i16, 1_i16, 2_i16, 2_i16));
+    assert_eq!(v.zxyz(), i16vec4(3_i16, 1_i16, 2_i16, 3_i16));
+    assert_eq!(v.zxzx(), i16vec4(3_i16, 1_i16, 3_i16, 1_i16));
+    assert_eq!(v.zxzy(), i16vec4(3_i16, 1_i16, 3_i16, 2_i16));
+    assert_eq!(v.zxzz(), i16vec4(3_i16, 1_i16, 3_i16, 3_i16));
+    assert_eq!(v.zyxx(), i16vec4(3_i16, 2_i16, 1_i16, 1_i16));
+    assert_eq!(v.zyxy(), i16vec4(3_i16, 2_i16, 1_i16, 2_i16));
+    assert_eq!(v.zyxz(), i16vec4(3_i16, 2_i16, 1_i16, 3_i16));
+    assert_eq!(v.zyyx(), i16vec4(3_i16, 2_i16, 2_i16, 1_i16));
+    assert_eq!(v.zyyy(), i16vec4(3_i16, 2_i16, 2_i16, 2_i16));
+    assert_eq!(v.zyyz(), i16vec4(3_i16, 2_i16, 2_i16, 3_i16));
+    assert_eq!(v.zyzx(), i16vec4(3_i16, 2_i16, 3_i16, 1_i16));
+    assert_eq!(v.zyzy(), i16vec4(3_i16, 2_i16, 3_i16, 2_i16));
+    assert_eq!(v.zyzz(), i16vec4(3_i16, 2_i16, 3_i16, 3_i16));
+    assert_eq!(v.zzxx(), i16vec4(3_i16, 3_i16, 1_i16, 1_i16));
+    assert_eq!(v.zzxy(), i16vec4(3_i16, 3_i16, 1_i16, 2_i16));
+    assert_eq!(v.zzxz(), i16vec4(3_i16, 3_i16, 1_i16, 3_i16));
+    assert_eq!(v.zzyx(), i16vec4(3_i16, 3_i16, 2_i16, 1_i16));
+    assert_eq!(v.zzyy(), i16vec4(3_i16, 3_i16, 2_i16, 2_i16));
+    assert_eq!(v.zzyz(), i16vec4(3_i16, 3_i16, 2_i16, 3_i16));
+    assert_eq!(v.zzzx(), i16vec4(3_i16, 3_i16, 3_i16, 1_i16));
+    assert_eq!(v.zzzy(), i16vec4(3_i16, 3_i16, 3_i16, 2_i16));
+    assert_eq!(v.zzzz(), i16vec4(3_i16, 3_i16, 3_i16, 3_i16));
+    assert_eq!(v.xxx(), i16vec3(1_i16, 1_i16, 1_i16));
+    assert_eq!(v.xxy(), i16vec3(1_i16, 1_i16, 2_i16));
+    assert_eq!(v.xxz(), i16vec3(1_i16, 1_i16, 3_i16));
+    assert_eq!(v.xyx(), i16vec3(1_i16, 2_i16, 1_i16));
+    assert_eq!(v.xyy(), i16vec3(1_i16, 2_i16, 2_i16));
+    assert_eq!(v.xzx(), i16vec3(1_i16, 3_i16, 1_i16));
+    assert_eq!(v.xzy(), i16vec3(1_i16, 3_i16, 2_i16));
+    assert_eq!(v.xzz(), i16vec3(1_i16, 3_i16, 3_i16));
+    assert_eq!(v.yxx(), i16vec3(2_i16, 1_i16, 1_i16));
+    assert_eq!(v.yxy(), i16vec3(2_i16, 1_i16, 2_i16));
+    assert_eq!(v.yxz(), i16vec3(2_i16, 1_i16, 3_i16));
+    assert_eq!(v.yyx(), i16vec3(2_i16, 2_i16, 1_i16));
+    assert_eq!(v.yyy(), i16vec3(2_i16, 2_i16, 2_i16));
+    assert_eq!(v.yyz(), i16vec3(2_i16, 2_i16, 3_i16));
+    assert_eq!(v.yzx(), i16vec3(2_i16, 3_i16, 1_i16));
+    assert_eq!(v.yzy(), i16vec3(2_i16, 3_i16, 2_i16));
+    assert_eq!(v.yzz(), i16vec3(2_i16, 3_i16, 3_i16));
+    assert_eq!(v.zxx(), i16vec3(3_i16, 1_i16, 1_i16));
+    assert_eq!(v.zxy(), i16vec3(3_i16, 1_i16, 2_i16));
+    assert_eq!(v.zxz(), i16vec3(3_i16, 1_i16, 3_i16));
+    assert_eq!(v.zyx(), i16vec3(3_i16, 2_i16, 1_i16));
+    assert_eq!(v.zyy(), i16vec3(3_i16, 2_i16, 2_i16));
+    assert_eq!(v.zyz(), i16vec3(3_i16, 2_i16, 3_i16));
+    assert_eq!(v.zzx(), i16vec3(3_i16, 3_i16, 1_i16));
+    assert_eq!(v.zzy(), i16vec3(3_i16, 3_i16, 2_i16));
+    assert_eq!(v.zzz(), i16vec3(3_i16, 3_i16, 3_i16));
+    assert_eq!(v.xx(), i16vec2(1_i16, 1_i16));
+    assert_eq!(v.xy(), i16vec2(1_i16, 2_i16));
+    assert_eq!(v.xz(), i16vec2(1_i16, 3_i16));
+    assert_eq!(v.yx(), i16vec2(2_i16, 1_i16));
+    assert_eq!(v.yy(), i16vec2(2_i16, 2_i16));
+    assert_eq!(v.yz(), i16vec2(2_i16, 3_i16));
+    assert_eq!(v.zx(), i16vec2(3_i16, 1_i16));
+    assert_eq!(v.zy(), i16vec2(3_i16, 2_i16));
+    assert_eq!(v.zz(), i16vec2(3_i16, 3_i16));
+});
+
+glam_test!(test_i16vec2_swizzles, {
+    let v = i16vec2(1_i16, 2_i16);
+    assert_eq!(v, v.xy());
+    assert_eq!(v.xxxx(), i16vec4(1_i16, 1_i16, 1_i16, 1_i16));
+    assert_eq!(v.xxxy(), i16vec4(1_i16, 1_i16, 1_i16, 2_i16));
+    assert_eq!(v.xxyx(), i16vec4(1_i16, 1_i16, 2_i16, 1_i16));
+    assert_eq!(v.xxyy(), i16vec4(1_i16, 1_i16, 2_i16, 2_i16));
+    assert_eq!(v.xyxx(), i16vec4(1_i16, 2_i16, 1_i16, 1_i16));
+    assert_eq!(v.xyxy(), i16vec4(1_i16, 2_i16, 1_i16, 2_i16));
+    assert_eq!(v.xyyx(), i16vec4(1_i16, 2_i16, 2_i16, 1_i16));
+    assert_eq!(v.xyyy(), i16vec4(1_i16, 2_i16, 2_i16, 2_i16));
+    assert_eq!(v.yxxx(), i16vec4(2_i16, 1_i16, 1_i16, 1_i16));
+    assert_eq!(v.yxxy(), i16vec4(2_i16, 1_i16, 1_i16, 2_i16));
+    assert_eq!(v.yxyx(), i16vec4(2_i16, 1_i16, 2_i16, 1_i16));
+    assert_eq!(v.yxyy(), i16vec4(2_i16, 1_i16, 2_i16, 2_i16));
+    assert_eq!(v.yyxx(), i16vec4(2_i16, 2_i16, 1_i16, 1_i16));
+    assert_eq!(v.yyxy(), i16vec4(2_i16, 2_i16, 1_i16, 2_i16));
+    assert_eq!(v.yyyx(), i16vec4(2_i16, 2_i16, 2_i16, 1_i16));
+    assert_eq!(v.yyyy(), i16vec4(2_i16, 2_i16, 2_i16, 2_i16));
+    assert_eq!(v.xxx(), i16vec3(1_i16, 1_i16, 1_i16));
+    assert_eq!(v.xxy(), i16vec3(1_i16, 1_i16, 2_i16));
+    assert_eq!(v.xyx(), i16vec3(1_i16, 2_i16, 1_i16));
+    assert_eq!(v.xyy(), i16vec3(1_i16, 2_i16, 2_i16));
+    assert_eq!(v.yxx(), i16vec3(2_i16, 1_i16, 1_i16));
+    assert_eq!(v.yxy(), i16vec3(2_i16, 1_i16, 2_i16));
+    assert_eq!(v.yyx(), i16vec3(2_i16, 2_i16, 1_i16));
+    assert_eq!(v.yyy(), i16vec3(2_i16, 2_i16, 2_i16));
+    assert_eq!(v.xx(), i16vec2(1_i16, 1_i16));
+    assert_eq!(v.yx(), i16vec2(2_i16, 1_i16));
+    assert_eq!(v.yy(), i16vec2(2_i16, 2_i16));
+});
diff --git a/tests/swizzles_i64.rs b/tests/swizzles_i64.rs
new file mode 100644
index 0000000..d9a0b45
--- /dev/null
+++ b/tests/swizzles_i64.rs
@@ -0,0 +1,497 @@
+// Generated by swizzlegen. Do not edit.
+#[macro_use]
+mod support;
+use glam::*;
+
+glam_test!(test_i64vec4_swizzles, {
+    let v = i64vec4(1_i64, 2_i64, 3_i64, 4_i64);
+    assert_eq!(v, v.xyzw());
+    assert_eq!(v.xxxx(), i64vec4(1_i64, 1_i64, 1_i64, 1_i64));
+    assert_eq!(v.xxxy(), i64vec4(1_i64, 1_i64, 1_i64, 2_i64));
+    assert_eq!(v.xxxz(), i64vec4(1_i64, 1_i64, 1_i64, 3_i64));
+    assert_eq!(v.xxxw(), i64vec4(1_i64, 1_i64, 1_i64, 4_i64));
+    assert_eq!(v.xxyx(), i64vec4(1_i64, 1_i64, 2_i64, 1_i64));
+    assert_eq!(v.xxyy(), i64vec4(1_i64, 1_i64, 2_i64, 2_i64));
+    assert_eq!(v.xxyz(), i64vec4(1_i64, 1_i64, 2_i64, 3_i64));
+    assert_eq!(v.xxyw(), i64vec4(1_i64, 1_i64, 2_i64, 4_i64));
+    assert_eq!(v.xxzx(), i64vec4(1_i64, 1_i64, 3_i64, 1_i64));
+    assert_eq!(v.xxzy(), i64vec4(1_i64, 1_i64, 3_i64, 2_i64));
+    assert_eq!(v.xxzz(), i64vec4(1_i64, 1_i64, 3_i64, 3_i64));
+    assert_eq!(v.xxzw(), i64vec4(1_i64, 1_i64, 3_i64, 4_i64));
+    assert_eq!(v.xxwx(), i64vec4(1_i64, 1_i64, 4_i64, 1_i64));
+    assert_eq!(v.xxwy(), i64vec4(1_i64, 1_i64, 4_i64, 2_i64));
+    assert_eq!(v.xxwz(), i64vec4(1_i64, 1_i64, 4_i64, 3_i64));
+    assert_eq!(v.xxww(), i64vec4(1_i64, 1_i64, 4_i64, 4_i64));
+    assert_eq!(v.xyxx(), i64vec4(1_i64, 2_i64, 1_i64, 1_i64));
+    assert_eq!(v.xyxy(), i64vec4(1_i64, 2_i64, 1_i64, 2_i64));
+    assert_eq!(v.xyxz(), i64vec4(1_i64, 2_i64, 1_i64, 3_i64));
+    assert_eq!(v.xyxw(), i64vec4(1_i64, 2_i64, 1_i64, 4_i64));
+    assert_eq!(v.xyyx(), i64vec4(1_i64, 2_i64, 2_i64, 1_i64));
+    assert_eq!(v.xyyy(), i64vec4(1_i64, 2_i64, 2_i64, 2_i64));
+    assert_eq!(v.xyyz(), i64vec4(1_i64, 2_i64, 2_i64, 3_i64));
+    assert_eq!(v.xyyw(), i64vec4(1_i64, 2_i64, 2_i64, 4_i64));
+    assert_eq!(v.xyzx(), i64vec4(1_i64, 2_i64, 3_i64, 1_i64));
+    assert_eq!(v.xyzy(), i64vec4(1_i64, 2_i64, 3_i64, 2_i64));
+    assert_eq!(v.xyzz(), i64vec4(1_i64, 2_i64, 3_i64, 3_i64));
+    assert_eq!(v.xywx(), i64vec4(1_i64, 2_i64, 4_i64, 1_i64));
+    assert_eq!(v.xywy(), i64vec4(1_i64, 2_i64, 4_i64, 2_i64));
+    assert_eq!(v.xywz(), i64vec4(1_i64, 2_i64, 4_i64, 3_i64));
+    assert_eq!(v.xyww(), i64vec4(1_i64, 2_i64, 4_i64, 4_i64));
+    assert_eq!(v.xzxx(), i64vec4(1_i64, 3_i64, 1_i64, 1_i64));
+    assert_eq!(v.xzxy(), i64vec4(1_i64, 3_i64, 1_i64, 2_i64));
+    assert_eq!(v.xzxz(), i64vec4(1_i64, 3_i64, 1_i64, 3_i64));
+    assert_eq!(v.xzxw(), i64vec4(1_i64, 3_i64, 1_i64, 4_i64));
+    assert_eq!(v.xzyx(), i64vec4(1_i64, 3_i64, 2_i64, 1_i64));
+    assert_eq!(v.xzyy(), i64vec4(1_i64, 3_i64, 2_i64, 2_i64));
+    assert_eq!(v.xzyz(), i64vec4(1_i64, 3_i64, 2_i64, 3_i64));
+    assert_eq!(v.xzyw(), i64vec4(1_i64, 3_i64, 2_i64, 4_i64));
+    assert_eq!(v.xzzx(), i64vec4(1_i64, 3_i64, 3_i64, 1_i64));
+    assert_eq!(v.xzzy(), i64vec4(1_i64, 3_i64, 3_i64, 2_i64));
+    assert_eq!(v.xzzz(), i64vec4(1_i64, 3_i64, 3_i64, 3_i64));
+    assert_eq!(v.xzzw(), i64vec4(1_i64, 3_i64, 3_i64, 4_i64));
+    assert_eq!(v.xzwx(), i64vec4(1_i64, 3_i64, 4_i64, 1_i64));
+    assert_eq!(v.xzwy(), i64vec4(1_i64, 3_i64, 4_i64, 2_i64));
+    assert_eq!(v.xzwz(), i64vec4(1_i64, 3_i64, 4_i64, 3_i64));
+    assert_eq!(v.xzww(), i64vec4(1_i64, 3_i64, 4_i64, 4_i64));
+    assert_eq!(v.xwxx(), i64vec4(1_i64, 4_i64, 1_i64, 1_i64));
+    assert_eq!(v.xwxy(), i64vec4(1_i64, 4_i64, 1_i64, 2_i64));
+    assert_eq!(v.xwxz(), i64vec4(1_i64, 4_i64, 1_i64, 3_i64));
+    assert_eq!(v.xwxw(), i64vec4(1_i64, 4_i64, 1_i64, 4_i64));
+    assert_eq!(v.xwyx(), i64vec4(1_i64, 4_i64, 2_i64, 1_i64));
+    assert_eq!(v.xwyy(), i64vec4(1_i64, 4_i64, 2_i64, 2_i64));
+    assert_eq!(v.xwyz(), i64vec4(1_i64, 4_i64, 2_i64, 3_i64));
+    assert_eq!(v.xwyw(), i64vec4(1_i64, 4_i64, 2_i64, 4_i64));
+    assert_eq!(v.xwzx(), i64vec4(1_i64, 4_i64, 3_i64, 1_i64));
+    assert_eq!(v.xwzy(), i64vec4(1_i64, 4_i64, 3_i64, 2_i64));
+    assert_eq!(v.xwzz(), i64vec4(1_i64, 4_i64, 3_i64, 3_i64));
+    assert_eq!(v.xwzw(), i64vec4(1_i64, 4_i64, 3_i64, 4_i64));
+    assert_eq!(v.xwwx(), i64vec4(1_i64, 4_i64, 4_i64, 1_i64));
+    assert_eq!(v.xwwy(), i64vec4(1_i64, 4_i64, 4_i64, 2_i64));
+    assert_eq!(v.xwwz(), i64vec4(1_i64, 4_i64, 4_i64, 3_i64));
+    assert_eq!(v.xwww(), i64vec4(1_i64, 4_i64, 4_i64, 4_i64));
+    assert_eq!(v.yxxx(), i64vec4(2_i64, 1_i64, 1_i64, 1_i64));
+    assert_eq!(v.yxxy(), i64vec4(2_i64, 1_i64, 1_i64, 2_i64));
+    assert_eq!(v.yxxz(), i64vec4(2_i64, 1_i64, 1_i64, 3_i64));
+    assert_eq!(v.yxxw(), i64vec4(2_i64, 1_i64, 1_i64, 4_i64));
+    assert_eq!(v.yxyx(), i64vec4(2_i64, 1_i64, 2_i64, 1_i64));
+    assert_eq!(v.yxyy(), i64vec4(2_i64, 1_i64, 2_i64, 2_i64));
+    assert_eq!(v.yxyz(), i64vec4(2_i64, 1_i64, 2_i64, 3_i64));
+    assert_eq!(v.yxyw(), i64vec4(2_i64, 1_i64, 2_i64, 4_i64));
+    assert_eq!(v.yxzx(), i64vec4(2_i64, 1_i64, 3_i64, 1_i64));
+    assert_eq!(v.yxzy(), i64vec4(2_i64, 1_i64, 3_i64, 2_i64));
+    assert_eq!(v.yxzz(), i64vec4(2_i64, 1_i64, 3_i64, 3_i64));
+    assert_eq!(v.yxzw(), i64vec4(2_i64, 1_i64, 3_i64, 4_i64));
+    assert_eq!(v.yxwx(), i64vec4(2_i64, 1_i64, 4_i64, 1_i64));
+    assert_eq!(v.yxwy(), i64vec4(2_i64, 1_i64, 4_i64, 2_i64));
+    assert_eq!(v.yxwz(), i64vec4(2_i64, 1_i64, 4_i64, 3_i64));
+    assert_eq!(v.yxww(), i64vec4(2_i64, 1_i64, 4_i64, 4_i64));
+    assert_eq!(v.yyxx(), i64vec4(2_i64, 2_i64, 1_i64, 1_i64));
+    assert_eq!(v.yyxy(), i64vec4(2_i64, 2_i64, 1_i64, 2_i64));
+    assert_eq!(v.yyxz(), i64vec4(2_i64, 2_i64, 1_i64, 3_i64));
+    assert_eq!(v.yyxw(), i64vec4(2_i64, 2_i64, 1_i64, 4_i64));
+    assert_eq!(v.yyyx(), i64vec4(2_i64, 2_i64, 2_i64, 1_i64));
+    assert_eq!(v.yyyy(), i64vec4(2_i64, 2_i64, 2_i64, 2_i64));
+    assert_eq!(v.yyyz(), i64vec4(2_i64, 2_i64, 2_i64, 3_i64));
+    assert_eq!(v.yyyw(), i64vec4(2_i64, 2_i64, 2_i64, 4_i64));
+    assert_eq!(v.yyzx(), i64vec4(2_i64, 2_i64, 3_i64, 1_i64));
+    assert_eq!(v.yyzy(), i64vec4(2_i64, 2_i64, 3_i64, 2_i64));
+    assert_eq!(v.yyzz(), i64vec4(2_i64, 2_i64, 3_i64, 3_i64));
+    assert_eq!(v.yyzw(), i64vec4(2_i64, 2_i64, 3_i64, 4_i64));
+    assert_eq!(v.yywx(), i64vec4(2_i64, 2_i64, 4_i64, 1_i64));
+    assert_eq!(v.yywy(), i64vec4(2_i64, 2_i64, 4_i64, 2_i64));
+    assert_eq!(v.yywz(), i64vec4(2_i64, 2_i64, 4_i64, 3_i64));
+    assert_eq!(v.yyww(), i64vec4(2_i64, 2_i64, 4_i64, 4_i64));
+    assert_eq!(v.yzxx(), i64vec4(2_i64, 3_i64, 1_i64, 1_i64));
+    assert_eq!(v.yzxy(), i64vec4(2_i64, 3_i64, 1_i64, 2_i64));
+    assert_eq!(v.yzxz(), i64vec4(2_i64, 3_i64, 1_i64, 3_i64));
+    assert_eq!(v.yzxw(), i64vec4(2_i64, 3_i64, 1_i64, 4_i64));
+    assert_eq!(v.yzyx(), i64vec4(2_i64, 3_i64, 2_i64, 1_i64));
+    assert_eq!(v.yzyy(), i64vec4(2_i64, 3_i64, 2_i64, 2_i64));
+    assert_eq!(v.yzyz(), i64vec4(2_i64, 3_i64, 2_i64, 3_i64));
+    assert_eq!(v.yzyw(), i64vec4(2_i64, 3_i64, 2_i64, 4_i64));
+    assert_eq!(v.yzzx(), i64vec4(2_i64, 3_i64, 3_i64, 1_i64));
+    assert_eq!(v.yzzy(), i64vec4(2_i64, 3_i64, 3_i64, 2_i64));
+    assert_eq!(v.yzzz(), i64vec4(2_i64, 3_i64, 3_i64, 3_i64));
+    assert_eq!(v.yzzw(), i64vec4(2_i64, 3_i64, 3_i64, 4_i64));
+    assert_eq!(v.yzwx(), i64vec4(2_i64, 3_i64, 4_i64, 1_i64));
+    assert_eq!(v.yzwy(), i64vec4(2_i64, 3_i64, 4_i64, 2_i64));
+    assert_eq!(v.yzwz(), i64vec4(2_i64, 3_i64, 4_i64, 3_i64));
+    assert_eq!(v.yzww(), i64vec4(2_i64, 3_i64, 4_i64, 4_i64));
+    assert_eq!(v.ywxx(), i64vec4(2_i64, 4_i64, 1_i64, 1_i64));
+    assert_eq!(v.ywxy(), i64vec4(2_i64, 4_i64, 1_i64, 2_i64));
+    assert_eq!(v.ywxz(), i64vec4(2_i64, 4_i64, 1_i64, 3_i64));
+    assert_eq!(v.ywxw(), i64vec4(2_i64, 4_i64, 1_i64, 4_i64));
+    assert_eq!(v.ywyx(), i64vec4(2_i64, 4_i64, 2_i64, 1_i64));
+    assert_eq!(v.ywyy(), i64vec4(2_i64, 4_i64, 2_i64, 2_i64));
+    assert_eq!(v.ywyz(), i64vec4(2_i64, 4_i64, 2_i64, 3_i64));
+    assert_eq!(v.ywyw(), i64vec4(2_i64, 4_i64, 2_i64, 4_i64));
+    assert_eq!(v.ywzx(), i64vec4(2_i64, 4_i64, 3_i64, 1_i64));
+    assert_eq!(v.ywzy(), i64vec4(2_i64, 4_i64, 3_i64, 2_i64));
+    assert_eq!(v.ywzz(), i64vec4(2_i64, 4_i64, 3_i64, 3_i64));
+    assert_eq!(v.ywzw(), i64vec4(2_i64, 4_i64, 3_i64, 4_i64));
+    assert_eq!(v.ywwx(), i64vec4(2_i64, 4_i64, 4_i64, 1_i64));
+    assert_eq!(v.ywwy(), i64vec4(2_i64, 4_i64, 4_i64, 2_i64));
+    assert_eq!(v.ywwz(), i64vec4(2_i64, 4_i64, 4_i64, 3_i64));
+    assert_eq!(v.ywww(), i64vec4(2_i64, 4_i64, 4_i64, 4_i64));
+    assert_eq!(v.zxxx(), i64vec4(3_i64, 1_i64, 1_i64, 1_i64));
+    assert_eq!(v.zxxy(), i64vec4(3_i64, 1_i64, 1_i64, 2_i64));
+    assert_eq!(v.zxxz(), i64vec4(3_i64, 1_i64, 1_i64, 3_i64));
+    assert_eq!(v.zxxw(), i64vec4(3_i64, 1_i64, 1_i64, 4_i64));
+    assert_eq!(v.zxyx(), i64vec4(3_i64, 1_i64, 2_i64, 1_i64));
+    assert_eq!(v.zxyy(), i64vec4(3_i64, 1_i64, 2_i64, 2_i64));
+    assert_eq!(v.zxyz(), i64vec4(3_i64, 1_i64, 2_i64, 3_i64));
+    assert_eq!(v.zxyw(), i64vec4(3_i64, 1_i64, 2_i64, 4_i64));
+    assert_eq!(v.zxzx(), i64vec4(3_i64, 1_i64, 3_i64, 1_i64));
+    assert_eq!(v.zxzy(), i64vec4(3_i64, 1_i64, 3_i64, 2_i64));
+    assert_eq!(v.zxzz(), i64vec4(3_i64, 1_i64, 3_i64, 3_i64));
+    assert_eq!(v.zxzw(), i64vec4(3_i64, 1_i64, 3_i64, 4_i64));
+    assert_eq!(v.zxwx(), i64vec4(3_i64, 1_i64, 4_i64, 1_i64));
+    assert_eq!(v.zxwy(), i64vec4(3_i64, 1_i64, 4_i64, 2_i64));
+    assert_eq!(v.zxwz(), i64vec4(3_i64, 1_i64, 4_i64, 3_i64));
+    assert_eq!(v.zxww(), i64vec4(3_i64, 1_i64, 4_i64, 4_i64));
+    assert_eq!(v.zyxx(), i64vec4(3_i64, 2_i64, 1_i64, 1_i64));
+    assert_eq!(v.zyxy(), i64vec4(3_i64, 2_i64, 1_i64, 2_i64));
+    assert_eq!(v.zyxz(), i64vec4(3_i64, 2_i64, 1_i64, 3_i64));
+    assert_eq!(v.zyxw(), i64vec4(3_i64, 2_i64, 1_i64, 4_i64));
+    assert_eq!(v.zyyx(), i64vec4(3_i64, 2_i64, 2_i64, 1_i64));
+    assert_eq!(v.zyyy(), i64vec4(3_i64, 2_i64, 2_i64, 2_i64));
+    assert_eq!(v.zyyz(), i64vec4(3_i64, 2_i64, 2_i64, 3_i64));
+    assert_eq!(v.zyyw(), i64vec4(3_i64, 2_i64, 2_i64, 4_i64));
+    assert_eq!(v.zyzx(), i64vec4(3_i64, 2_i64, 3_i64, 1_i64));
+    assert_eq!(v.zyzy(), i64vec4(3_i64, 2_i64, 3_i64, 2_i64));
+    assert_eq!(v.zyzz(), i64vec4(3_i64, 2_i64, 3_i64, 3_i64));
+    assert_eq!(v.zyzw(), i64vec4(3_i64, 2_i64, 3_i64, 4_i64));
+    assert_eq!(v.zywx(), i64vec4(3_i64, 2_i64, 4_i64, 1_i64));
+    assert_eq!(v.zywy(), i64vec4(3_i64, 2_i64, 4_i64, 2_i64));
+    assert_eq!(v.zywz(), i64vec4(3_i64, 2_i64, 4_i64, 3_i64));
+    assert_eq!(v.zyww(), i64vec4(3_i64, 2_i64, 4_i64, 4_i64));
+    assert_eq!(v.zzxx(), i64vec4(3_i64, 3_i64, 1_i64, 1_i64));
+    assert_eq!(v.zzxy(), i64vec4(3_i64, 3_i64, 1_i64, 2_i64));
+    assert_eq!(v.zzxz(), i64vec4(3_i64, 3_i64, 1_i64, 3_i64));
+    assert_eq!(v.zzxw(), i64vec4(3_i64, 3_i64, 1_i64, 4_i64));
+    assert_eq!(v.zzyx(), i64vec4(3_i64, 3_i64, 2_i64, 1_i64));
+    assert_eq!(v.zzyy(), i64vec4(3_i64, 3_i64, 2_i64, 2_i64));
+    assert_eq!(v.zzyz(), i64vec4(3_i64, 3_i64, 2_i64, 3_i64));
+    assert_eq!(v.zzyw(), i64vec4(3_i64, 3_i64, 2_i64, 4_i64));
+    assert_eq!(v.zzzx(), i64vec4(3_i64, 3_i64, 3_i64, 1_i64));
+    assert_eq!(v.zzzy(), i64vec4(3_i64, 3_i64, 3_i64, 2_i64));
+    assert_eq!(v.zzzz(), i64vec4(3_i64, 3_i64, 3_i64, 3_i64));
+    assert_eq!(v.zzzw(), i64vec4(3_i64, 3_i64, 3_i64, 4_i64));
+    assert_eq!(v.zzwx(), i64vec4(3_i64, 3_i64, 4_i64, 1_i64));
+    assert_eq!(v.zzwy(), i64vec4(3_i64, 3_i64, 4_i64, 2_i64));
+    assert_eq!(v.zzwz(), i64vec4(3_i64, 3_i64, 4_i64, 3_i64));
+    assert_eq!(v.zzww(), i64vec4(3_i64, 3_i64, 4_i64, 4_i64));
+    assert_eq!(v.zwxx(), i64vec4(3_i64, 4_i64, 1_i64, 1_i64));
+    assert_eq!(v.zwxy(), i64vec4(3_i64, 4_i64, 1_i64, 2_i64));
+    assert_eq!(v.zwxz(), i64vec4(3_i64, 4_i64, 1_i64, 3_i64));
+    assert_eq!(v.zwxw(), i64vec4(3_i64, 4_i64, 1_i64, 4_i64));
+    assert_eq!(v.zwyx(), i64vec4(3_i64, 4_i64, 2_i64, 1_i64));
+    assert_eq!(v.zwyy(), i64vec4(3_i64, 4_i64, 2_i64, 2_i64));
+    assert_eq!(v.zwyz(), i64vec4(3_i64, 4_i64, 2_i64, 3_i64));
+    assert_eq!(v.zwyw(), i64vec4(3_i64, 4_i64, 2_i64, 4_i64));
+    assert_eq!(v.zwzx(), i64vec4(3_i64, 4_i64, 3_i64, 1_i64));
+    assert_eq!(v.zwzy(), i64vec4(3_i64, 4_i64, 3_i64, 2_i64));
+    assert_eq!(v.zwzz(), i64vec4(3_i64, 4_i64, 3_i64, 3_i64));
+    assert_eq!(v.zwzw(), i64vec4(3_i64, 4_i64, 3_i64, 4_i64));
+    assert_eq!(v.zwwx(), i64vec4(3_i64, 4_i64, 4_i64, 1_i64));
+    assert_eq!(v.zwwy(), i64vec4(3_i64, 4_i64, 4_i64, 2_i64));
+    assert_eq!(v.zwwz(), i64vec4(3_i64, 4_i64, 4_i64, 3_i64));
+    assert_eq!(v.zwww(), i64vec4(3_i64, 4_i64, 4_i64, 4_i64));
+    assert_eq!(v.wxxx(), i64vec4(4_i64, 1_i64, 1_i64, 1_i64));
+    assert_eq!(v.wxxy(), i64vec4(4_i64, 1_i64, 1_i64, 2_i64));
+    assert_eq!(v.wxxz(), i64vec4(4_i64, 1_i64, 1_i64, 3_i64));
+    assert_eq!(v.wxxw(), i64vec4(4_i64, 1_i64, 1_i64, 4_i64));
+    assert_eq!(v.wxyx(), i64vec4(4_i64, 1_i64, 2_i64, 1_i64));
+    assert_eq!(v.wxyy(), i64vec4(4_i64, 1_i64, 2_i64, 2_i64));
+    assert_eq!(v.wxyz(), i64vec4(4_i64, 1_i64, 2_i64, 3_i64));
+    assert_eq!(v.wxyw(), i64vec4(4_i64, 1_i64, 2_i64, 4_i64));
+    assert_eq!(v.wxzx(), i64vec4(4_i64, 1_i64, 3_i64, 1_i64));
+    assert_eq!(v.wxzy(), i64vec4(4_i64, 1_i64, 3_i64, 2_i64));
+    assert_eq!(v.wxzz(), i64vec4(4_i64, 1_i64, 3_i64, 3_i64));
+    assert_eq!(v.wxzw(), i64vec4(4_i64, 1_i64, 3_i64, 4_i64));
+    assert_eq!(v.wxwx(), i64vec4(4_i64, 1_i64, 4_i64, 1_i64));
+    assert_eq!(v.wxwy(), i64vec4(4_i64, 1_i64, 4_i64, 2_i64));
+    assert_eq!(v.wxwz(), i64vec4(4_i64, 1_i64, 4_i64, 3_i64));
+    assert_eq!(v.wxww(), i64vec4(4_i64, 1_i64, 4_i64, 4_i64));
+    assert_eq!(v.wyxx(), i64vec4(4_i64, 2_i64, 1_i64, 1_i64));
+    assert_eq!(v.wyxy(), i64vec4(4_i64, 2_i64, 1_i64, 2_i64));
+    assert_eq!(v.wyxz(), i64vec4(4_i64, 2_i64, 1_i64, 3_i64));
+    assert_eq!(v.wyxw(), i64vec4(4_i64, 2_i64, 1_i64, 4_i64));
+    assert_eq!(v.wyyx(), i64vec4(4_i64, 2_i64, 2_i64, 1_i64));
+    assert_eq!(v.wyyy(), i64vec4(4_i64, 2_i64, 2_i64, 2_i64));
+    assert_eq!(v.wyyz(), i64vec4(4_i64, 2_i64, 2_i64, 3_i64));
+    assert_eq!(v.wyyw(), i64vec4(4_i64, 2_i64, 2_i64, 4_i64));
+    assert_eq!(v.wyzx(), i64vec4(4_i64, 2_i64, 3_i64, 1_i64));
+    assert_eq!(v.wyzy(), i64vec4(4_i64, 2_i64, 3_i64, 2_i64));
+    assert_eq!(v.wyzz(), i64vec4(4_i64, 2_i64, 3_i64, 3_i64));
+    assert_eq!(v.wyzw(), i64vec4(4_i64, 2_i64, 3_i64, 4_i64));
+    assert_eq!(v.wywx(), i64vec4(4_i64, 2_i64, 4_i64, 1_i64));
+    assert_eq!(v.wywy(), i64vec4(4_i64, 2_i64, 4_i64, 2_i64));
+    assert_eq!(v.wywz(), i64vec4(4_i64, 2_i64, 4_i64, 3_i64));
+    assert_eq!(v.wyww(), i64vec4(4_i64, 2_i64, 4_i64, 4_i64));
+    assert_eq!(v.wzxx(), i64vec4(4_i64, 3_i64, 1_i64, 1_i64));
+    assert_eq!(v.wzxy(), i64vec4(4_i64, 3_i64, 1_i64, 2_i64));
+    assert_eq!(v.wzxz(), i64vec4(4_i64, 3_i64, 1_i64, 3_i64));
+    assert_eq!(v.wzxw(), i64vec4(4_i64, 3_i64, 1_i64, 4_i64));
+    assert_eq!(v.wzyx(), i64vec4(4_i64, 3_i64, 2_i64, 1_i64));
+    assert_eq!(v.wzyy(), i64vec4(4_i64, 3_i64, 2_i64, 2_i64));
+    assert_eq!(v.wzyz(), i64vec4(4_i64, 3_i64, 2_i64, 3_i64));
+    assert_eq!(v.wzyw(), i64vec4(4_i64, 3_i64, 2_i64, 4_i64));
+    assert_eq!(v.wzzx(), i64vec4(4_i64, 3_i64, 3_i64, 1_i64));
+    assert_eq!(v.wzzy(), i64vec4(4_i64, 3_i64, 3_i64, 2_i64));
+    assert_eq!(v.wzzz(), i64vec4(4_i64, 3_i64, 3_i64, 3_i64));
+    assert_eq!(v.wzzw(), i64vec4(4_i64, 3_i64, 3_i64, 4_i64));
+    assert_eq!(v.wzwx(), i64vec4(4_i64, 3_i64, 4_i64, 1_i64));
+    assert_eq!(v.wzwy(), i64vec4(4_i64, 3_i64, 4_i64, 2_i64));
+    assert_eq!(v.wzwz(), i64vec4(4_i64, 3_i64, 4_i64, 3_i64));
+    assert_eq!(v.wzww(), i64vec4(4_i64, 3_i64, 4_i64, 4_i64));
+    assert_eq!(v.wwxx(), i64vec4(4_i64, 4_i64, 1_i64, 1_i64));
+    assert_eq!(v.wwxy(), i64vec4(4_i64, 4_i64, 1_i64, 2_i64));
+    assert_eq!(v.wwxz(), i64vec4(4_i64, 4_i64, 1_i64, 3_i64));
+    assert_eq!(v.wwxw(), i64vec4(4_i64, 4_i64, 1_i64, 4_i64));
+    assert_eq!(v.wwyx(), i64vec4(4_i64, 4_i64, 2_i64, 1_i64));
+    assert_eq!(v.wwyy(), i64vec4(4_i64, 4_i64, 2_i64, 2_i64));
+    assert_eq!(v.wwyz(), i64vec4(4_i64, 4_i64, 2_i64, 3_i64));
+    assert_eq!(v.wwyw(), i64vec4(4_i64, 4_i64, 2_i64, 4_i64));
+    assert_eq!(v.wwzx(), i64vec4(4_i64, 4_i64, 3_i64, 1_i64));
+    assert_eq!(v.wwzy(), i64vec4(4_i64, 4_i64, 3_i64, 2_i64));
+    assert_eq!(v.wwzz(), i64vec4(4_i64, 4_i64, 3_i64, 3_i64));
+    assert_eq!(v.wwzw(), i64vec4(4_i64, 4_i64, 3_i64, 4_i64));
+    assert_eq!(v.wwwx(), i64vec4(4_i64, 4_i64, 4_i64, 1_i64));
+    assert_eq!(v.wwwy(), i64vec4(4_i64, 4_i64, 4_i64, 2_i64));
+    assert_eq!(v.wwwz(), i64vec4(4_i64, 4_i64, 4_i64, 3_i64));
+    assert_eq!(v.wwww(), i64vec4(4_i64, 4_i64, 4_i64, 4_i64));
+    assert_eq!(v.xxx(), i64vec3(1_i64, 1_i64, 1_i64));
+    assert_eq!(v.xxy(), i64vec3(1_i64, 1_i64, 2_i64));
+    assert_eq!(v.xxz(), i64vec3(1_i64, 1_i64, 3_i64));
+    assert_eq!(v.xxw(), i64vec3(1_i64, 1_i64, 4_i64));
+    assert_eq!(v.xyx(), i64vec3(1_i64, 2_i64, 1_i64));
+    assert_eq!(v.xyy(), i64vec3(1_i64, 2_i64, 2_i64));
+    assert_eq!(v.xyz(), i64vec3(1_i64, 2_i64, 3_i64));
+    assert_eq!(v.xyw(), i64vec3(1_i64, 2_i64, 4_i64));
+    assert_eq!(v.xzx(), i64vec3(1_i64, 3_i64, 1_i64));
+    assert_eq!(v.xzy(), i64vec3(1_i64, 3_i64, 2_i64));
+    assert_eq!(v.xzz(), i64vec3(1_i64, 3_i64, 3_i64));
+    assert_eq!(v.xzw(), i64vec3(1_i64, 3_i64, 4_i64));
+    assert_eq!(v.xwx(), i64vec3(1_i64, 4_i64, 1_i64));
+    assert_eq!(v.xwy(), i64vec3(1_i64, 4_i64, 2_i64));
+    assert_eq!(v.xwz(), i64vec3(1_i64, 4_i64, 3_i64));
+    assert_eq!(v.xww(), i64vec3(1_i64, 4_i64, 4_i64));
+    assert_eq!(v.yxx(), i64vec3(2_i64, 1_i64, 1_i64));
+    assert_eq!(v.yxy(), i64vec3(2_i64, 1_i64, 2_i64));
+    assert_eq!(v.yxz(), i64vec3(2_i64, 1_i64, 3_i64));
+    assert_eq!(v.yxw(), i64vec3(2_i64, 1_i64, 4_i64));
+    assert_eq!(v.yyx(), i64vec3(2_i64, 2_i64, 1_i64));
+    assert_eq!(v.yyy(), i64vec3(2_i64, 2_i64, 2_i64));
+    assert_eq!(v.yyz(), i64vec3(2_i64, 2_i64, 3_i64));
+    assert_eq!(v.yyw(), i64vec3(2_i64, 2_i64, 4_i64));
+    assert_eq!(v.yzx(), i64vec3(2_i64, 3_i64, 1_i64));
+    assert_eq!(v.yzy(), i64vec3(2_i64, 3_i64, 2_i64));
+    assert_eq!(v.yzz(), i64vec3(2_i64, 3_i64, 3_i64));
+    assert_eq!(v.yzw(), i64vec3(2_i64, 3_i64, 4_i64));
+    assert_eq!(v.ywx(), i64vec3(2_i64, 4_i64, 1_i64));
+    assert_eq!(v.ywy(), i64vec3(2_i64, 4_i64, 2_i64));
+    assert_eq!(v.ywz(), i64vec3(2_i64, 4_i64, 3_i64));
+    assert_eq!(v.yww(), i64vec3(2_i64, 4_i64, 4_i64));
+    assert_eq!(v.zxx(), i64vec3(3_i64, 1_i64, 1_i64));
+    assert_eq!(v.zxy(), i64vec3(3_i64, 1_i64, 2_i64));
+    assert_eq!(v.zxz(), i64vec3(3_i64, 1_i64, 3_i64));
+    assert_eq!(v.zxw(), i64vec3(3_i64, 1_i64, 4_i64));
+    assert_eq!(v.zyx(), i64vec3(3_i64, 2_i64, 1_i64));
+    assert_eq!(v.zyy(), i64vec3(3_i64, 2_i64, 2_i64));
+    assert_eq!(v.zyz(), i64vec3(3_i64, 2_i64, 3_i64));
+    assert_eq!(v.zyw(), i64vec3(3_i64, 2_i64, 4_i64));
+    assert_eq!(v.zzx(), i64vec3(3_i64, 3_i64, 1_i64));
+    assert_eq!(v.zzy(), i64vec3(3_i64, 3_i64, 2_i64));
+    assert_eq!(v.zzz(), i64vec3(3_i64, 3_i64, 3_i64));
+    assert_eq!(v.zzw(), i64vec3(3_i64, 3_i64, 4_i64));
+    assert_eq!(v.zwx(), i64vec3(3_i64, 4_i64, 1_i64));
+    assert_eq!(v.zwy(), i64vec3(3_i64, 4_i64, 2_i64));
+    assert_eq!(v.zwz(), i64vec3(3_i64, 4_i64, 3_i64));
+    assert_eq!(v.zww(), i64vec3(3_i64, 4_i64, 4_i64));
+    assert_eq!(v.wxx(), i64vec3(4_i64, 1_i64, 1_i64));
+    assert_eq!(v.wxy(), i64vec3(4_i64, 1_i64, 2_i64));
+    assert_eq!(v.wxz(), i64vec3(4_i64, 1_i64, 3_i64));
+    assert_eq!(v.wxw(), i64vec3(4_i64, 1_i64, 4_i64));
+    assert_eq!(v.wyx(), i64vec3(4_i64, 2_i64, 1_i64));
+    assert_eq!(v.wyy(), i64vec3(4_i64, 2_i64, 2_i64));
+    assert_eq!(v.wyz(), i64vec3(4_i64, 2_i64, 3_i64));
+    assert_eq!(v.wyw(), i64vec3(4_i64, 2_i64, 4_i64));
+    assert_eq!(v.wzx(), i64vec3(4_i64, 3_i64, 1_i64));
+    assert_eq!(v.wzy(), i64vec3(4_i64, 3_i64, 2_i64));
+    assert_eq!(v.wzz(), i64vec3(4_i64, 3_i64, 3_i64));
+    assert_eq!(v.wzw(), i64vec3(4_i64, 3_i64, 4_i64));
+    assert_eq!(v.wwx(), i64vec3(4_i64, 4_i64, 1_i64));
+    assert_eq!(v.wwy(), i64vec3(4_i64, 4_i64, 2_i64));
+    assert_eq!(v.wwz(), i64vec3(4_i64, 4_i64, 3_i64));
+    assert_eq!(v.www(), i64vec3(4_i64, 4_i64, 4_i64));
+    assert_eq!(v.xx(), i64vec2(1_i64, 1_i64));
+    assert_eq!(v.xy(), i64vec2(1_i64, 2_i64));
+    assert_eq!(v.xz(), i64vec2(1_i64, 3_i64));
+    assert_eq!(v.xw(), i64vec2(1_i64, 4_i64));
+    assert_eq!(v.yx(), i64vec2(2_i64, 1_i64));
+    assert_eq!(v.yy(), i64vec2(2_i64, 2_i64));
+    assert_eq!(v.yz(), i64vec2(2_i64, 3_i64));
+    assert_eq!(v.yw(), i64vec2(2_i64, 4_i64));
+    assert_eq!(v.zx(), i64vec2(3_i64, 1_i64));
+    assert_eq!(v.zy(), i64vec2(3_i64, 2_i64));
+    assert_eq!(v.zz(), i64vec2(3_i64, 3_i64));
+    assert_eq!(v.zw(), i64vec2(3_i64, 4_i64));
+    assert_eq!(v.wx(), i64vec2(4_i64, 1_i64));
+    assert_eq!(v.wy(), i64vec2(4_i64, 2_i64));
+    assert_eq!(v.wz(), i64vec2(4_i64, 3_i64));
+    assert_eq!(v.ww(), i64vec2(4_i64, 4_i64));
+});
+
+glam_test!(test_i64vec3_swizzles, {
+    let v = i64vec3(1_i64, 2_i64, 3_i64);
+    assert_eq!(v, v.xyz());
+    assert_eq!(v.xxxx(), i64vec4(1_i64, 1_i64, 1_i64, 1_i64));
+    assert_eq!(v.xxxy(), i64vec4(1_i64, 1_i64, 1_i64, 2_i64));
+    assert_eq!(v.xxxz(), i64vec4(1_i64, 1_i64, 1_i64, 3_i64));
+    assert_eq!(v.xxyx(), i64vec4(1_i64, 1_i64, 2_i64, 1_i64));
+    assert_eq!(v.xxyy(), i64vec4(1_i64, 1_i64, 2_i64, 2_i64));
+    assert_eq!(v.xxyz(), i64vec4(1_i64, 1_i64, 2_i64, 3_i64));
+    assert_eq!(v.xxzx(), i64vec4(1_i64, 1_i64, 3_i64, 1_i64));
+    assert_eq!(v.xxzy(), i64vec4(1_i64, 1_i64, 3_i64, 2_i64));
+    assert_eq!(v.xxzz(), i64vec4(1_i64, 1_i64, 3_i64, 3_i64));
+    assert_eq!(v.xyxx(), i64vec4(1_i64, 2_i64, 1_i64, 1_i64));
+    assert_eq!(v.xyxy(), i64vec4(1_i64, 2_i64, 1_i64, 2_i64));
+    assert_eq!(v.xyxz(), i64vec4(1_i64, 2_i64, 1_i64, 3_i64));
+    assert_eq!(v.xyyx(), i64vec4(1_i64, 2_i64, 2_i64, 1_i64));
+    assert_eq!(v.xyyy(), i64vec4(1_i64, 2_i64, 2_i64, 2_i64));
+    assert_eq!(v.xyyz(), i64vec4(1_i64, 2_i64, 2_i64, 3_i64));
+    assert_eq!(v.xyzx(), i64vec4(1_i64, 2_i64, 3_i64, 1_i64));
+    assert_eq!(v.xyzy(), i64vec4(1_i64, 2_i64, 3_i64, 2_i64));
+    assert_eq!(v.xyzz(), i64vec4(1_i64, 2_i64, 3_i64, 3_i64));
+    assert_eq!(v.xzxx(), i64vec4(1_i64, 3_i64, 1_i64, 1_i64));
+    assert_eq!(v.xzxy(), i64vec4(1_i64, 3_i64, 1_i64, 2_i64));
+    assert_eq!(v.xzxz(), i64vec4(1_i64, 3_i64, 1_i64, 3_i64));
+    assert_eq!(v.xzyx(), i64vec4(1_i64, 3_i64, 2_i64, 1_i64));
+    assert_eq!(v.xzyy(), i64vec4(1_i64, 3_i64, 2_i64, 2_i64));
+    assert_eq!(v.xzyz(), i64vec4(1_i64, 3_i64, 2_i64, 3_i64));
+    assert_eq!(v.xzzx(), i64vec4(1_i64, 3_i64, 3_i64, 1_i64));
+    assert_eq!(v.xzzy(), i64vec4(1_i64, 3_i64, 3_i64, 2_i64));
+    assert_eq!(v.xzzz(), i64vec4(1_i64, 3_i64, 3_i64, 3_i64));
+    assert_eq!(v.yxxx(), i64vec4(2_i64, 1_i64, 1_i64, 1_i64));
+    assert_eq!(v.yxxy(), i64vec4(2_i64, 1_i64, 1_i64, 2_i64));
+    assert_eq!(v.yxxz(), i64vec4(2_i64, 1_i64, 1_i64, 3_i64));
+    assert_eq!(v.yxyx(), i64vec4(2_i64, 1_i64, 2_i64, 1_i64));
+    assert_eq!(v.yxyy(), i64vec4(2_i64, 1_i64, 2_i64, 2_i64));
+    assert_eq!(v.yxyz(), i64vec4(2_i64, 1_i64, 2_i64, 3_i64));
+    assert_eq!(v.yxzx(), i64vec4(2_i64, 1_i64, 3_i64, 1_i64));
+    assert_eq!(v.yxzy(), i64vec4(2_i64, 1_i64, 3_i64, 2_i64));
+    assert_eq!(v.yxzz(), i64vec4(2_i64, 1_i64, 3_i64, 3_i64));
+    assert_eq!(v.yyxx(), i64vec4(2_i64, 2_i64, 1_i64, 1_i64));
+    assert_eq!(v.yyxy(), i64vec4(2_i64, 2_i64, 1_i64, 2_i64));
+    assert_eq!(v.yyxz(), i64vec4(2_i64, 2_i64, 1_i64, 3_i64));
+    assert_eq!(v.yyyx(), i64vec4(2_i64, 2_i64, 2_i64, 1_i64));
+    assert_eq!(v.yyyy(), i64vec4(2_i64, 2_i64, 2_i64, 2_i64));
+    assert_eq!(v.yyyz(), i64vec4(2_i64, 2_i64, 2_i64, 3_i64));
+    assert_eq!(v.yyzx(), i64vec4(2_i64, 2_i64, 3_i64, 1_i64));
+    assert_eq!(v.yyzy(), i64vec4(2_i64, 2_i64, 3_i64, 2_i64));
+    assert_eq!(v.yyzz(), i64vec4(2_i64, 2_i64, 3_i64, 3_i64));
+    assert_eq!(v.yzxx(), i64vec4(2_i64, 3_i64, 1_i64, 1_i64));
+    assert_eq!(v.yzxy(), i64vec4(2_i64, 3_i64, 1_i64, 2_i64));
+    assert_eq!(v.yzxz(), i64vec4(2_i64, 3_i64, 1_i64, 3_i64));
+    assert_eq!(v.yzyx(), i64vec4(2_i64, 3_i64, 2_i64, 1_i64));
+    assert_eq!(v.yzyy(), i64vec4(2_i64, 3_i64, 2_i64, 2_i64));
+    assert_eq!(v.yzyz(), i64vec4(2_i64, 3_i64, 2_i64, 3_i64));
+    assert_eq!(v.yzzx(), i64vec4(2_i64, 3_i64, 3_i64, 1_i64));
+    assert_eq!(v.yzzy(), i64vec4(2_i64, 3_i64, 3_i64, 2_i64));
+    assert_eq!(v.yzzz(), i64vec4(2_i64, 3_i64, 3_i64, 3_i64));
+    assert_eq!(v.zxxx(), i64vec4(3_i64, 1_i64, 1_i64, 1_i64));
+    assert_eq!(v.zxxy(), i64vec4(3_i64, 1_i64, 1_i64, 2_i64));
+    assert_eq!(v.zxxz(), i64vec4(3_i64, 1_i64, 1_i64, 3_i64));
+    assert_eq!(v.zxyx(), i64vec4(3_i64, 1_i64, 2_i64, 1_i64));
+    assert_eq!(v.zxyy(), i64vec4(3_i64, 1_i64, 2_i64, 2_i64));
+    assert_eq!(v.zxyz(), i64vec4(3_i64, 1_i64, 2_i64, 3_i64));
+    assert_eq!(v.zxzx(), i64vec4(3_i64, 1_i64, 3_i64, 1_i64));
+    assert_eq!(v.zxzy(), i64vec4(3_i64, 1_i64, 3_i64, 2_i64));
+    assert_eq!(v.zxzz(), i64vec4(3_i64, 1_i64, 3_i64, 3_i64));
+    assert_eq!(v.zyxx(), i64vec4(3_i64, 2_i64, 1_i64, 1_i64));
+    assert_eq!(v.zyxy(), i64vec4(3_i64, 2_i64, 1_i64, 2_i64));
+    assert_eq!(v.zyxz(), i64vec4(3_i64, 2_i64, 1_i64, 3_i64));
+    assert_eq!(v.zyyx(), i64vec4(3_i64, 2_i64, 2_i64, 1_i64));
+    assert_eq!(v.zyyy(), i64vec4(3_i64, 2_i64, 2_i64, 2_i64));
+    assert_eq!(v.zyyz(), i64vec4(3_i64, 2_i64, 2_i64, 3_i64));
+    assert_eq!(v.zyzx(), i64vec4(3_i64, 2_i64, 3_i64, 1_i64));
+    assert_eq!(v.zyzy(), i64vec4(3_i64, 2_i64, 3_i64, 2_i64));
+    assert_eq!(v.zyzz(), i64vec4(3_i64, 2_i64, 3_i64, 3_i64));
+    assert_eq!(v.zzxx(), i64vec4(3_i64, 3_i64, 1_i64, 1_i64));
+    assert_eq!(v.zzxy(), i64vec4(3_i64, 3_i64, 1_i64, 2_i64));
+    assert_eq!(v.zzxz(), i64vec4(3_i64, 3_i64, 1_i64, 3_i64));
+    assert_eq!(v.zzyx(), i64vec4(3_i64, 3_i64, 2_i64, 1_i64));
+    assert_eq!(v.zzyy(), i64vec4(3_i64, 3_i64, 2_i64, 2_i64));
+    assert_eq!(v.zzyz(), i64vec4(3_i64, 3_i64, 2_i64, 3_i64));
+    assert_eq!(v.zzzx(), i64vec4(3_i64, 3_i64, 3_i64, 1_i64));
+    assert_eq!(v.zzzy(), i64vec4(3_i64, 3_i64, 3_i64, 2_i64));
+    assert_eq!(v.zzzz(), i64vec4(3_i64, 3_i64, 3_i64, 3_i64));
+    assert_eq!(v.xxx(), i64vec3(1_i64, 1_i64, 1_i64));
+    assert_eq!(v.xxy(), i64vec3(1_i64, 1_i64, 2_i64));
+    assert_eq!(v.xxz(), i64vec3(1_i64, 1_i64, 3_i64));
+    assert_eq!(v.xyx(), i64vec3(1_i64, 2_i64, 1_i64));
+    assert_eq!(v.xyy(), i64vec3(1_i64, 2_i64, 2_i64));
+    assert_eq!(v.xzx(), i64vec3(1_i64, 3_i64, 1_i64));
+    assert_eq!(v.xzy(), i64vec3(1_i64, 3_i64, 2_i64));
+    assert_eq!(v.xzz(), i64vec3(1_i64, 3_i64, 3_i64));
+    assert_eq!(v.yxx(), i64vec3(2_i64, 1_i64, 1_i64));
+    assert_eq!(v.yxy(), i64vec3(2_i64, 1_i64, 2_i64));
+    assert_eq!(v.yxz(), i64vec3(2_i64, 1_i64, 3_i64));
+    assert_eq!(v.yyx(), i64vec3(2_i64, 2_i64, 1_i64));
+    assert_eq!(v.yyy(), i64vec3(2_i64, 2_i64, 2_i64));
+    assert_eq!(v.yyz(), i64vec3(2_i64, 2_i64, 3_i64));
+    assert_eq!(v.yzx(), i64vec3(2_i64, 3_i64, 1_i64));
+    assert_eq!(v.yzy(), i64vec3(2_i64, 3_i64, 2_i64));
+    assert_eq!(v.yzz(), i64vec3(2_i64, 3_i64, 3_i64));
+    assert_eq!(v.zxx(), i64vec3(3_i64, 1_i64, 1_i64));
+    assert_eq!(v.zxy(), i64vec3(3_i64, 1_i64, 2_i64));
+    assert_eq!(v.zxz(), i64vec3(3_i64, 1_i64, 3_i64));
+    assert_eq!(v.zyx(), i64vec3(3_i64, 2_i64, 1_i64));
+    assert_eq!(v.zyy(), i64vec3(3_i64, 2_i64, 2_i64));
+    assert_eq!(v.zyz(), i64vec3(3_i64, 2_i64, 3_i64));
+    assert_eq!(v.zzx(), i64vec3(3_i64, 3_i64, 1_i64));
+    assert_eq!(v.zzy(), i64vec3(3_i64, 3_i64, 2_i64));
+    assert_eq!(v.zzz(), i64vec3(3_i64, 3_i64, 3_i64));
+    assert_eq!(v.xx(), i64vec2(1_i64, 1_i64));
+    assert_eq!(v.xy(), i64vec2(1_i64, 2_i64));
+    assert_eq!(v.xz(), i64vec2(1_i64, 3_i64));
+    assert_eq!(v.yx(), i64vec2(2_i64, 1_i64));
+    assert_eq!(v.yy(), i64vec2(2_i64, 2_i64));
+    assert_eq!(v.yz(), i64vec2(2_i64, 3_i64));
+    assert_eq!(v.zx(), i64vec2(3_i64, 1_i64));
+    assert_eq!(v.zy(), i64vec2(3_i64, 2_i64));
+    assert_eq!(v.zz(), i64vec2(3_i64, 3_i64));
+});
+
+glam_test!(test_i64vec2_swizzles, {
+    let v = i64vec2(1_i64, 2_i64);
+    assert_eq!(v, v.xy());
+    assert_eq!(v.xxxx(), i64vec4(1_i64, 1_i64, 1_i64, 1_i64));
+    assert_eq!(v.xxxy(), i64vec4(1_i64, 1_i64, 1_i64, 2_i64));
+    assert_eq!(v.xxyx(), i64vec4(1_i64, 1_i64, 2_i64, 1_i64));
+    assert_eq!(v.xxyy(), i64vec4(1_i64, 1_i64, 2_i64, 2_i64));
+    assert_eq!(v.xyxx(), i64vec4(1_i64, 2_i64, 1_i64, 1_i64));
+    assert_eq!(v.xyxy(), i64vec4(1_i64, 2_i64, 1_i64, 2_i64));
+    assert_eq!(v.xyyx(), i64vec4(1_i64, 2_i64, 2_i64, 1_i64));
+    assert_eq!(v.xyyy(), i64vec4(1_i64, 2_i64, 2_i64, 2_i64));
+    assert_eq!(v.yxxx(), i64vec4(2_i64, 1_i64, 1_i64, 1_i64));
+    assert_eq!(v.yxxy(), i64vec4(2_i64, 1_i64, 1_i64, 2_i64));
+    assert_eq!(v.yxyx(), i64vec4(2_i64, 1_i64, 2_i64, 1_i64));
+    assert_eq!(v.yxyy(), i64vec4(2_i64, 1_i64, 2_i64, 2_i64));
+    assert_eq!(v.yyxx(), i64vec4(2_i64, 2_i64, 1_i64, 1_i64));
+    assert_eq!(v.yyxy(), i64vec4(2_i64, 2_i64, 1_i64, 2_i64));
+    assert_eq!(v.yyyx(), i64vec4(2_i64, 2_i64, 2_i64, 1_i64));
+    assert_eq!(v.yyyy(), i64vec4(2_i64, 2_i64, 2_i64, 2_i64));
+    assert_eq!(v.xxx(), i64vec3(1_i64, 1_i64, 1_i64));
+    assert_eq!(v.xxy(), i64vec3(1_i64, 1_i64, 2_i64));
+    assert_eq!(v.xyx(), i64vec3(1_i64, 2_i64, 1_i64));
+    assert_eq!(v.xyy(), i64vec3(1_i64, 2_i64, 2_i64));
+    assert_eq!(v.yxx(), i64vec3(2_i64, 1_i64, 1_i64));
+    assert_eq!(v.yxy(), i64vec3(2_i64, 1_i64, 2_i64));
+    assert_eq!(v.yyx(), i64vec3(2_i64, 2_i64, 1_i64));
+    assert_eq!(v.yyy(), i64vec3(2_i64, 2_i64, 2_i64));
+    assert_eq!(v.xx(), i64vec2(1_i64, 1_i64));
+    assert_eq!(v.yx(), i64vec2(2_i64, 1_i64));
+    assert_eq!(v.yy(), i64vec2(2_i64, 2_i64));
+});
diff --git a/tests/swizzles_u16.rs b/tests/swizzles_u16.rs
new file mode 100644
index 0000000..e72b301
--- /dev/null
+++ b/tests/swizzles_u16.rs
@@ -0,0 +1,497 @@
+// Generated by swizzlegen. Do not edit.
+#[macro_use]
+mod support;
+use glam::*;
+
+glam_test!(test_u16vec4_swizzles, {
+    let v = u16vec4(1_u16, 2_u16, 3_u16, 4_u16);
+    assert_eq!(v, v.xyzw());
+    assert_eq!(v.xxxx(), u16vec4(1_u16, 1_u16, 1_u16, 1_u16));
+    assert_eq!(v.xxxy(), u16vec4(1_u16, 1_u16, 1_u16, 2_u16));
+    assert_eq!(v.xxxz(), u16vec4(1_u16, 1_u16, 1_u16, 3_u16));
+    assert_eq!(v.xxxw(), u16vec4(1_u16, 1_u16, 1_u16, 4_u16));
+    assert_eq!(v.xxyx(), u16vec4(1_u16, 1_u16, 2_u16, 1_u16));
+    assert_eq!(v.xxyy(), u16vec4(1_u16, 1_u16, 2_u16, 2_u16));
+    assert_eq!(v.xxyz(), u16vec4(1_u16, 1_u16, 2_u16, 3_u16));
+    assert_eq!(v.xxyw(), u16vec4(1_u16, 1_u16, 2_u16, 4_u16));
+    assert_eq!(v.xxzx(), u16vec4(1_u16, 1_u16, 3_u16, 1_u16));
+    assert_eq!(v.xxzy(), u16vec4(1_u16, 1_u16, 3_u16, 2_u16));
+    assert_eq!(v.xxzz(), u16vec4(1_u16, 1_u16, 3_u16, 3_u16));
+    assert_eq!(v.xxzw(), u16vec4(1_u16, 1_u16, 3_u16, 4_u16));
+    assert_eq!(v.xxwx(), u16vec4(1_u16, 1_u16, 4_u16, 1_u16));
+    assert_eq!(v.xxwy(), u16vec4(1_u16, 1_u16, 4_u16, 2_u16));
+    assert_eq!(v.xxwz(), u16vec4(1_u16, 1_u16, 4_u16, 3_u16));
+    assert_eq!(v.xxww(), u16vec4(1_u16, 1_u16, 4_u16, 4_u16));
+    assert_eq!(v.xyxx(), u16vec4(1_u16, 2_u16, 1_u16, 1_u16));
+    assert_eq!(v.xyxy(), u16vec4(1_u16, 2_u16, 1_u16, 2_u16));
+    assert_eq!(v.xyxz(), u16vec4(1_u16, 2_u16, 1_u16, 3_u16));
+    assert_eq!(v.xyxw(), u16vec4(1_u16, 2_u16, 1_u16, 4_u16));
+    assert_eq!(v.xyyx(), u16vec4(1_u16, 2_u16, 2_u16, 1_u16));
+    assert_eq!(v.xyyy(), u16vec4(1_u16, 2_u16, 2_u16, 2_u16));
+    assert_eq!(v.xyyz(), u16vec4(1_u16, 2_u16, 2_u16, 3_u16));
+    assert_eq!(v.xyyw(), u16vec4(1_u16, 2_u16, 2_u16, 4_u16));
+    assert_eq!(v.xyzx(), u16vec4(1_u16, 2_u16, 3_u16, 1_u16));
+    assert_eq!(v.xyzy(), u16vec4(1_u16, 2_u16, 3_u16, 2_u16));
+    assert_eq!(v.xyzz(), u16vec4(1_u16, 2_u16, 3_u16, 3_u16));
+    assert_eq!(v.xywx(), u16vec4(1_u16, 2_u16, 4_u16, 1_u16));
+    assert_eq!(v.xywy(), u16vec4(1_u16, 2_u16, 4_u16, 2_u16));
+    assert_eq!(v.xywz(), u16vec4(1_u16, 2_u16, 4_u16, 3_u16));
+    assert_eq!(v.xyww(), u16vec4(1_u16, 2_u16, 4_u16, 4_u16));
+    assert_eq!(v.xzxx(), u16vec4(1_u16, 3_u16, 1_u16, 1_u16));
+    assert_eq!(v.xzxy(), u16vec4(1_u16, 3_u16, 1_u16, 2_u16));
+    assert_eq!(v.xzxz(), u16vec4(1_u16, 3_u16, 1_u16, 3_u16));
+    assert_eq!(v.xzxw(), u16vec4(1_u16, 3_u16, 1_u16, 4_u16));
+    assert_eq!(v.xzyx(), u16vec4(1_u16, 3_u16, 2_u16, 1_u16));
+    assert_eq!(v.xzyy(), u16vec4(1_u16, 3_u16, 2_u16, 2_u16));
+    assert_eq!(v.xzyz(), u16vec4(1_u16, 3_u16, 2_u16, 3_u16));
+    assert_eq!(v.xzyw(), u16vec4(1_u16, 3_u16, 2_u16, 4_u16));
+    assert_eq!(v.xzzx(), u16vec4(1_u16, 3_u16, 3_u16, 1_u16));
+    assert_eq!(v.xzzy(), u16vec4(1_u16, 3_u16, 3_u16, 2_u16));
+    assert_eq!(v.xzzz(), u16vec4(1_u16, 3_u16, 3_u16, 3_u16));
+    assert_eq!(v.xzzw(), u16vec4(1_u16, 3_u16, 3_u16, 4_u16));
+    assert_eq!(v.xzwx(), u16vec4(1_u16, 3_u16, 4_u16, 1_u16));
+    assert_eq!(v.xzwy(), u16vec4(1_u16, 3_u16, 4_u16, 2_u16));
+    assert_eq!(v.xzwz(), u16vec4(1_u16, 3_u16, 4_u16, 3_u16));
+    assert_eq!(v.xzww(), u16vec4(1_u16, 3_u16, 4_u16, 4_u16));
+    assert_eq!(v.xwxx(), u16vec4(1_u16, 4_u16, 1_u16, 1_u16));
+    assert_eq!(v.xwxy(), u16vec4(1_u16, 4_u16, 1_u16, 2_u16));
+    assert_eq!(v.xwxz(), u16vec4(1_u16, 4_u16, 1_u16, 3_u16));
+    assert_eq!(v.xwxw(), u16vec4(1_u16, 4_u16, 1_u16, 4_u16));
+    assert_eq!(v.xwyx(), u16vec4(1_u16, 4_u16, 2_u16, 1_u16));
+    assert_eq!(v.xwyy(), u16vec4(1_u16, 4_u16, 2_u16, 2_u16));
+    assert_eq!(v.xwyz(), u16vec4(1_u16, 4_u16, 2_u16, 3_u16));
+    assert_eq!(v.xwyw(), u16vec4(1_u16, 4_u16, 2_u16, 4_u16));
+    assert_eq!(v.xwzx(), u16vec4(1_u16, 4_u16, 3_u16, 1_u16));
+    assert_eq!(v.xwzy(), u16vec4(1_u16, 4_u16, 3_u16, 2_u16));
+    assert_eq!(v.xwzz(), u16vec4(1_u16, 4_u16, 3_u16, 3_u16));
+    assert_eq!(v.xwzw(), u16vec4(1_u16, 4_u16, 3_u16, 4_u16));
+    assert_eq!(v.xwwx(), u16vec4(1_u16, 4_u16, 4_u16, 1_u16));
+    assert_eq!(v.xwwy(), u16vec4(1_u16, 4_u16, 4_u16, 2_u16));
+    assert_eq!(v.xwwz(), u16vec4(1_u16, 4_u16, 4_u16, 3_u16));
+    assert_eq!(v.xwww(), u16vec4(1_u16, 4_u16, 4_u16, 4_u16));
+    assert_eq!(v.yxxx(), u16vec4(2_u16, 1_u16, 1_u16, 1_u16));
+    assert_eq!(v.yxxy(), u16vec4(2_u16, 1_u16, 1_u16, 2_u16));
+    assert_eq!(v.yxxz(), u16vec4(2_u16, 1_u16, 1_u16, 3_u16));
+    assert_eq!(v.yxxw(), u16vec4(2_u16, 1_u16, 1_u16, 4_u16));
+    assert_eq!(v.yxyx(), u16vec4(2_u16, 1_u16, 2_u16, 1_u16));
+    assert_eq!(v.yxyy(), u16vec4(2_u16, 1_u16, 2_u16, 2_u16));
+    assert_eq!(v.yxyz(), u16vec4(2_u16, 1_u16, 2_u16, 3_u16));
+    assert_eq!(v.yxyw(), u16vec4(2_u16, 1_u16, 2_u16, 4_u16));
+    assert_eq!(v.yxzx(), u16vec4(2_u16, 1_u16, 3_u16, 1_u16));
+    assert_eq!(v.yxzy(), u16vec4(2_u16, 1_u16, 3_u16, 2_u16));
+    assert_eq!(v.yxzz(), u16vec4(2_u16, 1_u16, 3_u16, 3_u16));
+    assert_eq!(v.yxzw(), u16vec4(2_u16, 1_u16, 3_u16, 4_u16));
+    assert_eq!(v.yxwx(), u16vec4(2_u16, 1_u16, 4_u16, 1_u16));
+    assert_eq!(v.yxwy(), u16vec4(2_u16, 1_u16, 4_u16, 2_u16));
+    assert_eq!(v.yxwz(), u16vec4(2_u16, 1_u16, 4_u16, 3_u16));
+    assert_eq!(v.yxww(), u16vec4(2_u16, 1_u16, 4_u16, 4_u16));
+    assert_eq!(v.yyxx(), u16vec4(2_u16, 2_u16, 1_u16, 1_u16));
+    assert_eq!(v.yyxy(), u16vec4(2_u16, 2_u16, 1_u16, 2_u16));
+    assert_eq!(v.yyxz(), u16vec4(2_u16, 2_u16, 1_u16, 3_u16));
+    assert_eq!(v.yyxw(), u16vec4(2_u16, 2_u16, 1_u16, 4_u16));
+    assert_eq!(v.yyyx(), u16vec4(2_u16, 2_u16, 2_u16, 1_u16));
+    assert_eq!(v.yyyy(), u16vec4(2_u16, 2_u16, 2_u16, 2_u16));
+    assert_eq!(v.yyyz(), u16vec4(2_u16, 2_u16, 2_u16, 3_u16));
+    assert_eq!(v.yyyw(), u16vec4(2_u16, 2_u16, 2_u16, 4_u16));
+    assert_eq!(v.yyzx(), u16vec4(2_u16, 2_u16, 3_u16, 1_u16));
+    assert_eq!(v.yyzy(), u16vec4(2_u16, 2_u16, 3_u16, 2_u16));
+    assert_eq!(v.yyzz(), u16vec4(2_u16, 2_u16, 3_u16, 3_u16));
+    assert_eq!(v.yyzw(), u16vec4(2_u16, 2_u16, 3_u16, 4_u16));
+    assert_eq!(v.yywx(), u16vec4(2_u16, 2_u16, 4_u16, 1_u16));
+    assert_eq!(v.yywy(), u16vec4(2_u16, 2_u16, 4_u16, 2_u16));
+    assert_eq!(v.yywz(), u16vec4(2_u16, 2_u16, 4_u16, 3_u16));
+    assert_eq!(v.yyww(), u16vec4(2_u16, 2_u16, 4_u16, 4_u16));
+    assert_eq!(v.yzxx(), u16vec4(2_u16, 3_u16, 1_u16, 1_u16));
+    assert_eq!(v.yzxy(), u16vec4(2_u16, 3_u16, 1_u16, 2_u16));
+    assert_eq!(v.yzxz(), u16vec4(2_u16, 3_u16, 1_u16, 3_u16));
+    assert_eq!(v.yzxw(), u16vec4(2_u16, 3_u16, 1_u16, 4_u16));
+    assert_eq!(v.yzyx(), u16vec4(2_u16, 3_u16, 2_u16, 1_u16));
+    assert_eq!(v.yzyy(), u16vec4(2_u16, 3_u16, 2_u16, 2_u16));
+    assert_eq!(v.yzyz(), u16vec4(2_u16, 3_u16, 2_u16, 3_u16));
+    assert_eq!(v.yzyw(), u16vec4(2_u16, 3_u16, 2_u16, 4_u16));
+    assert_eq!(v.yzzx(), u16vec4(2_u16, 3_u16, 3_u16, 1_u16));
+    assert_eq!(v.yzzy(), u16vec4(2_u16, 3_u16, 3_u16, 2_u16));
+    assert_eq!(v.yzzz(), u16vec4(2_u16, 3_u16, 3_u16, 3_u16));
+    assert_eq!(v.yzzw(), u16vec4(2_u16, 3_u16, 3_u16, 4_u16));
+    assert_eq!(v.yzwx(), u16vec4(2_u16, 3_u16, 4_u16, 1_u16));
+    assert_eq!(v.yzwy(), u16vec4(2_u16, 3_u16, 4_u16, 2_u16));
+    assert_eq!(v.yzwz(), u16vec4(2_u16, 3_u16, 4_u16, 3_u16));
+    assert_eq!(v.yzww(), u16vec4(2_u16, 3_u16, 4_u16, 4_u16));
+    assert_eq!(v.ywxx(), u16vec4(2_u16, 4_u16, 1_u16, 1_u16));
+    assert_eq!(v.ywxy(), u16vec4(2_u16, 4_u16, 1_u16, 2_u16));
+    assert_eq!(v.ywxz(), u16vec4(2_u16, 4_u16, 1_u16, 3_u16));
+    assert_eq!(v.ywxw(), u16vec4(2_u16, 4_u16, 1_u16, 4_u16));
+    assert_eq!(v.ywyx(), u16vec4(2_u16, 4_u16, 2_u16, 1_u16));
+    assert_eq!(v.ywyy(), u16vec4(2_u16, 4_u16, 2_u16, 2_u16));
+    assert_eq!(v.ywyz(), u16vec4(2_u16, 4_u16, 2_u16, 3_u16));
+    assert_eq!(v.ywyw(), u16vec4(2_u16, 4_u16, 2_u16, 4_u16));
+    assert_eq!(v.ywzx(), u16vec4(2_u16, 4_u16, 3_u16, 1_u16));
+    assert_eq!(v.ywzy(), u16vec4(2_u16, 4_u16, 3_u16, 2_u16));
+    assert_eq!(v.ywzz(), u16vec4(2_u16, 4_u16, 3_u16, 3_u16));
+    assert_eq!(v.ywzw(), u16vec4(2_u16, 4_u16, 3_u16, 4_u16));
+    assert_eq!(v.ywwx(), u16vec4(2_u16, 4_u16, 4_u16, 1_u16));
+    assert_eq!(v.ywwy(), u16vec4(2_u16, 4_u16, 4_u16, 2_u16));
+    assert_eq!(v.ywwz(), u16vec4(2_u16, 4_u16, 4_u16, 3_u16));
+    assert_eq!(v.ywww(), u16vec4(2_u16, 4_u16, 4_u16, 4_u16));
+    assert_eq!(v.zxxx(), u16vec4(3_u16, 1_u16, 1_u16, 1_u16));
+    assert_eq!(v.zxxy(), u16vec4(3_u16, 1_u16, 1_u16, 2_u16));
+    assert_eq!(v.zxxz(), u16vec4(3_u16, 1_u16, 1_u16, 3_u16));
+    assert_eq!(v.zxxw(), u16vec4(3_u16, 1_u16, 1_u16, 4_u16));
+    assert_eq!(v.zxyx(), u16vec4(3_u16, 1_u16, 2_u16, 1_u16));
+    assert_eq!(v.zxyy(), u16vec4(3_u16, 1_u16, 2_u16, 2_u16));
+    assert_eq!(v.zxyz(), u16vec4(3_u16, 1_u16, 2_u16, 3_u16));
+    assert_eq!(v.zxyw(), u16vec4(3_u16, 1_u16, 2_u16, 4_u16));
+    assert_eq!(v.zxzx(), u16vec4(3_u16, 1_u16, 3_u16, 1_u16));
+    assert_eq!(v.zxzy(), u16vec4(3_u16, 1_u16, 3_u16, 2_u16));
+    assert_eq!(v.zxzz(), u16vec4(3_u16, 1_u16, 3_u16, 3_u16));
+    assert_eq!(v.zxzw(), u16vec4(3_u16, 1_u16, 3_u16, 4_u16));
+    assert_eq!(v.zxwx(), u16vec4(3_u16, 1_u16, 4_u16, 1_u16));
+    assert_eq!(v.zxwy(), u16vec4(3_u16, 1_u16, 4_u16, 2_u16));
+    assert_eq!(v.zxwz(), u16vec4(3_u16, 1_u16, 4_u16, 3_u16));
+    assert_eq!(v.zxww(), u16vec4(3_u16, 1_u16, 4_u16, 4_u16));
+    assert_eq!(v.zyxx(), u16vec4(3_u16, 2_u16, 1_u16, 1_u16));
+    assert_eq!(v.zyxy(), u16vec4(3_u16, 2_u16, 1_u16, 2_u16));
+    assert_eq!(v.zyxz(), u16vec4(3_u16, 2_u16, 1_u16, 3_u16));
+    assert_eq!(v.zyxw(), u16vec4(3_u16, 2_u16, 1_u16, 4_u16));
+    assert_eq!(v.zyyx(), u16vec4(3_u16, 2_u16, 2_u16, 1_u16));
+    assert_eq!(v.zyyy(), u16vec4(3_u16, 2_u16, 2_u16, 2_u16));
+    assert_eq!(v.zyyz(), u16vec4(3_u16, 2_u16, 2_u16, 3_u16));
+    assert_eq!(v.zyyw(), u16vec4(3_u16, 2_u16, 2_u16, 4_u16));
+    assert_eq!(v.zyzx(), u16vec4(3_u16, 2_u16, 3_u16, 1_u16));
+    assert_eq!(v.zyzy(), u16vec4(3_u16, 2_u16, 3_u16, 2_u16));
+    assert_eq!(v.zyzz(), u16vec4(3_u16, 2_u16, 3_u16, 3_u16));
+    assert_eq!(v.zyzw(), u16vec4(3_u16, 2_u16, 3_u16, 4_u16));
+    assert_eq!(v.zywx(), u16vec4(3_u16, 2_u16, 4_u16, 1_u16));
+    assert_eq!(v.zywy(), u16vec4(3_u16, 2_u16, 4_u16, 2_u16));
+    assert_eq!(v.zywz(), u16vec4(3_u16, 2_u16, 4_u16, 3_u16));
+    assert_eq!(v.zyww(), u16vec4(3_u16, 2_u16, 4_u16, 4_u16));
+    assert_eq!(v.zzxx(), u16vec4(3_u16, 3_u16, 1_u16, 1_u16));
+    assert_eq!(v.zzxy(), u16vec4(3_u16, 3_u16, 1_u16, 2_u16));
+    assert_eq!(v.zzxz(), u16vec4(3_u16, 3_u16, 1_u16, 3_u16));
+    assert_eq!(v.zzxw(), u16vec4(3_u16, 3_u16, 1_u16, 4_u16));
+    assert_eq!(v.zzyx(), u16vec4(3_u16, 3_u16, 2_u16, 1_u16));
+    assert_eq!(v.zzyy(), u16vec4(3_u16, 3_u16, 2_u16, 2_u16));
+    assert_eq!(v.zzyz(), u16vec4(3_u16, 3_u16, 2_u16, 3_u16));
+    assert_eq!(v.zzyw(), u16vec4(3_u16, 3_u16, 2_u16, 4_u16));
+    assert_eq!(v.zzzx(), u16vec4(3_u16, 3_u16, 3_u16, 1_u16));
+    assert_eq!(v.zzzy(), u16vec4(3_u16, 3_u16, 3_u16, 2_u16));
+    assert_eq!(v.zzzz(), u16vec4(3_u16, 3_u16, 3_u16, 3_u16));
+    assert_eq!(v.zzzw(), u16vec4(3_u16, 3_u16, 3_u16, 4_u16));
+    assert_eq!(v.zzwx(), u16vec4(3_u16, 3_u16, 4_u16, 1_u16));
+    assert_eq!(v.zzwy(), u16vec4(3_u16, 3_u16, 4_u16, 2_u16));
+    assert_eq!(v.zzwz(), u16vec4(3_u16, 3_u16, 4_u16, 3_u16));
+    assert_eq!(v.zzww(), u16vec4(3_u16, 3_u16, 4_u16, 4_u16));
+    assert_eq!(v.zwxx(), u16vec4(3_u16, 4_u16, 1_u16, 1_u16));
+    assert_eq!(v.zwxy(), u16vec4(3_u16, 4_u16, 1_u16, 2_u16));
+    assert_eq!(v.zwxz(), u16vec4(3_u16, 4_u16, 1_u16, 3_u16));
+    assert_eq!(v.zwxw(), u16vec4(3_u16, 4_u16, 1_u16, 4_u16));
+    assert_eq!(v.zwyx(), u16vec4(3_u16, 4_u16, 2_u16, 1_u16));
+    assert_eq!(v.zwyy(), u16vec4(3_u16, 4_u16, 2_u16, 2_u16));
+    assert_eq!(v.zwyz(), u16vec4(3_u16, 4_u16, 2_u16, 3_u16));
+    assert_eq!(v.zwyw(), u16vec4(3_u16, 4_u16, 2_u16, 4_u16));
+    assert_eq!(v.zwzx(), u16vec4(3_u16, 4_u16, 3_u16, 1_u16));
+    assert_eq!(v.zwzy(), u16vec4(3_u16, 4_u16, 3_u16, 2_u16));
+    assert_eq!(v.zwzz(), u16vec4(3_u16, 4_u16, 3_u16, 3_u16));
+    assert_eq!(v.zwzw(), u16vec4(3_u16, 4_u16, 3_u16, 4_u16));
+    assert_eq!(v.zwwx(), u16vec4(3_u16, 4_u16, 4_u16, 1_u16));
+    assert_eq!(v.zwwy(), u16vec4(3_u16, 4_u16, 4_u16, 2_u16));
+    assert_eq!(v.zwwz(), u16vec4(3_u16, 4_u16, 4_u16, 3_u16));
+    assert_eq!(v.zwww(), u16vec4(3_u16, 4_u16, 4_u16, 4_u16));
+    assert_eq!(v.wxxx(), u16vec4(4_u16, 1_u16, 1_u16, 1_u16));
+    assert_eq!(v.wxxy(), u16vec4(4_u16, 1_u16, 1_u16, 2_u16));
+    assert_eq!(v.wxxz(), u16vec4(4_u16, 1_u16, 1_u16, 3_u16));
+    assert_eq!(v.wxxw(), u16vec4(4_u16, 1_u16, 1_u16, 4_u16));
+    assert_eq!(v.wxyx(), u16vec4(4_u16, 1_u16, 2_u16, 1_u16));
+    assert_eq!(v.wxyy(), u16vec4(4_u16, 1_u16, 2_u16, 2_u16));
+    assert_eq!(v.wxyz(), u16vec4(4_u16, 1_u16, 2_u16, 3_u16));
+    assert_eq!(v.wxyw(), u16vec4(4_u16, 1_u16, 2_u16, 4_u16));
+    assert_eq!(v.wxzx(), u16vec4(4_u16, 1_u16, 3_u16, 1_u16));
+    assert_eq!(v.wxzy(), u16vec4(4_u16, 1_u16, 3_u16, 2_u16));
+    assert_eq!(v.wxzz(), u16vec4(4_u16, 1_u16, 3_u16, 3_u16));
+    assert_eq!(v.wxzw(), u16vec4(4_u16, 1_u16, 3_u16, 4_u16));
+    assert_eq!(v.wxwx(), u16vec4(4_u16, 1_u16, 4_u16, 1_u16));
+    assert_eq!(v.wxwy(), u16vec4(4_u16, 1_u16, 4_u16, 2_u16));
+    assert_eq!(v.wxwz(), u16vec4(4_u16, 1_u16, 4_u16, 3_u16));
+    assert_eq!(v.wxww(), u16vec4(4_u16, 1_u16, 4_u16, 4_u16));
+    assert_eq!(v.wyxx(), u16vec4(4_u16, 2_u16, 1_u16, 1_u16));
+    assert_eq!(v.wyxy(), u16vec4(4_u16, 2_u16, 1_u16, 2_u16));
+    assert_eq!(v.wyxz(), u16vec4(4_u16, 2_u16, 1_u16, 3_u16));
+    assert_eq!(v.wyxw(), u16vec4(4_u16, 2_u16, 1_u16, 4_u16));
+    assert_eq!(v.wyyx(), u16vec4(4_u16, 2_u16, 2_u16, 1_u16));
+    assert_eq!(v.wyyy(), u16vec4(4_u16, 2_u16, 2_u16, 2_u16));
+    assert_eq!(v.wyyz(), u16vec4(4_u16, 2_u16, 2_u16, 3_u16));
+    assert_eq!(v.wyyw(), u16vec4(4_u16, 2_u16, 2_u16, 4_u16));
+    assert_eq!(v.wyzx(), u16vec4(4_u16, 2_u16, 3_u16, 1_u16));
+    assert_eq!(v.wyzy(), u16vec4(4_u16, 2_u16, 3_u16, 2_u16));
+    assert_eq!(v.wyzz(), u16vec4(4_u16, 2_u16, 3_u16, 3_u16));
+    assert_eq!(v.wyzw(), u16vec4(4_u16, 2_u16, 3_u16, 4_u16));
+    assert_eq!(v.wywx(), u16vec4(4_u16, 2_u16, 4_u16, 1_u16));
+    assert_eq!(v.wywy(), u16vec4(4_u16, 2_u16, 4_u16, 2_u16));
+    assert_eq!(v.wywz(), u16vec4(4_u16, 2_u16, 4_u16, 3_u16));
+    assert_eq!(v.wyww(), u16vec4(4_u16, 2_u16, 4_u16, 4_u16));
+    assert_eq!(v.wzxx(), u16vec4(4_u16, 3_u16, 1_u16, 1_u16));
+    assert_eq!(v.wzxy(), u16vec4(4_u16, 3_u16, 1_u16, 2_u16));
+    assert_eq!(v.wzxz(), u16vec4(4_u16, 3_u16, 1_u16, 3_u16));
+    assert_eq!(v.wzxw(), u16vec4(4_u16, 3_u16, 1_u16, 4_u16));
+    assert_eq!(v.wzyx(), u16vec4(4_u16, 3_u16, 2_u16, 1_u16));
+    assert_eq!(v.wzyy(), u16vec4(4_u16, 3_u16, 2_u16, 2_u16));
+    assert_eq!(v.wzyz(), u16vec4(4_u16, 3_u16, 2_u16, 3_u16));
+    assert_eq!(v.wzyw(), u16vec4(4_u16, 3_u16, 2_u16, 4_u16));
+    assert_eq!(v.wzzx(), u16vec4(4_u16, 3_u16, 3_u16, 1_u16));
+    assert_eq!(v.wzzy(), u16vec4(4_u16, 3_u16, 3_u16, 2_u16));
+    assert_eq!(v.wzzz(), u16vec4(4_u16, 3_u16, 3_u16, 3_u16));
+    assert_eq!(v.wzzw(), u16vec4(4_u16, 3_u16, 3_u16, 4_u16));
+    assert_eq!(v.wzwx(), u16vec4(4_u16, 3_u16, 4_u16, 1_u16));
+    assert_eq!(v.wzwy(), u16vec4(4_u16, 3_u16, 4_u16, 2_u16));
+    assert_eq!(v.wzwz(), u16vec4(4_u16, 3_u16, 4_u16, 3_u16));
+    assert_eq!(v.wzww(), u16vec4(4_u16, 3_u16, 4_u16, 4_u16));
+    assert_eq!(v.wwxx(), u16vec4(4_u16, 4_u16, 1_u16, 1_u16));
+    assert_eq!(v.wwxy(), u16vec4(4_u16, 4_u16, 1_u16, 2_u16));
+    assert_eq!(v.wwxz(), u16vec4(4_u16, 4_u16, 1_u16, 3_u16));
+    assert_eq!(v.wwxw(), u16vec4(4_u16, 4_u16, 1_u16, 4_u16));
+    assert_eq!(v.wwyx(), u16vec4(4_u16, 4_u16, 2_u16, 1_u16));
+    assert_eq!(v.wwyy(), u16vec4(4_u16, 4_u16, 2_u16, 2_u16));
+    assert_eq!(v.wwyz(), u16vec4(4_u16, 4_u16, 2_u16, 3_u16));
+    assert_eq!(v.wwyw(), u16vec4(4_u16, 4_u16, 2_u16, 4_u16));
+    assert_eq!(v.wwzx(), u16vec4(4_u16, 4_u16, 3_u16, 1_u16));
+    assert_eq!(v.wwzy(), u16vec4(4_u16, 4_u16, 3_u16, 2_u16));
+    assert_eq!(v.wwzz(), u16vec4(4_u16, 4_u16, 3_u16, 3_u16));
+    assert_eq!(v.wwzw(), u16vec4(4_u16, 4_u16, 3_u16, 4_u16));
+    assert_eq!(v.wwwx(), u16vec4(4_u16, 4_u16, 4_u16, 1_u16));
+    assert_eq!(v.wwwy(), u16vec4(4_u16, 4_u16, 4_u16, 2_u16));
+    assert_eq!(v.wwwz(), u16vec4(4_u16, 4_u16, 4_u16, 3_u16));
+    assert_eq!(v.wwww(), u16vec4(4_u16, 4_u16, 4_u16, 4_u16));
+    assert_eq!(v.xxx(), u16vec3(1_u16, 1_u16, 1_u16));
+    assert_eq!(v.xxy(), u16vec3(1_u16, 1_u16, 2_u16));
+    assert_eq!(v.xxz(), u16vec3(1_u16, 1_u16, 3_u16));
+    assert_eq!(v.xxw(), u16vec3(1_u16, 1_u16, 4_u16));
+    assert_eq!(v.xyx(), u16vec3(1_u16, 2_u16, 1_u16));
+    assert_eq!(v.xyy(), u16vec3(1_u16, 2_u16, 2_u16));
+    assert_eq!(v.xyz(), u16vec3(1_u16, 2_u16, 3_u16));
+    assert_eq!(v.xyw(), u16vec3(1_u16, 2_u16, 4_u16));
+    assert_eq!(v.xzx(), u16vec3(1_u16, 3_u16, 1_u16));
+    assert_eq!(v.xzy(), u16vec3(1_u16, 3_u16, 2_u16));
+    assert_eq!(v.xzz(), u16vec3(1_u16, 3_u16, 3_u16));
+    assert_eq!(v.xzw(), u16vec3(1_u16, 3_u16, 4_u16));
+    assert_eq!(v.xwx(), u16vec3(1_u16, 4_u16, 1_u16));
+    assert_eq!(v.xwy(), u16vec3(1_u16, 4_u16, 2_u16));
+    assert_eq!(v.xwz(), u16vec3(1_u16, 4_u16, 3_u16));
+    assert_eq!(v.xww(), u16vec3(1_u16, 4_u16, 4_u16));
+    assert_eq!(v.yxx(), u16vec3(2_u16, 1_u16, 1_u16));
+    assert_eq!(v.yxy(), u16vec3(2_u16, 1_u16, 2_u16));
+    assert_eq!(v.yxz(), u16vec3(2_u16, 1_u16, 3_u16));
+    assert_eq!(v.yxw(), u16vec3(2_u16, 1_u16, 4_u16));
+    assert_eq!(v.yyx(), u16vec3(2_u16, 2_u16, 1_u16));
+    assert_eq!(v.yyy(), u16vec3(2_u16, 2_u16, 2_u16));
+    assert_eq!(v.yyz(), u16vec3(2_u16, 2_u16, 3_u16));
+    assert_eq!(v.yyw(), u16vec3(2_u16, 2_u16, 4_u16));
+    assert_eq!(v.yzx(), u16vec3(2_u16, 3_u16, 1_u16));
+    assert_eq!(v.yzy(), u16vec3(2_u16, 3_u16, 2_u16));
+    assert_eq!(v.yzz(), u16vec3(2_u16, 3_u16, 3_u16));
+    assert_eq!(v.yzw(), u16vec3(2_u16, 3_u16, 4_u16));
+    assert_eq!(v.ywx(), u16vec3(2_u16, 4_u16, 1_u16));
+    assert_eq!(v.ywy(), u16vec3(2_u16, 4_u16, 2_u16));
+    assert_eq!(v.ywz(), u16vec3(2_u16, 4_u16, 3_u16));
+    assert_eq!(v.yww(), u16vec3(2_u16, 4_u16, 4_u16));
+    assert_eq!(v.zxx(), u16vec3(3_u16, 1_u16, 1_u16));
+    assert_eq!(v.zxy(), u16vec3(3_u16, 1_u16, 2_u16));
+    assert_eq!(v.zxz(), u16vec3(3_u16, 1_u16, 3_u16));
+    assert_eq!(v.zxw(), u16vec3(3_u16, 1_u16, 4_u16));
+    assert_eq!(v.zyx(), u16vec3(3_u16, 2_u16, 1_u16));
+    assert_eq!(v.zyy(), u16vec3(3_u16, 2_u16, 2_u16));
+    assert_eq!(v.zyz(), u16vec3(3_u16, 2_u16, 3_u16));
+    assert_eq!(v.zyw(), u16vec3(3_u16, 2_u16, 4_u16));
+    assert_eq!(v.zzx(), u16vec3(3_u16, 3_u16, 1_u16));
+    assert_eq!(v.zzy(), u16vec3(3_u16, 3_u16, 2_u16));
+    assert_eq!(v.zzz(), u16vec3(3_u16, 3_u16, 3_u16));
+    assert_eq!(v.zzw(), u16vec3(3_u16, 3_u16, 4_u16));
+    assert_eq!(v.zwx(), u16vec3(3_u16, 4_u16, 1_u16));
+    assert_eq!(v.zwy(), u16vec3(3_u16, 4_u16, 2_u16));
+    assert_eq!(v.zwz(), u16vec3(3_u16, 4_u16, 3_u16));
+    assert_eq!(v.zww(), u16vec3(3_u16, 4_u16, 4_u16));
+    assert_eq!(v.wxx(), u16vec3(4_u16, 1_u16, 1_u16));
+    assert_eq!(v.wxy(), u16vec3(4_u16, 1_u16, 2_u16));
+    assert_eq!(v.wxz(), u16vec3(4_u16, 1_u16, 3_u16));
+    assert_eq!(v.wxw(), u16vec3(4_u16, 1_u16, 4_u16));
+    assert_eq!(v.wyx(), u16vec3(4_u16, 2_u16, 1_u16));
+    assert_eq!(v.wyy(), u16vec3(4_u16, 2_u16, 2_u16));
+    assert_eq!(v.wyz(), u16vec3(4_u16, 2_u16, 3_u16));
+    assert_eq!(v.wyw(), u16vec3(4_u16, 2_u16, 4_u16));
+    assert_eq!(v.wzx(), u16vec3(4_u16, 3_u16, 1_u16));
+    assert_eq!(v.wzy(), u16vec3(4_u16, 3_u16, 2_u16));
+    assert_eq!(v.wzz(), u16vec3(4_u16, 3_u16, 3_u16));
+    assert_eq!(v.wzw(), u16vec3(4_u16, 3_u16, 4_u16));
+    assert_eq!(v.wwx(), u16vec3(4_u16, 4_u16, 1_u16));
+    assert_eq!(v.wwy(), u16vec3(4_u16, 4_u16, 2_u16));
+    assert_eq!(v.wwz(), u16vec3(4_u16, 4_u16, 3_u16));
+    assert_eq!(v.www(), u16vec3(4_u16, 4_u16, 4_u16));
+    assert_eq!(v.xx(), u16vec2(1_u16, 1_u16));
+    assert_eq!(v.xy(), u16vec2(1_u16, 2_u16));
+    assert_eq!(v.xz(), u16vec2(1_u16, 3_u16));
+    assert_eq!(v.xw(), u16vec2(1_u16, 4_u16));
+    assert_eq!(v.yx(), u16vec2(2_u16, 1_u16));
+    assert_eq!(v.yy(), u16vec2(2_u16, 2_u16));
+    assert_eq!(v.yz(), u16vec2(2_u16, 3_u16));
+    assert_eq!(v.yw(), u16vec2(2_u16, 4_u16));
+    assert_eq!(v.zx(), u16vec2(3_u16, 1_u16));
+    assert_eq!(v.zy(), u16vec2(3_u16, 2_u16));
+    assert_eq!(v.zz(), u16vec2(3_u16, 3_u16));
+    assert_eq!(v.zw(), u16vec2(3_u16, 4_u16));
+    assert_eq!(v.wx(), u16vec2(4_u16, 1_u16));
+    assert_eq!(v.wy(), u16vec2(4_u16, 2_u16));
+    assert_eq!(v.wz(), u16vec2(4_u16, 3_u16));
+    assert_eq!(v.ww(), u16vec2(4_u16, 4_u16));
+});
+
+glam_test!(test_u16vec3_swizzles, {
+    let v = u16vec3(1_u16, 2_u16, 3_u16);
+    assert_eq!(v, v.xyz());
+    assert_eq!(v.xxxx(), u16vec4(1_u16, 1_u16, 1_u16, 1_u16));
+    assert_eq!(v.xxxy(), u16vec4(1_u16, 1_u16, 1_u16, 2_u16));
+    assert_eq!(v.xxxz(), u16vec4(1_u16, 1_u16, 1_u16, 3_u16));
+    assert_eq!(v.xxyx(), u16vec4(1_u16, 1_u16, 2_u16, 1_u16));
+    assert_eq!(v.xxyy(), u16vec4(1_u16, 1_u16, 2_u16, 2_u16));
+    assert_eq!(v.xxyz(), u16vec4(1_u16, 1_u16, 2_u16, 3_u16));
+    assert_eq!(v.xxzx(), u16vec4(1_u16, 1_u16, 3_u16, 1_u16));
+    assert_eq!(v.xxzy(), u16vec4(1_u16, 1_u16, 3_u16, 2_u16));
+    assert_eq!(v.xxzz(), u16vec4(1_u16, 1_u16, 3_u16, 3_u16));
+    assert_eq!(v.xyxx(), u16vec4(1_u16, 2_u16, 1_u16, 1_u16));
+    assert_eq!(v.xyxy(), u16vec4(1_u16, 2_u16, 1_u16, 2_u16));
+    assert_eq!(v.xyxz(), u16vec4(1_u16, 2_u16, 1_u16, 3_u16));
+    assert_eq!(v.xyyx(), u16vec4(1_u16, 2_u16, 2_u16, 1_u16));
+    assert_eq!(v.xyyy(), u16vec4(1_u16, 2_u16, 2_u16, 2_u16));
+    assert_eq!(v.xyyz(), u16vec4(1_u16, 2_u16, 2_u16, 3_u16));
+    assert_eq!(v.xyzx(), u16vec4(1_u16, 2_u16, 3_u16, 1_u16));
+    assert_eq!(v.xyzy(), u16vec4(1_u16, 2_u16, 3_u16, 2_u16));
+    assert_eq!(v.xyzz(), u16vec4(1_u16, 2_u16, 3_u16, 3_u16));
+    assert_eq!(v.xzxx(), u16vec4(1_u16, 3_u16, 1_u16, 1_u16));
+    assert_eq!(v.xzxy(), u16vec4(1_u16, 3_u16, 1_u16, 2_u16));
+    assert_eq!(v.xzxz(), u16vec4(1_u16, 3_u16, 1_u16, 3_u16));
+    assert_eq!(v.xzyx(), u16vec4(1_u16, 3_u16, 2_u16, 1_u16));
+    assert_eq!(v.xzyy(), u16vec4(1_u16, 3_u16, 2_u16, 2_u16));
+    assert_eq!(v.xzyz(), u16vec4(1_u16, 3_u16, 2_u16, 3_u16));
+    assert_eq!(v.xzzx(), u16vec4(1_u16, 3_u16, 3_u16, 1_u16));
+    assert_eq!(v.xzzy(), u16vec4(1_u16, 3_u16, 3_u16, 2_u16));
+    assert_eq!(v.xzzz(), u16vec4(1_u16, 3_u16, 3_u16, 3_u16));
+    assert_eq!(v.yxxx(), u16vec4(2_u16, 1_u16, 1_u16, 1_u16));
+    assert_eq!(v.yxxy(), u16vec4(2_u16, 1_u16, 1_u16, 2_u16));
+    assert_eq!(v.yxxz(), u16vec4(2_u16, 1_u16, 1_u16, 3_u16));
+    assert_eq!(v.yxyx(), u16vec4(2_u16, 1_u16, 2_u16, 1_u16));
+    assert_eq!(v.yxyy(), u16vec4(2_u16, 1_u16, 2_u16, 2_u16));
+    assert_eq!(v.yxyz(), u16vec4(2_u16, 1_u16, 2_u16, 3_u16));
+    assert_eq!(v.yxzx(), u16vec4(2_u16, 1_u16, 3_u16, 1_u16));
+    assert_eq!(v.yxzy(), u16vec4(2_u16, 1_u16, 3_u16, 2_u16));
+    assert_eq!(v.yxzz(), u16vec4(2_u16, 1_u16, 3_u16, 3_u16));
+    assert_eq!(v.yyxx(), u16vec4(2_u16, 2_u16, 1_u16, 1_u16));
+    assert_eq!(v.yyxy(), u16vec4(2_u16, 2_u16, 1_u16, 2_u16));
+    assert_eq!(v.yyxz(), u16vec4(2_u16, 2_u16, 1_u16, 3_u16));
+    assert_eq!(v.yyyx(), u16vec4(2_u16, 2_u16, 2_u16, 1_u16));
+    assert_eq!(v.yyyy(), u16vec4(2_u16, 2_u16, 2_u16, 2_u16));
+    assert_eq!(v.yyyz(), u16vec4(2_u16, 2_u16, 2_u16, 3_u16));
+    assert_eq!(v.yyzx(), u16vec4(2_u16, 2_u16, 3_u16, 1_u16));
+    assert_eq!(v.yyzy(), u16vec4(2_u16, 2_u16, 3_u16, 2_u16));
+    assert_eq!(v.yyzz(), u16vec4(2_u16, 2_u16, 3_u16, 3_u16));
+    assert_eq!(v.yzxx(), u16vec4(2_u16, 3_u16, 1_u16, 1_u16));
+    assert_eq!(v.yzxy(), u16vec4(2_u16, 3_u16, 1_u16, 2_u16));
+    assert_eq!(v.yzxz(), u16vec4(2_u16, 3_u16, 1_u16, 3_u16));
+    assert_eq!(v.yzyx(), u16vec4(2_u16, 3_u16, 2_u16, 1_u16));
+    assert_eq!(v.yzyy(), u16vec4(2_u16, 3_u16, 2_u16, 2_u16));
+    assert_eq!(v.yzyz(), u16vec4(2_u16, 3_u16, 2_u16, 3_u16));
+    assert_eq!(v.yzzx(), u16vec4(2_u16, 3_u16, 3_u16, 1_u16));
+    assert_eq!(v.yzzy(), u16vec4(2_u16, 3_u16, 3_u16, 2_u16));
+    assert_eq!(v.yzzz(), u16vec4(2_u16, 3_u16, 3_u16, 3_u16));
+    assert_eq!(v.zxxx(), u16vec4(3_u16, 1_u16, 1_u16, 1_u16));
+    assert_eq!(v.zxxy(), u16vec4(3_u16, 1_u16, 1_u16, 2_u16));
+    assert_eq!(v.zxxz(), u16vec4(3_u16, 1_u16, 1_u16, 3_u16));
+    assert_eq!(v.zxyx(), u16vec4(3_u16, 1_u16, 2_u16, 1_u16));
+    assert_eq!(v.zxyy(), u16vec4(3_u16, 1_u16, 2_u16, 2_u16));
+    assert_eq!(v.zxyz(), u16vec4(3_u16, 1_u16, 2_u16, 3_u16));
+    assert_eq!(v.zxzx(), u16vec4(3_u16, 1_u16, 3_u16, 1_u16));
+    assert_eq!(v.zxzy(), u16vec4(3_u16, 1_u16, 3_u16, 2_u16));
+    assert_eq!(v.zxzz(), u16vec4(3_u16, 1_u16, 3_u16, 3_u16));
+    assert_eq!(v.zyxx(), u16vec4(3_u16, 2_u16, 1_u16, 1_u16));
+    assert_eq!(v.zyxy(), u16vec4(3_u16, 2_u16, 1_u16, 2_u16));
+    assert_eq!(v.zyxz(), u16vec4(3_u16, 2_u16, 1_u16, 3_u16));
+    assert_eq!(v.zyyx(), u16vec4(3_u16, 2_u16, 2_u16, 1_u16));
+    assert_eq!(v.zyyy(), u16vec4(3_u16, 2_u16, 2_u16, 2_u16));
+    assert_eq!(v.zyyz(), u16vec4(3_u16, 2_u16, 2_u16, 3_u16));
+    assert_eq!(v.zyzx(), u16vec4(3_u16, 2_u16, 3_u16, 1_u16));
+    assert_eq!(v.zyzy(), u16vec4(3_u16, 2_u16, 3_u16, 2_u16));
+    assert_eq!(v.zyzz(), u16vec4(3_u16, 2_u16, 3_u16, 3_u16));
+    assert_eq!(v.zzxx(), u16vec4(3_u16, 3_u16, 1_u16, 1_u16));
+    assert_eq!(v.zzxy(), u16vec4(3_u16, 3_u16, 1_u16, 2_u16));
+    assert_eq!(v.zzxz(), u16vec4(3_u16, 3_u16, 1_u16, 3_u16));
+    assert_eq!(v.zzyx(), u16vec4(3_u16, 3_u16, 2_u16, 1_u16));
+    assert_eq!(v.zzyy(), u16vec4(3_u16, 3_u16, 2_u16, 2_u16));
+    assert_eq!(v.zzyz(), u16vec4(3_u16, 3_u16, 2_u16, 3_u16));
+    assert_eq!(v.zzzx(), u16vec4(3_u16, 3_u16, 3_u16, 1_u16));
+    assert_eq!(v.zzzy(), u16vec4(3_u16, 3_u16, 3_u16, 2_u16));
+    assert_eq!(v.zzzz(), u16vec4(3_u16, 3_u16, 3_u16, 3_u16));
+    assert_eq!(v.xxx(), u16vec3(1_u16, 1_u16, 1_u16));
+    assert_eq!(v.xxy(), u16vec3(1_u16, 1_u16, 2_u16));
+    assert_eq!(v.xxz(), u16vec3(1_u16, 1_u16, 3_u16));
+    assert_eq!(v.xyx(), u16vec3(1_u16, 2_u16, 1_u16));
+    assert_eq!(v.xyy(), u16vec3(1_u16, 2_u16, 2_u16));
+    assert_eq!(v.xzx(), u16vec3(1_u16, 3_u16, 1_u16));
+    assert_eq!(v.xzy(), u16vec3(1_u16, 3_u16, 2_u16));
+    assert_eq!(v.xzz(), u16vec3(1_u16, 3_u16, 3_u16));
+    assert_eq!(v.yxx(), u16vec3(2_u16, 1_u16, 1_u16));
+    assert_eq!(v.yxy(), u16vec3(2_u16, 1_u16, 2_u16));
+    assert_eq!(v.yxz(), u16vec3(2_u16, 1_u16, 3_u16));
+    assert_eq!(v.yyx(), u16vec3(2_u16, 2_u16, 1_u16));
+    assert_eq!(v.yyy(), u16vec3(2_u16, 2_u16, 2_u16));
+    assert_eq!(v.yyz(), u16vec3(2_u16, 2_u16, 3_u16));
+    assert_eq!(v.yzx(), u16vec3(2_u16, 3_u16, 1_u16));
+    assert_eq!(v.yzy(), u16vec3(2_u16, 3_u16, 2_u16));
+    assert_eq!(v.yzz(), u16vec3(2_u16, 3_u16, 3_u16));
+    assert_eq!(v.zxx(), u16vec3(3_u16, 1_u16, 1_u16));
+    assert_eq!(v.zxy(), u16vec3(3_u16, 1_u16, 2_u16));
+    assert_eq!(v.zxz(), u16vec3(3_u16, 1_u16, 3_u16));
+    assert_eq!(v.zyx(), u16vec3(3_u16, 2_u16, 1_u16));
+    assert_eq!(v.zyy(), u16vec3(3_u16, 2_u16, 2_u16));
+    assert_eq!(v.zyz(), u16vec3(3_u16, 2_u16, 3_u16));
+    assert_eq!(v.zzx(), u16vec3(3_u16, 3_u16, 1_u16));
+    assert_eq!(v.zzy(), u16vec3(3_u16, 3_u16, 2_u16));
+    assert_eq!(v.zzz(), u16vec3(3_u16, 3_u16, 3_u16));
+    assert_eq!(v.xx(), u16vec2(1_u16, 1_u16));
+    assert_eq!(v.xy(), u16vec2(1_u16, 2_u16));
+    assert_eq!(v.xz(), u16vec2(1_u16, 3_u16));
+    assert_eq!(v.yx(), u16vec2(2_u16, 1_u16));
+    assert_eq!(v.yy(), u16vec2(2_u16, 2_u16));
+    assert_eq!(v.yz(), u16vec2(2_u16, 3_u16));
+    assert_eq!(v.zx(), u16vec2(3_u16, 1_u16));
+    assert_eq!(v.zy(), u16vec2(3_u16, 2_u16));
+    assert_eq!(v.zz(), u16vec2(3_u16, 3_u16));
+});
+
+glam_test!(test_u16vec2_swizzles, {
+    let v = u16vec2(1_u16, 2_u16);
+    assert_eq!(v, v.xy());
+    assert_eq!(v.xxxx(), u16vec4(1_u16, 1_u16, 1_u16, 1_u16));
+    assert_eq!(v.xxxy(), u16vec4(1_u16, 1_u16, 1_u16, 2_u16));
+    assert_eq!(v.xxyx(), u16vec4(1_u16, 1_u16, 2_u16, 1_u16));
+    assert_eq!(v.xxyy(), u16vec4(1_u16, 1_u16, 2_u16, 2_u16));
+    assert_eq!(v.xyxx(), u16vec4(1_u16, 2_u16, 1_u16, 1_u16));
+    assert_eq!(v.xyxy(), u16vec4(1_u16, 2_u16, 1_u16, 2_u16));
+    assert_eq!(v.xyyx(), u16vec4(1_u16, 2_u16, 2_u16, 1_u16));
+    assert_eq!(v.xyyy(), u16vec4(1_u16, 2_u16, 2_u16, 2_u16));
+    assert_eq!(v.yxxx(), u16vec4(2_u16, 1_u16, 1_u16, 1_u16));
+    assert_eq!(v.yxxy(), u16vec4(2_u16, 1_u16, 1_u16, 2_u16));
+    assert_eq!(v.yxyx(), u16vec4(2_u16, 1_u16, 2_u16, 1_u16));
+    assert_eq!(v.yxyy(), u16vec4(2_u16, 1_u16, 2_u16, 2_u16));
+    assert_eq!(v.yyxx(), u16vec4(2_u16, 2_u16, 1_u16, 1_u16));
+    assert_eq!(v.yyxy(), u16vec4(2_u16, 2_u16, 1_u16, 2_u16));
+    assert_eq!(v.yyyx(), u16vec4(2_u16, 2_u16, 2_u16, 1_u16));
+    assert_eq!(v.yyyy(), u16vec4(2_u16, 2_u16, 2_u16, 2_u16));
+    assert_eq!(v.xxx(), u16vec3(1_u16, 1_u16, 1_u16));
+    assert_eq!(v.xxy(), u16vec3(1_u16, 1_u16, 2_u16));
+    assert_eq!(v.xyx(), u16vec3(1_u16, 2_u16, 1_u16));
+    assert_eq!(v.xyy(), u16vec3(1_u16, 2_u16, 2_u16));
+    assert_eq!(v.yxx(), u16vec3(2_u16, 1_u16, 1_u16));
+    assert_eq!(v.yxy(), u16vec3(2_u16, 1_u16, 2_u16));
+    assert_eq!(v.yyx(), u16vec3(2_u16, 2_u16, 1_u16));
+    assert_eq!(v.yyy(), u16vec3(2_u16, 2_u16, 2_u16));
+    assert_eq!(v.xx(), u16vec2(1_u16, 1_u16));
+    assert_eq!(v.yx(), u16vec2(2_u16, 1_u16));
+    assert_eq!(v.yy(), u16vec2(2_u16, 2_u16));
+});
diff --git a/tests/swizzles_u64.rs b/tests/swizzles_u64.rs
new file mode 100644
index 0000000..fdb2c34
--- /dev/null
+++ b/tests/swizzles_u64.rs
@@ -0,0 +1,497 @@
+// Generated by swizzlegen. Do not edit.
+#[macro_use]
+mod support;
+use glam::*;
+
+glam_test!(test_u64vec4_swizzles, {
+    let v = u64vec4(1_u64, 2_u64, 3_u64, 4_u64);
+    assert_eq!(v, v.xyzw());
+    assert_eq!(v.xxxx(), u64vec4(1_u64, 1_u64, 1_u64, 1_u64));
+    assert_eq!(v.xxxy(), u64vec4(1_u64, 1_u64, 1_u64, 2_u64));
+    assert_eq!(v.xxxz(), u64vec4(1_u64, 1_u64, 1_u64, 3_u64));
+    assert_eq!(v.xxxw(), u64vec4(1_u64, 1_u64, 1_u64, 4_u64));
+    assert_eq!(v.xxyx(), u64vec4(1_u64, 1_u64, 2_u64, 1_u64));
+    assert_eq!(v.xxyy(), u64vec4(1_u64, 1_u64, 2_u64, 2_u64));
+    assert_eq!(v.xxyz(), u64vec4(1_u64, 1_u64, 2_u64, 3_u64));
+    assert_eq!(v.xxyw(), u64vec4(1_u64, 1_u64, 2_u64, 4_u64));
+    assert_eq!(v.xxzx(), u64vec4(1_u64, 1_u64, 3_u64, 1_u64));
+    assert_eq!(v.xxzy(), u64vec4(1_u64, 1_u64, 3_u64, 2_u64));
+    assert_eq!(v.xxzz(), u64vec4(1_u64, 1_u64, 3_u64, 3_u64));
+    assert_eq!(v.xxzw(), u64vec4(1_u64, 1_u64, 3_u64, 4_u64));
+    assert_eq!(v.xxwx(), u64vec4(1_u64, 1_u64, 4_u64, 1_u64));
+    assert_eq!(v.xxwy(), u64vec4(1_u64, 1_u64, 4_u64, 2_u64));
+    assert_eq!(v.xxwz(), u64vec4(1_u64, 1_u64, 4_u64, 3_u64));
+    assert_eq!(v.xxww(), u64vec4(1_u64, 1_u64, 4_u64, 4_u64));
+    assert_eq!(v.xyxx(), u64vec4(1_u64, 2_u64, 1_u64, 1_u64));
+    assert_eq!(v.xyxy(), u64vec4(1_u64, 2_u64, 1_u64, 2_u64));
+    assert_eq!(v.xyxz(), u64vec4(1_u64, 2_u64, 1_u64, 3_u64));
+    assert_eq!(v.xyxw(), u64vec4(1_u64, 2_u64, 1_u64, 4_u64));
+    assert_eq!(v.xyyx(), u64vec4(1_u64, 2_u64, 2_u64, 1_u64));
+    assert_eq!(v.xyyy(), u64vec4(1_u64, 2_u64, 2_u64, 2_u64));
+    assert_eq!(v.xyyz(), u64vec4(1_u64, 2_u64, 2_u64, 3_u64));
+    assert_eq!(v.xyyw(), u64vec4(1_u64, 2_u64, 2_u64, 4_u64));
+    assert_eq!(v.xyzx(), u64vec4(1_u64, 2_u64, 3_u64, 1_u64));
+    assert_eq!(v.xyzy(), u64vec4(1_u64, 2_u64, 3_u64, 2_u64));
+    assert_eq!(v.xyzz(), u64vec4(1_u64, 2_u64, 3_u64, 3_u64));
+    assert_eq!(v.xywx(), u64vec4(1_u64, 2_u64, 4_u64, 1_u64));
+    assert_eq!(v.xywy(), u64vec4(1_u64, 2_u64, 4_u64, 2_u64));
+    assert_eq!(v.xywz(), u64vec4(1_u64, 2_u64, 4_u64, 3_u64));
+    assert_eq!(v.xyww(), u64vec4(1_u64, 2_u64, 4_u64, 4_u64));
+    assert_eq!(v.xzxx(), u64vec4(1_u64, 3_u64, 1_u64, 1_u64));
+    assert_eq!(v.xzxy(), u64vec4(1_u64, 3_u64, 1_u64, 2_u64));
+    assert_eq!(v.xzxz(), u64vec4(1_u64, 3_u64, 1_u64, 3_u64));
+    assert_eq!(v.xzxw(), u64vec4(1_u64, 3_u64, 1_u64, 4_u64));
+    assert_eq!(v.xzyx(), u64vec4(1_u64, 3_u64, 2_u64, 1_u64));
+    assert_eq!(v.xzyy(), u64vec4(1_u64, 3_u64, 2_u64, 2_u64));
+    assert_eq!(v.xzyz(), u64vec4(1_u64, 3_u64, 2_u64, 3_u64));
+    assert_eq!(v.xzyw(), u64vec4(1_u64, 3_u64, 2_u64, 4_u64));
+    assert_eq!(v.xzzx(), u64vec4(1_u64, 3_u64, 3_u64, 1_u64));
+    assert_eq!(v.xzzy(), u64vec4(1_u64, 3_u64, 3_u64, 2_u64));
+    assert_eq!(v.xzzz(), u64vec4(1_u64, 3_u64, 3_u64, 3_u64));
+    assert_eq!(v.xzzw(), u64vec4(1_u64, 3_u64, 3_u64, 4_u64));
+    assert_eq!(v.xzwx(), u64vec4(1_u64, 3_u64, 4_u64, 1_u64));
+    assert_eq!(v.xzwy(), u64vec4(1_u64, 3_u64, 4_u64, 2_u64));
+    assert_eq!(v.xzwz(), u64vec4(1_u64, 3_u64, 4_u64, 3_u64));
+    assert_eq!(v.xzww(), u64vec4(1_u64, 3_u64, 4_u64, 4_u64));
+    assert_eq!(v.xwxx(), u64vec4(1_u64, 4_u64, 1_u64, 1_u64));
+    assert_eq!(v.xwxy(), u64vec4(1_u64, 4_u64, 1_u64, 2_u64));
+    assert_eq!(v.xwxz(), u64vec4(1_u64, 4_u64, 1_u64, 3_u64));
+    assert_eq!(v.xwxw(), u64vec4(1_u64, 4_u64, 1_u64, 4_u64));
+    assert_eq!(v.xwyx(), u64vec4(1_u64, 4_u64, 2_u64, 1_u64));
+    assert_eq!(v.xwyy(), u64vec4(1_u64, 4_u64, 2_u64, 2_u64));
+    assert_eq!(v.xwyz(), u64vec4(1_u64, 4_u64, 2_u64, 3_u64));
+    assert_eq!(v.xwyw(), u64vec4(1_u64, 4_u64, 2_u64, 4_u64));
+    assert_eq!(v.xwzx(), u64vec4(1_u64, 4_u64, 3_u64, 1_u64));
+    assert_eq!(v.xwzy(), u64vec4(1_u64, 4_u64, 3_u64, 2_u64));
+    assert_eq!(v.xwzz(), u64vec4(1_u64, 4_u64, 3_u64, 3_u64));
+    assert_eq!(v.xwzw(), u64vec4(1_u64, 4_u64, 3_u64, 4_u64));
+    assert_eq!(v.xwwx(), u64vec4(1_u64, 4_u64, 4_u64, 1_u64));
+    assert_eq!(v.xwwy(), u64vec4(1_u64, 4_u64, 4_u64, 2_u64));
+    assert_eq!(v.xwwz(), u64vec4(1_u64, 4_u64, 4_u64, 3_u64));
+    assert_eq!(v.xwww(), u64vec4(1_u64, 4_u64, 4_u64, 4_u64));
+    assert_eq!(v.yxxx(), u64vec4(2_u64, 1_u64, 1_u64, 1_u64));
+    assert_eq!(v.yxxy(), u64vec4(2_u64, 1_u64, 1_u64, 2_u64));
+    assert_eq!(v.yxxz(), u64vec4(2_u64, 1_u64, 1_u64, 3_u64));
+    assert_eq!(v.yxxw(), u64vec4(2_u64, 1_u64, 1_u64, 4_u64));
+    assert_eq!(v.yxyx(), u64vec4(2_u64, 1_u64, 2_u64, 1_u64));
+    assert_eq!(v.yxyy(), u64vec4(2_u64, 1_u64, 2_u64, 2_u64));
+    assert_eq!(v.yxyz(), u64vec4(2_u64, 1_u64, 2_u64, 3_u64));
+    assert_eq!(v.yxyw(), u64vec4(2_u64, 1_u64, 2_u64, 4_u64));
+    assert_eq!(v.yxzx(), u64vec4(2_u64, 1_u64, 3_u64, 1_u64));
+    assert_eq!(v.yxzy(), u64vec4(2_u64, 1_u64, 3_u64, 2_u64));
+    assert_eq!(v.yxzz(), u64vec4(2_u64, 1_u64, 3_u64, 3_u64));
+    assert_eq!(v.yxzw(), u64vec4(2_u64, 1_u64, 3_u64, 4_u64));
+    assert_eq!(v.yxwx(), u64vec4(2_u64, 1_u64, 4_u64, 1_u64));
+    assert_eq!(v.yxwy(), u64vec4(2_u64, 1_u64, 4_u64, 2_u64));
+    assert_eq!(v.yxwz(), u64vec4(2_u64, 1_u64, 4_u64, 3_u64));
+    assert_eq!(v.yxww(), u64vec4(2_u64, 1_u64, 4_u64, 4_u64));
+    assert_eq!(v.yyxx(), u64vec4(2_u64, 2_u64, 1_u64, 1_u64));
+    assert_eq!(v.yyxy(), u64vec4(2_u64, 2_u64, 1_u64, 2_u64));
+    assert_eq!(v.yyxz(), u64vec4(2_u64, 2_u64, 1_u64, 3_u64));
+    assert_eq!(v.yyxw(), u64vec4(2_u64, 2_u64, 1_u64, 4_u64));
+    assert_eq!(v.yyyx(), u64vec4(2_u64, 2_u64, 2_u64, 1_u64));
+    assert_eq!(v.yyyy(), u64vec4(2_u64, 2_u64, 2_u64, 2_u64));
+    assert_eq!(v.yyyz(), u64vec4(2_u64, 2_u64, 2_u64, 3_u64));
+    assert_eq!(v.yyyw(), u64vec4(2_u64, 2_u64, 2_u64, 4_u64));
+    assert_eq!(v.yyzx(), u64vec4(2_u64, 2_u64, 3_u64, 1_u64));
+    assert_eq!(v.yyzy(), u64vec4(2_u64, 2_u64, 3_u64, 2_u64));
+    assert_eq!(v.yyzz(), u64vec4(2_u64, 2_u64, 3_u64, 3_u64));
+    assert_eq!(v.yyzw(), u64vec4(2_u64, 2_u64, 3_u64, 4_u64));
+    assert_eq!(v.yywx(), u64vec4(2_u64, 2_u64, 4_u64, 1_u64));
+    assert_eq!(v.yywy(), u64vec4(2_u64, 2_u64, 4_u64, 2_u64));
+    assert_eq!(v.yywz(), u64vec4(2_u64, 2_u64, 4_u64, 3_u64));
+    assert_eq!(v.yyww(), u64vec4(2_u64, 2_u64, 4_u64, 4_u64));
+    assert_eq!(v.yzxx(), u64vec4(2_u64, 3_u64, 1_u64, 1_u64));
+    assert_eq!(v.yzxy(), u64vec4(2_u64, 3_u64, 1_u64, 2_u64));
+    assert_eq!(v.yzxz(), u64vec4(2_u64, 3_u64, 1_u64, 3_u64));
+    assert_eq!(v.yzxw(), u64vec4(2_u64, 3_u64, 1_u64, 4_u64));
+    assert_eq!(v.yzyx(), u64vec4(2_u64, 3_u64, 2_u64, 1_u64));
+    assert_eq!(v.yzyy(), u64vec4(2_u64, 3_u64, 2_u64, 2_u64));
+    assert_eq!(v.yzyz(), u64vec4(2_u64, 3_u64, 2_u64, 3_u64));
+    assert_eq!(v.yzyw(), u64vec4(2_u64, 3_u64, 2_u64, 4_u64));
+    assert_eq!(v.yzzx(), u64vec4(2_u64, 3_u64, 3_u64, 1_u64));
+    assert_eq!(v.yzzy(), u64vec4(2_u64, 3_u64, 3_u64, 2_u64));
+    assert_eq!(v.yzzz(), u64vec4(2_u64, 3_u64, 3_u64, 3_u64));
+    assert_eq!(v.yzzw(), u64vec4(2_u64, 3_u64, 3_u64, 4_u64));
+    assert_eq!(v.yzwx(), u64vec4(2_u64, 3_u64, 4_u64, 1_u64));
+    assert_eq!(v.yzwy(), u64vec4(2_u64, 3_u64, 4_u64, 2_u64));
+    assert_eq!(v.yzwz(), u64vec4(2_u64, 3_u64, 4_u64, 3_u64));
+    assert_eq!(v.yzww(), u64vec4(2_u64, 3_u64, 4_u64, 4_u64));
+    assert_eq!(v.ywxx(), u64vec4(2_u64, 4_u64, 1_u64, 1_u64));
+    assert_eq!(v.ywxy(), u64vec4(2_u64, 4_u64, 1_u64, 2_u64));
+    assert_eq!(v.ywxz(), u64vec4(2_u64, 4_u64, 1_u64, 3_u64));
+    assert_eq!(v.ywxw(), u64vec4(2_u64, 4_u64, 1_u64, 4_u64));
+    assert_eq!(v.ywyx(), u64vec4(2_u64, 4_u64, 2_u64, 1_u64));
+    assert_eq!(v.ywyy(), u64vec4(2_u64, 4_u64, 2_u64, 2_u64));
+    assert_eq!(v.ywyz(), u64vec4(2_u64, 4_u64, 2_u64, 3_u64));
+    assert_eq!(v.ywyw(), u64vec4(2_u64, 4_u64, 2_u64, 4_u64));
+    assert_eq!(v.ywzx(), u64vec4(2_u64, 4_u64, 3_u64, 1_u64));
+    assert_eq!(v.ywzy(), u64vec4(2_u64, 4_u64, 3_u64, 2_u64));
+    assert_eq!(v.ywzz(), u64vec4(2_u64, 4_u64, 3_u64, 3_u64));
+    assert_eq!(v.ywzw(), u64vec4(2_u64, 4_u64, 3_u64, 4_u64));
+    assert_eq!(v.ywwx(), u64vec4(2_u64, 4_u64, 4_u64, 1_u64));
+    assert_eq!(v.ywwy(), u64vec4(2_u64, 4_u64, 4_u64, 2_u64));
+    assert_eq!(v.ywwz(), u64vec4(2_u64, 4_u64, 4_u64, 3_u64));
+    assert_eq!(v.ywww(), u64vec4(2_u64, 4_u64, 4_u64, 4_u64));
+    assert_eq!(v.zxxx(), u64vec4(3_u64, 1_u64, 1_u64, 1_u64));
+    assert_eq!(v.zxxy(), u64vec4(3_u64, 1_u64, 1_u64, 2_u64));
+    assert_eq!(v.zxxz(), u64vec4(3_u64, 1_u64, 1_u64, 3_u64));
+    assert_eq!(v.zxxw(), u64vec4(3_u64, 1_u64, 1_u64, 4_u64));
+    assert_eq!(v.zxyx(), u64vec4(3_u64, 1_u64, 2_u64, 1_u64));
+    assert_eq!(v.zxyy(), u64vec4(3_u64, 1_u64, 2_u64, 2_u64));
+    assert_eq!(v.zxyz(), u64vec4(3_u64, 1_u64, 2_u64, 3_u64));
+    assert_eq!(v.zxyw(), u64vec4(3_u64, 1_u64, 2_u64, 4_u64));
+    assert_eq!(v.zxzx(), u64vec4(3_u64, 1_u64, 3_u64, 1_u64));
+    assert_eq!(v.zxzy(), u64vec4(3_u64, 1_u64, 3_u64, 2_u64));
+    assert_eq!(v.zxzz(), u64vec4(3_u64, 1_u64, 3_u64, 3_u64));
+    assert_eq!(v.zxzw(), u64vec4(3_u64, 1_u64, 3_u64, 4_u64));
+    assert_eq!(v.zxwx(), u64vec4(3_u64, 1_u64, 4_u64, 1_u64));
+    assert_eq!(v.zxwy(), u64vec4(3_u64, 1_u64, 4_u64, 2_u64));
+    assert_eq!(v.zxwz(), u64vec4(3_u64, 1_u64, 4_u64, 3_u64));
+    assert_eq!(v.zxww(), u64vec4(3_u64, 1_u64, 4_u64, 4_u64));
+    assert_eq!(v.zyxx(), u64vec4(3_u64, 2_u64, 1_u64, 1_u64));
+    assert_eq!(v.zyxy(), u64vec4(3_u64, 2_u64, 1_u64, 2_u64));
+    assert_eq!(v.zyxz(), u64vec4(3_u64, 2_u64, 1_u64, 3_u64));
+    assert_eq!(v.zyxw(), u64vec4(3_u64, 2_u64, 1_u64, 4_u64));
+    assert_eq!(v.zyyx(), u64vec4(3_u64, 2_u64, 2_u64, 1_u64));
+    assert_eq!(v.zyyy(), u64vec4(3_u64, 2_u64, 2_u64, 2_u64));
+    assert_eq!(v.zyyz(), u64vec4(3_u64, 2_u64, 2_u64, 3_u64));
+    assert_eq!(v.zyyw(), u64vec4(3_u64, 2_u64, 2_u64, 4_u64));
+    assert_eq!(v.zyzx(), u64vec4(3_u64, 2_u64, 3_u64, 1_u64));
+    assert_eq!(v.zyzy(), u64vec4(3_u64, 2_u64, 3_u64, 2_u64));
+    assert_eq!(v.zyzz(), u64vec4(3_u64, 2_u64, 3_u64, 3_u64));
+    assert_eq!(v.zyzw(), u64vec4(3_u64, 2_u64, 3_u64, 4_u64));
+    assert_eq!(v.zywx(), u64vec4(3_u64, 2_u64, 4_u64, 1_u64));
+    assert_eq!(v.zywy(), u64vec4(3_u64, 2_u64, 4_u64, 2_u64));
+    assert_eq!(v.zywz(), u64vec4(3_u64, 2_u64, 4_u64, 3_u64));
+    assert_eq!(v.zyww(), u64vec4(3_u64, 2_u64, 4_u64, 4_u64));
+    assert_eq!(v.zzxx(), u64vec4(3_u64, 3_u64, 1_u64, 1_u64));
+    assert_eq!(v.zzxy(), u64vec4(3_u64, 3_u64, 1_u64, 2_u64));
+    assert_eq!(v.zzxz(), u64vec4(3_u64, 3_u64, 1_u64, 3_u64));
+    assert_eq!(v.zzxw(), u64vec4(3_u64, 3_u64, 1_u64, 4_u64));
+    assert_eq!(v.zzyx(), u64vec4(3_u64, 3_u64, 2_u64, 1_u64));
+    assert_eq!(v.zzyy(), u64vec4(3_u64, 3_u64, 2_u64, 2_u64));
+    assert_eq!(v.zzyz(), u64vec4(3_u64, 3_u64, 2_u64, 3_u64));
+    assert_eq!(v.zzyw(), u64vec4(3_u64, 3_u64, 2_u64, 4_u64));
+    assert_eq!(v.zzzx(), u64vec4(3_u64, 3_u64, 3_u64, 1_u64));
+    assert_eq!(v.zzzy(), u64vec4(3_u64, 3_u64, 3_u64, 2_u64));
+    assert_eq!(v.zzzz(), u64vec4(3_u64, 3_u64, 3_u64, 3_u64));
+    assert_eq!(v.zzzw(), u64vec4(3_u64, 3_u64, 3_u64, 4_u64));
+    assert_eq!(v.zzwx(), u64vec4(3_u64, 3_u64, 4_u64, 1_u64));
+    assert_eq!(v.zzwy(), u64vec4(3_u64, 3_u64, 4_u64, 2_u64));
+    assert_eq!(v.zzwz(), u64vec4(3_u64, 3_u64, 4_u64, 3_u64));
+    assert_eq!(v.zzww(), u64vec4(3_u64, 3_u64, 4_u64, 4_u64));
+    assert_eq!(v.zwxx(), u64vec4(3_u64, 4_u64, 1_u64, 1_u64));
+    assert_eq!(v.zwxy(), u64vec4(3_u64, 4_u64, 1_u64, 2_u64));
+    assert_eq!(v.zwxz(), u64vec4(3_u64, 4_u64, 1_u64, 3_u64));
+    assert_eq!(v.zwxw(), u64vec4(3_u64, 4_u64, 1_u64, 4_u64));
+    assert_eq!(v.zwyx(), u64vec4(3_u64, 4_u64, 2_u64, 1_u64));
+    assert_eq!(v.zwyy(), u64vec4(3_u64, 4_u64, 2_u64, 2_u64));
+    assert_eq!(v.zwyz(), u64vec4(3_u64, 4_u64, 2_u64, 3_u64));
+    assert_eq!(v.zwyw(), u64vec4(3_u64, 4_u64, 2_u64, 4_u64));
+    assert_eq!(v.zwzx(), u64vec4(3_u64, 4_u64, 3_u64, 1_u64));
+    assert_eq!(v.zwzy(), u64vec4(3_u64, 4_u64, 3_u64, 2_u64));
+    assert_eq!(v.zwzz(), u64vec4(3_u64, 4_u64, 3_u64, 3_u64));
+    assert_eq!(v.zwzw(), u64vec4(3_u64, 4_u64, 3_u64, 4_u64));
+    assert_eq!(v.zwwx(), u64vec4(3_u64, 4_u64, 4_u64, 1_u64));
+    assert_eq!(v.zwwy(), u64vec4(3_u64, 4_u64, 4_u64, 2_u64));
+    assert_eq!(v.zwwz(), u64vec4(3_u64, 4_u64, 4_u64, 3_u64));
+    assert_eq!(v.zwww(), u64vec4(3_u64, 4_u64, 4_u64, 4_u64));
+    assert_eq!(v.wxxx(), u64vec4(4_u64, 1_u64, 1_u64, 1_u64));
+    assert_eq!(v.wxxy(), u64vec4(4_u64, 1_u64, 1_u64, 2_u64));
+    assert_eq!(v.wxxz(), u64vec4(4_u64, 1_u64, 1_u64, 3_u64));
+    assert_eq!(v.wxxw(), u64vec4(4_u64, 1_u64, 1_u64, 4_u64));
+    assert_eq!(v.wxyx(), u64vec4(4_u64, 1_u64, 2_u64, 1_u64));
+    assert_eq!(v.wxyy(), u64vec4(4_u64, 1_u64, 2_u64, 2_u64));
+    assert_eq!(v.wxyz(), u64vec4(4_u64, 1_u64, 2_u64, 3_u64));
+    assert_eq!(v.wxyw(), u64vec4(4_u64, 1_u64, 2_u64, 4_u64));
+    assert_eq!(v.wxzx(), u64vec4(4_u64, 1_u64, 3_u64, 1_u64));
+    assert_eq!(v.wxzy(), u64vec4(4_u64, 1_u64, 3_u64, 2_u64));
+    assert_eq!(v.wxzz(), u64vec4(4_u64, 1_u64, 3_u64, 3_u64));
+    assert_eq!(v.wxzw(), u64vec4(4_u64, 1_u64, 3_u64, 4_u64));
+    assert_eq!(v.wxwx(), u64vec4(4_u64, 1_u64, 4_u64, 1_u64));
+    assert_eq!(v.wxwy(), u64vec4(4_u64, 1_u64, 4_u64, 2_u64));
+    assert_eq!(v.wxwz(), u64vec4(4_u64, 1_u64, 4_u64, 3_u64));
+    assert_eq!(v.wxww(), u64vec4(4_u64, 1_u64, 4_u64, 4_u64));
+    assert_eq!(v.wyxx(), u64vec4(4_u64, 2_u64, 1_u64, 1_u64));
+    assert_eq!(v.wyxy(), u64vec4(4_u64, 2_u64, 1_u64, 2_u64));
+    assert_eq!(v.wyxz(), u64vec4(4_u64, 2_u64, 1_u64, 3_u64));
+    assert_eq!(v.wyxw(), u64vec4(4_u64, 2_u64, 1_u64, 4_u64));
+    assert_eq!(v.wyyx(), u64vec4(4_u64, 2_u64, 2_u64, 1_u64));
+    assert_eq!(v.wyyy(), u64vec4(4_u64, 2_u64, 2_u64, 2_u64));
+    assert_eq!(v.wyyz(), u64vec4(4_u64, 2_u64, 2_u64, 3_u64));
+    assert_eq!(v.wyyw(), u64vec4(4_u64, 2_u64, 2_u64, 4_u64));
+    assert_eq!(v.wyzx(), u64vec4(4_u64, 2_u64, 3_u64, 1_u64));
+    assert_eq!(v.wyzy(), u64vec4(4_u64, 2_u64, 3_u64, 2_u64));
+    assert_eq!(v.wyzz(), u64vec4(4_u64, 2_u64, 3_u64, 3_u64));
+    assert_eq!(v.wyzw(), u64vec4(4_u64, 2_u64, 3_u64, 4_u64));
+    assert_eq!(v.wywx(), u64vec4(4_u64, 2_u64, 4_u64, 1_u64));
+    assert_eq!(v.wywy(), u64vec4(4_u64, 2_u64, 4_u64, 2_u64));
+    assert_eq!(v.wywz(), u64vec4(4_u64, 2_u64, 4_u64, 3_u64));
+    assert_eq!(v.wyww(), u64vec4(4_u64, 2_u64, 4_u64, 4_u64));
+    assert_eq!(v.wzxx(), u64vec4(4_u64, 3_u64, 1_u64, 1_u64));
+    assert_eq!(v.wzxy(), u64vec4(4_u64, 3_u64, 1_u64, 2_u64));
+    assert_eq!(v.wzxz(), u64vec4(4_u64, 3_u64, 1_u64, 3_u64));
+    assert_eq!(v.wzxw(), u64vec4(4_u64, 3_u64, 1_u64, 4_u64));
+    assert_eq!(v.wzyx(), u64vec4(4_u64, 3_u64, 2_u64, 1_u64));
+    assert_eq!(v.wzyy(), u64vec4(4_u64, 3_u64, 2_u64, 2_u64));
+    assert_eq!(v.wzyz(), u64vec4(4_u64, 3_u64, 2_u64, 3_u64));
+    assert_eq!(v.wzyw(), u64vec4(4_u64, 3_u64, 2_u64, 4_u64));
+    assert_eq!(v.wzzx(), u64vec4(4_u64, 3_u64, 3_u64, 1_u64));
+    assert_eq!(v.wzzy(), u64vec4(4_u64, 3_u64, 3_u64, 2_u64));
+    assert_eq!(v.wzzz(), u64vec4(4_u64, 3_u64, 3_u64, 3_u64));
+    assert_eq!(v.wzzw(), u64vec4(4_u64, 3_u64, 3_u64, 4_u64));
+    assert_eq!(v.wzwx(), u64vec4(4_u64, 3_u64, 4_u64, 1_u64));
+    assert_eq!(v.wzwy(), u64vec4(4_u64, 3_u64, 4_u64, 2_u64));
+    assert_eq!(v.wzwz(), u64vec4(4_u64, 3_u64, 4_u64, 3_u64));
+    assert_eq!(v.wzww(), u64vec4(4_u64, 3_u64, 4_u64, 4_u64));
+    assert_eq!(v.wwxx(), u64vec4(4_u64, 4_u64, 1_u64, 1_u64));
+    assert_eq!(v.wwxy(), u64vec4(4_u64, 4_u64, 1_u64, 2_u64));
+    assert_eq!(v.wwxz(), u64vec4(4_u64, 4_u64, 1_u64, 3_u64));
+    assert_eq!(v.wwxw(), u64vec4(4_u64, 4_u64, 1_u64, 4_u64));
+    assert_eq!(v.wwyx(), u64vec4(4_u64, 4_u64, 2_u64, 1_u64));
+    assert_eq!(v.wwyy(), u64vec4(4_u64, 4_u64, 2_u64, 2_u64));
+    assert_eq!(v.wwyz(), u64vec4(4_u64, 4_u64, 2_u64, 3_u64));
+    assert_eq!(v.wwyw(), u64vec4(4_u64, 4_u64, 2_u64, 4_u64));
+    assert_eq!(v.wwzx(), u64vec4(4_u64, 4_u64, 3_u64, 1_u64));
+    assert_eq!(v.wwzy(), u64vec4(4_u64, 4_u64, 3_u64, 2_u64));
+    assert_eq!(v.wwzz(), u64vec4(4_u64, 4_u64, 3_u64, 3_u64));
+    assert_eq!(v.wwzw(), u64vec4(4_u64, 4_u64, 3_u64, 4_u64));
+    assert_eq!(v.wwwx(), u64vec4(4_u64, 4_u64, 4_u64, 1_u64));
+    assert_eq!(v.wwwy(), u64vec4(4_u64, 4_u64, 4_u64, 2_u64));
+    assert_eq!(v.wwwz(), u64vec4(4_u64, 4_u64, 4_u64, 3_u64));
+    assert_eq!(v.wwww(), u64vec4(4_u64, 4_u64, 4_u64, 4_u64));
+    assert_eq!(v.xxx(), u64vec3(1_u64, 1_u64, 1_u64));
+    assert_eq!(v.xxy(), u64vec3(1_u64, 1_u64, 2_u64));
+    assert_eq!(v.xxz(), u64vec3(1_u64, 1_u64, 3_u64));
+    assert_eq!(v.xxw(), u64vec3(1_u64, 1_u64, 4_u64));
+    assert_eq!(v.xyx(), u64vec3(1_u64, 2_u64, 1_u64));
+    assert_eq!(v.xyy(), u64vec3(1_u64, 2_u64, 2_u64));
+    assert_eq!(v.xyz(), u64vec3(1_u64, 2_u64, 3_u64));
+    assert_eq!(v.xyw(), u64vec3(1_u64, 2_u64, 4_u64));
+    assert_eq!(v.xzx(), u64vec3(1_u64, 3_u64, 1_u64));
+    assert_eq!(v.xzy(), u64vec3(1_u64, 3_u64, 2_u64));
+    assert_eq!(v.xzz(), u64vec3(1_u64, 3_u64, 3_u64));
+    assert_eq!(v.xzw(), u64vec3(1_u64, 3_u64, 4_u64));
+    assert_eq!(v.xwx(), u64vec3(1_u64, 4_u64, 1_u64));
+    assert_eq!(v.xwy(), u64vec3(1_u64, 4_u64, 2_u64));
+    assert_eq!(v.xwz(), u64vec3(1_u64, 4_u64, 3_u64));
+    assert_eq!(v.xww(), u64vec3(1_u64, 4_u64, 4_u64));
+    assert_eq!(v.yxx(), u64vec3(2_u64, 1_u64, 1_u64));
+    assert_eq!(v.yxy(), u64vec3(2_u64, 1_u64, 2_u64));
+    assert_eq!(v.yxz(), u64vec3(2_u64, 1_u64, 3_u64));
+    assert_eq!(v.yxw(), u64vec3(2_u64, 1_u64, 4_u64));
+    assert_eq!(v.yyx(), u64vec3(2_u64, 2_u64, 1_u64));
+    assert_eq!(v.yyy(), u64vec3(2_u64, 2_u64, 2_u64));
+    assert_eq!(v.yyz(), u64vec3(2_u64, 2_u64, 3_u64));
+    assert_eq!(v.yyw(), u64vec3(2_u64, 2_u64, 4_u64));
+    assert_eq!(v.yzx(), u64vec3(2_u64, 3_u64, 1_u64));
+    assert_eq!(v.yzy(), u64vec3(2_u64, 3_u64, 2_u64));
+    assert_eq!(v.yzz(), u64vec3(2_u64, 3_u64, 3_u64));
+    assert_eq!(v.yzw(), u64vec3(2_u64, 3_u64, 4_u64));
+    assert_eq!(v.ywx(), u64vec3(2_u64, 4_u64, 1_u64));
+    assert_eq!(v.ywy(), u64vec3(2_u64, 4_u64, 2_u64));
+    assert_eq!(v.ywz(), u64vec3(2_u64, 4_u64, 3_u64));
+    assert_eq!(v.yww(), u64vec3(2_u64, 4_u64, 4_u64));
+    assert_eq!(v.zxx(), u64vec3(3_u64, 1_u64, 1_u64));
+    assert_eq!(v.zxy(), u64vec3(3_u64, 1_u64, 2_u64));
+    assert_eq!(v.zxz(), u64vec3(3_u64, 1_u64, 3_u64));
+    assert_eq!(v.zxw(), u64vec3(3_u64, 1_u64, 4_u64));
+    assert_eq!(v.zyx(), u64vec3(3_u64, 2_u64, 1_u64));
+    assert_eq!(v.zyy(), u64vec3(3_u64, 2_u64, 2_u64));
+    assert_eq!(v.zyz(), u64vec3(3_u64, 2_u64, 3_u64));
+    assert_eq!(v.zyw(), u64vec3(3_u64, 2_u64, 4_u64));
+    assert_eq!(v.zzx(), u64vec3(3_u64, 3_u64, 1_u64));
+    assert_eq!(v.zzy(), u64vec3(3_u64, 3_u64, 2_u64));
+    assert_eq!(v.zzz(), u64vec3(3_u64, 3_u64, 3_u64));
+    assert_eq!(v.zzw(), u64vec3(3_u64, 3_u64, 4_u64));
+    assert_eq!(v.zwx(), u64vec3(3_u64, 4_u64, 1_u64));
+    assert_eq!(v.zwy(), u64vec3(3_u64, 4_u64, 2_u64));
+    assert_eq!(v.zwz(), u64vec3(3_u64, 4_u64, 3_u64));
+    assert_eq!(v.zww(), u64vec3(3_u64, 4_u64, 4_u64));
+    assert_eq!(v.wxx(), u64vec3(4_u64, 1_u64, 1_u64));
+    assert_eq!(v.wxy(), u64vec3(4_u64, 1_u64, 2_u64));
+    assert_eq!(v.wxz(), u64vec3(4_u64, 1_u64, 3_u64));
+    assert_eq!(v.wxw(), u64vec3(4_u64, 1_u64, 4_u64));
+    assert_eq!(v.wyx(), u64vec3(4_u64, 2_u64, 1_u64));
+    assert_eq!(v.wyy(), u64vec3(4_u64, 2_u64, 2_u64));
+    assert_eq!(v.wyz(), u64vec3(4_u64, 2_u64, 3_u64));
+    assert_eq!(v.wyw(), u64vec3(4_u64, 2_u64, 4_u64));
+    assert_eq!(v.wzx(), u64vec3(4_u64, 3_u64, 1_u64));
+    assert_eq!(v.wzy(), u64vec3(4_u64, 3_u64, 2_u64));
+    assert_eq!(v.wzz(), u64vec3(4_u64, 3_u64, 3_u64));
+    assert_eq!(v.wzw(), u64vec3(4_u64, 3_u64, 4_u64));
+    assert_eq!(v.wwx(), u64vec3(4_u64, 4_u64, 1_u64));
+    assert_eq!(v.wwy(), u64vec3(4_u64, 4_u64, 2_u64));
+    assert_eq!(v.wwz(), u64vec3(4_u64, 4_u64, 3_u64));
+    assert_eq!(v.www(), u64vec3(4_u64, 4_u64, 4_u64));
+    assert_eq!(v.xx(), u64vec2(1_u64, 1_u64));
+    assert_eq!(v.xy(), u64vec2(1_u64, 2_u64));
+    assert_eq!(v.xz(), u64vec2(1_u64, 3_u64));
+    assert_eq!(v.xw(), u64vec2(1_u64, 4_u64));
+    assert_eq!(v.yx(), u64vec2(2_u64, 1_u64));
+    assert_eq!(v.yy(), u64vec2(2_u64, 2_u64));
+    assert_eq!(v.yz(), u64vec2(2_u64, 3_u64));
+    assert_eq!(v.yw(), u64vec2(2_u64, 4_u64));
+    assert_eq!(v.zx(), u64vec2(3_u64, 1_u64));
+    assert_eq!(v.zy(), u64vec2(3_u64, 2_u64));
+    assert_eq!(v.zz(), u64vec2(3_u64, 3_u64));
+    assert_eq!(v.zw(), u64vec2(3_u64, 4_u64));
+    assert_eq!(v.wx(), u64vec2(4_u64, 1_u64));
+    assert_eq!(v.wy(), u64vec2(4_u64, 2_u64));
+    assert_eq!(v.wz(), u64vec2(4_u64, 3_u64));
+    assert_eq!(v.ww(), u64vec2(4_u64, 4_u64));
+});
+
+glam_test!(test_u64vec3_swizzles, {
+    let v = u64vec3(1_u64, 2_u64, 3_u64);
+    assert_eq!(v, v.xyz());
+    assert_eq!(v.xxxx(), u64vec4(1_u64, 1_u64, 1_u64, 1_u64));
+    assert_eq!(v.xxxy(), u64vec4(1_u64, 1_u64, 1_u64, 2_u64));
+    assert_eq!(v.xxxz(), u64vec4(1_u64, 1_u64, 1_u64, 3_u64));
+    assert_eq!(v.xxyx(), u64vec4(1_u64, 1_u64, 2_u64, 1_u64));
+    assert_eq!(v.xxyy(), u64vec4(1_u64, 1_u64, 2_u64, 2_u64));
+    assert_eq!(v.xxyz(), u64vec4(1_u64, 1_u64, 2_u64, 3_u64));
+    assert_eq!(v.xxzx(), u64vec4(1_u64, 1_u64, 3_u64, 1_u64));
+    assert_eq!(v.xxzy(), u64vec4(1_u64, 1_u64, 3_u64, 2_u64));
+    assert_eq!(v.xxzz(), u64vec4(1_u64, 1_u64, 3_u64, 3_u64));
+    assert_eq!(v.xyxx(), u64vec4(1_u64, 2_u64, 1_u64, 1_u64));
+    assert_eq!(v.xyxy(), u64vec4(1_u64, 2_u64, 1_u64, 2_u64));
+    assert_eq!(v.xyxz(), u64vec4(1_u64, 2_u64, 1_u64, 3_u64));
+    assert_eq!(v.xyyx(), u64vec4(1_u64, 2_u64, 2_u64, 1_u64));
+    assert_eq!(v.xyyy(), u64vec4(1_u64, 2_u64, 2_u64, 2_u64));
+    assert_eq!(v.xyyz(), u64vec4(1_u64, 2_u64, 2_u64, 3_u64));
+    assert_eq!(v.xyzx(), u64vec4(1_u64, 2_u64, 3_u64, 1_u64));
+    assert_eq!(v.xyzy(), u64vec4(1_u64, 2_u64, 3_u64, 2_u64));
+    assert_eq!(v.xyzz(), u64vec4(1_u64, 2_u64, 3_u64, 3_u64));
+    assert_eq!(v.xzxx(), u64vec4(1_u64, 3_u64, 1_u64, 1_u64));
+    assert_eq!(v.xzxy(), u64vec4(1_u64, 3_u64, 1_u64, 2_u64));
+    assert_eq!(v.xzxz(), u64vec4(1_u64, 3_u64, 1_u64, 3_u64));
+    assert_eq!(v.xzyx(), u64vec4(1_u64, 3_u64, 2_u64, 1_u64));
+    assert_eq!(v.xzyy(), u64vec4(1_u64, 3_u64, 2_u64, 2_u64));
+    assert_eq!(v.xzyz(), u64vec4(1_u64, 3_u64, 2_u64, 3_u64));
+    assert_eq!(v.xzzx(), u64vec4(1_u64, 3_u64, 3_u64, 1_u64));
+    assert_eq!(v.xzzy(), u64vec4(1_u64, 3_u64, 3_u64, 2_u64));
+    assert_eq!(v.xzzz(), u64vec4(1_u64, 3_u64, 3_u64, 3_u64));
+    assert_eq!(v.yxxx(), u64vec4(2_u64, 1_u64, 1_u64, 1_u64));
+    assert_eq!(v.yxxy(), u64vec4(2_u64, 1_u64, 1_u64, 2_u64));
+    assert_eq!(v.yxxz(), u64vec4(2_u64, 1_u64, 1_u64, 3_u64));
+    assert_eq!(v.yxyx(), u64vec4(2_u64, 1_u64, 2_u64, 1_u64));
+    assert_eq!(v.yxyy(), u64vec4(2_u64, 1_u64, 2_u64, 2_u64));
+    assert_eq!(v.yxyz(), u64vec4(2_u64, 1_u64, 2_u64, 3_u64));
+    assert_eq!(v.yxzx(), u64vec4(2_u64, 1_u64, 3_u64, 1_u64));
+    assert_eq!(v.yxzy(), u64vec4(2_u64, 1_u64, 3_u64, 2_u64));
+    assert_eq!(v.yxzz(), u64vec4(2_u64, 1_u64, 3_u64, 3_u64));
+    assert_eq!(v.yyxx(), u64vec4(2_u64, 2_u64, 1_u64, 1_u64));
+    assert_eq!(v.yyxy(), u64vec4(2_u64, 2_u64, 1_u64, 2_u64));
+    assert_eq!(v.yyxz(), u64vec4(2_u64, 2_u64, 1_u64, 3_u64));
+    assert_eq!(v.yyyx(), u64vec4(2_u64, 2_u64, 2_u64, 1_u64));
+    assert_eq!(v.yyyy(), u64vec4(2_u64, 2_u64, 2_u64, 2_u64));
+    assert_eq!(v.yyyz(), u64vec4(2_u64, 2_u64, 2_u64, 3_u64));
+    assert_eq!(v.yyzx(), u64vec4(2_u64, 2_u64, 3_u64, 1_u64));
+    assert_eq!(v.yyzy(), u64vec4(2_u64, 2_u64, 3_u64, 2_u64));
+    assert_eq!(v.yyzz(), u64vec4(2_u64, 2_u64, 3_u64, 3_u64));
+    assert_eq!(v.yzxx(), u64vec4(2_u64, 3_u64, 1_u64, 1_u64));
+    assert_eq!(v.yzxy(), u64vec4(2_u64, 3_u64, 1_u64, 2_u64));
+    assert_eq!(v.yzxz(), u64vec4(2_u64, 3_u64, 1_u64, 3_u64));
+    assert_eq!(v.yzyx(), u64vec4(2_u64, 3_u64, 2_u64, 1_u64));
+    assert_eq!(v.yzyy(), u64vec4(2_u64, 3_u64, 2_u64, 2_u64));
+    assert_eq!(v.yzyz(), u64vec4(2_u64, 3_u64, 2_u64, 3_u64));
+    assert_eq!(v.yzzx(), u64vec4(2_u64, 3_u64, 3_u64, 1_u64));
+    assert_eq!(v.yzzy(), u64vec4(2_u64, 3_u64, 3_u64, 2_u64));
+    assert_eq!(v.yzzz(), u64vec4(2_u64, 3_u64, 3_u64, 3_u64));
+    assert_eq!(v.zxxx(), u64vec4(3_u64, 1_u64, 1_u64, 1_u64));
+    assert_eq!(v.zxxy(), u64vec4(3_u64, 1_u64, 1_u64, 2_u64));
+    assert_eq!(v.zxxz(), u64vec4(3_u64, 1_u64, 1_u64, 3_u64));
+    assert_eq!(v.zxyx(), u64vec4(3_u64, 1_u64, 2_u64, 1_u64));
+    assert_eq!(v.zxyy(), u64vec4(3_u64, 1_u64, 2_u64, 2_u64));
+    assert_eq!(v.zxyz(), u64vec4(3_u64, 1_u64, 2_u64, 3_u64));
+    assert_eq!(v.zxzx(), u64vec4(3_u64, 1_u64, 3_u64, 1_u64));
+    assert_eq!(v.zxzy(), u64vec4(3_u64, 1_u64, 3_u64, 2_u64));
+    assert_eq!(v.zxzz(), u64vec4(3_u64, 1_u64, 3_u64, 3_u64));
+    assert_eq!(v.zyxx(), u64vec4(3_u64, 2_u64, 1_u64, 1_u64));
+    assert_eq!(v.zyxy(), u64vec4(3_u64, 2_u64, 1_u64, 2_u64));
+    assert_eq!(v.zyxz(), u64vec4(3_u64, 2_u64, 1_u64, 3_u64));
+    assert_eq!(v.zyyx(), u64vec4(3_u64, 2_u64, 2_u64, 1_u64));
+    assert_eq!(v.zyyy(), u64vec4(3_u64, 2_u64, 2_u64, 2_u64));
+    assert_eq!(v.zyyz(), u64vec4(3_u64, 2_u64, 2_u64, 3_u64));
+    assert_eq!(v.zyzx(), u64vec4(3_u64, 2_u64, 3_u64, 1_u64));
+    assert_eq!(v.zyzy(), u64vec4(3_u64, 2_u64, 3_u64, 2_u64));
+    assert_eq!(v.zyzz(), u64vec4(3_u64, 2_u64, 3_u64, 3_u64));
+    assert_eq!(v.zzxx(), u64vec4(3_u64, 3_u64, 1_u64, 1_u64));
+    assert_eq!(v.zzxy(), u64vec4(3_u64, 3_u64, 1_u64, 2_u64));
+    assert_eq!(v.zzxz(), u64vec4(3_u64, 3_u64, 1_u64, 3_u64));
+    assert_eq!(v.zzyx(), u64vec4(3_u64, 3_u64, 2_u64, 1_u64));
+    assert_eq!(v.zzyy(), u64vec4(3_u64, 3_u64, 2_u64, 2_u64));
+    assert_eq!(v.zzyz(), u64vec4(3_u64, 3_u64, 2_u64, 3_u64));
+    assert_eq!(v.zzzx(), u64vec4(3_u64, 3_u64, 3_u64, 1_u64));
+    assert_eq!(v.zzzy(), u64vec4(3_u64, 3_u64, 3_u64, 2_u64));
+    assert_eq!(v.zzzz(), u64vec4(3_u64, 3_u64, 3_u64, 3_u64));
+    assert_eq!(v.xxx(), u64vec3(1_u64, 1_u64, 1_u64));
+    assert_eq!(v.xxy(), u64vec3(1_u64, 1_u64, 2_u64));
+    assert_eq!(v.xxz(), u64vec3(1_u64, 1_u64, 3_u64));
+    assert_eq!(v.xyx(), u64vec3(1_u64, 2_u64, 1_u64));
+    assert_eq!(v.xyy(), u64vec3(1_u64, 2_u64, 2_u64));
+    assert_eq!(v.xzx(), u64vec3(1_u64, 3_u64, 1_u64));
+    assert_eq!(v.xzy(), u64vec3(1_u64, 3_u64, 2_u64));
+    assert_eq!(v.xzz(), u64vec3(1_u64, 3_u64, 3_u64));
+    assert_eq!(v.yxx(), u64vec3(2_u64, 1_u64, 1_u64));
+    assert_eq!(v.yxy(), u64vec3(2_u64, 1_u64, 2_u64));
+    assert_eq!(v.yxz(), u64vec3(2_u64, 1_u64, 3_u64));
+    assert_eq!(v.yyx(), u64vec3(2_u64, 2_u64, 1_u64));
+    assert_eq!(v.yyy(), u64vec3(2_u64, 2_u64, 2_u64));
+    assert_eq!(v.yyz(), u64vec3(2_u64, 2_u64, 3_u64));
+    assert_eq!(v.yzx(), u64vec3(2_u64, 3_u64, 1_u64));
+    assert_eq!(v.yzy(), u64vec3(2_u64, 3_u64, 2_u64));
+    assert_eq!(v.yzz(), u64vec3(2_u64, 3_u64, 3_u64));
+    assert_eq!(v.zxx(), u64vec3(3_u64, 1_u64, 1_u64));
+    assert_eq!(v.zxy(), u64vec3(3_u64, 1_u64, 2_u64));
+    assert_eq!(v.zxz(), u64vec3(3_u64, 1_u64, 3_u64));
+    assert_eq!(v.zyx(), u64vec3(3_u64, 2_u64, 1_u64));
+    assert_eq!(v.zyy(), u64vec3(3_u64, 2_u64, 2_u64));
+    assert_eq!(v.zyz(), u64vec3(3_u64, 2_u64, 3_u64));
+    assert_eq!(v.zzx(), u64vec3(3_u64, 3_u64, 1_u64));
+    assert_eq!(v.zzy(), u64vec3(3_u64, 3_u64, 2_u64));
+    assert_eq!(v.zzz(), u64vec3(3_u64, 3_u64, 3_u64));
+    assert_eq!(v.xx(), u64vec2(1_u64, 1_u64));
+    assert_eq!(v.xy(), u64vec2(1_u64, 2_u64));
+    assert_eq!(v.xz(), u64vec2(1_u64, 3_u64));
+    assert_eq!(v.yx(), u64vec2(2_u64, 1_u64));
+    assert_eq!(v.yy(), u64vec2(2_u64, 2_u64));
+    assert_eq!(v.yz(), u64vec2(2_u64, 3_u64));
+    assert_eq!(v.zx(), u64vec2(3_u64, 1_u64));
+    assert_eq!(v.zy(), u64vec2(3_u64, 2_u64));
+    assert_eq!(v.zz(), u64vec2(3_u64, 3_u64));
+});
+
+glam_test!(test_u64vec2_swizzles, {
+    let v = u64vec2(1_u64, 2_u64);
+    assert_eq!(v, v.xy());
+    assert_eq!(v.xxxx(), u64vec4(1_u64, 1_u64, 1_u64, 1_u64));
+    assert_eq!(v.xxxy(), u64vec4(1_u64, 1_u64, 1_u64, 2_u64));
+    assert_eq!(v.xxyx(), u64vec4(1_u64, 1_u64, 2_u64, 1_u64));
+    assert_eq!(v.xxyy(), u64vec4(1_u64, 1_u64, 2_u64, 2_u64));
+    assert_eq!(v.xyxx(), u64vec4(1_u64, 2_u64, 1_u64, 1_u64));
+    assert_eq!(v.xyxy(), u64vec4(1_u64, 2_u64, 1_u64, 2_u64));
+    assert_eq!(v.xyyx(), u64vec4(1_u64, 2_u64, 2_u64, 1_u64));
+    assert_eq!(v.xyyy(), u64vec4(1_u64, 2_u64, 2_u64, 2_u64));
+    assert_eq!(v.yxxx(), u64vec4(2_u64, 1_u64, 1_u64, 1_u64));
+    assert_eq!(v.yxxy(), u64vec4(2_u64, 1_u64, 1_u64, 2_u64));
+    assert_eq!(v.yxyx(), u64vec4(2_u64, 1_u64, 2_u64, 1_u64));
+    assert_eq!(v.yxyy(), u64vec4(2_u64, 1_u64, 2_u64, 2_u64));
+    assert_eq!(v.yyxx(), u64vec4(2_u64, 2_u64, 1_u64, 1_u64));
+    assert_eq!(v.yyxy(), u64vec4(2_u64, 2_u64, 1_u64, 2_u64));
+    assert_eq!(v.yyyx(), u64vec4(2_u64, 2_u64, 2_u64, 1_u64));
+    assert_eq!(v.yyyy(), u64vec4(2_u64, 2_u64, 2_u64, 2_u64));
+    assert_eq!(v.xxx(), u64vec3(1_u64, 1_u64, 1_u64));
+    assert_eq!(v.xxy(), u64vec3(1_u64, 1_u64, 2_u64));
+    assert_eq!(v.xyx(), u64vec3(1_u64, 2_u64, 1_u64));
+    assert_eq!(v.xyy(), u64vec3(1_u64, 2_u64, 2_u64));
+    assert_eq!(v.yxx(), u64vec3(2_u64, 1_u64, 1_u64));
+    assert_eq!(v.yxy(), u64vec3(2_u64, 1_u64, 2_u64));
+    assert_eq!(v.yyx(), u64vec3(2_u64, 2_u64, 1_u64));
+    assert_eq!(v.yyy(), u64vec3(2_u64, 2_u64, 2_u64));
+    assert_eq!(v.xx(), u64vec2(1_u64, 1_u64));
+    assert_eq!(v.yx(), u64vec2(2_u64, 1_u64));
+    assert_eq!(v.yy(), u64vec2(2_u64, 2_u64));
+});
diff --git a/tests/vec2.rs b/tests/vec2.rs
index 65bc6a2..fd6df74 100644
--- a/tests/vec2.rs
+++ b/tests/vec2.rs
@@ -4,7 +4,7 @@
 mod support;
 
 macro_rules! impl_vec2_tests {
-    ($t:ty, $new:ident, $vec2:ident, $vec3:ident, $mask:ident) => {
+    ($t:ident, $new:ident, $vec2:ident, $vec3:ident, $mask:ident) => {
         glam_test!(test_const, {
             const V0: $vec2 = $vec2::splat(1 as $t);
             const V1: $vec2 = $vec2::new(1 as $t, 2 as $t);
@@ -19,6 +19,8 @@
             assert_eq!($vec2::ONE, $new(1 as $t, 1 as $t));
             assert_eq!($vec2::X, $new(1 as $t, 0 as $t));
             assert_eq!($vec2::Y, $new(0 as $t, 1 as $t));
+            assert_eq!($vec2::MIN, $new($t::MIN, $t::MIN));
+            assert_eq!($vec2::MAX, $new($t::MAX, $t::MAX));
         });
 
         glam_test!(test_new, {
@@ -100,6 +102,20 @@
             let y = $new(0 as $t, 1 as $t);
             assert_eq!(1 as $t, x.dot(x));
             assert_eq!(0 as $t, x.dot(y));
+
+            assert_eq!(
+                $new(8 as $t, 8 as $t),
+                $new(1 as $t, 2 as $t).dot_into_vec($new(4 as $t, 2 as $t))
+            );
+        });
+
+        glam_test!(test_length_squared_unsigned, {
+            let x = $new(1 as $t, 0 as $t);
+            assert_eq!(4 as $t, (2 as $t * x).length_squared());
+            assert_eq!(
+                2 as $t * 2 as $t + 3 as $t * 3 as $t,
+                $new(2 as $t, 3 as $t).length_squared()
+            );
         });
 
         glam_test!(test_ops, {
@@ -409,6 +425,30 @@
             assert_ne!(b, c);
         });
 
+        glam_test!(test_mask_test, {
+            let a = $mask::new(true, false);
+            assert_eq!(a.test(0), true);
+            assert_eq!(a.test(1), false);
+
+            let b = $mask::new(false, true);
+            assert_eq!(b.test(0), false);
+            assert_eq!(b.test(1), true);
+        });
+
+        glam_test!(test_mask_set, {
+            let mut a = $mask::new(false, true);
+            a.set(0, true);
+            assert_eq!(a.test(0), true);
+            a.set(1, false);
+            assert_eq!(a.test(1), false);
+
+            let mut b = $mask::new(true, false);
+            b.set(0, false);
+            assert_eq!(b.test(0), false);
+            b.set(1, true);
+            assert_eq!(b.test(1), true);
+        });
+
         glam_test!(test_mask_hash, {
             use std::collections::hash_map::DefaultHasher;
             use std::hash::Hash;
@@ -448,14 +488,14 @@
 
         glam_test!(test_sum, {
             let one = $vec2::ONE;
-            assert_eq!(vec![one, one].iter().sum::<$vec2>(), one + one);
-            assert_eq!(vec![one, one].into_iter().sum::<$vec2>(), one + one);
+            assert_eq!([one, one].iter().sum::<$vec2>(), one + one);
+            assert_eq!([one, one].into_iter().sum::<$vec2>(), one + one);
         });
 
         glam_test!(test_product, {
             let two = $vec2::new(2 as $t, 2 as $t);
-            assert_eq!(vec![two, two].iter().product::<$vec2>(), two * two);
-            assert_eq!(vec![two, two].into_iter().product::<$vec2>(), two * two);
+            assert_eq!([two, two].iter().product::<$vec2>(), two * two);
+            assert_eq!([two, two].into_iter().product::<$vec2>(), two * two);
         });
     };
 }
@@ -464,6 +504,22 @@
     ($t:ident, $new:ident, $vec2:ident, $vec3:ident, $mask:ident) => {
         impl_vec2_tests!($t, $new, $vec2, $vec3, $mask);
 
+        glam_test!(test_is_negative_bitmask, {
+            assert_eq!($vec2::ZERO.is_negative_bitmask(), 0b00);
+            assert_eq!($vec2::ONE.is_negative_bitmask(), 0b00);
+            assert_eq!((-$vec2::ONE).is_negative_bitmask(), 0b11);
+            assert_eq!($vec2::new(-1 as $t, 2 as $t).is_negative_bitmask(), 0b01);
+            assert_eq!($vec2::new(8 as $t, 3 as $t).is_negative_bitmask(), 0b00);
+            assert_eq!($vec2::new(3 as $t, -4 as $t).is_negative_bitmask(), 0b10);
+            assert_eq!($vec2::new(-2 as $t, -6 as $t).is_negative_bitmask(), 0b11);
+        });
+
+        glam_test!(test_abs, {
+            assert_eq!($vec2::ZERO.abs(), $vec2::ZERO);
+            assert_eq!($vec2::ONE.abs(), $vec2::ONE);
+            assert_eq!((-$vec2::ONE).abs(), $vec2::ONE);
+        });
+
         glam_test!(test_dot_signed, {
             let x = $new(1 as $t, 0 as $t);
             let y = $new(0 as $t, 1 as $t);
@@ -472,6 +528,14 @@
             assert_eq!(-1 as $t, x.dot(-x));
         });
 
+        glam_test!(test_length_squared_signed, {
+            let x = $new(1 as $t, 0 as $t);
+            let y = $new(0 as $t, 1 as $t);
+            assert_eq!(9 as $t, (-3 as $t * y).length_squared());
+            assert_eq!(2 as $t, x.distance_squared(y));
+            assert_eq!(13 as $t, (2 as $t * x).distance_squared(-3 as $t * y));
+        });
+
         glam_test!(test_neg, {
             let a = $new(1 as $t, 2 as $t);
             assert_eq!($new(-1 as $t, -2 as $t), (-a));
@@ -496,6 +560,39 @@
                 $vec2::new(-1 as $t, 1 as $t)
             );
         });
+
+        glam_test!(test_div_euclid, {
+            let one = $vec2::ONE;
+            let two = one + one;
+            let three = two + one;
+            assert_eq!(three.div_euclid(two), one);
+            assert_eq!((-three).div_euclid(two), -two);
+            assert_eq!(three.div_euclid(-two), -one);
+            assert_eq!((-three).div_euclid(-two), two);
+        });
+
+        glam_test!(test_rem_euclid, {
+            let one = $vec2::ONE;
+            let two = one + one;
+            let three = two + one;
+            let four = three + one;
+            assert_eq!(four.rem_euclid(three), one);
+            assert_eq!((-four).rem_euclid(three), two);
+            assert_eq!(four.rem_euclid(-three), one);
+            assert_eq!((-four).rem_euclid(-three), two);
+        });
+    };
+}
+
+macro_rules! impl_vec2_signed_integer_tests {
+    ($t:ident, $new:ident, $vec2:ident, $vec3:ident, $mask:ident) => {
+        impl_vec2_signed_tests!($t, $new, $vec2, $vec3, $mask);
+
+        glam_test!(test_signum, {
+            assert_eq!($vec3::ZERO.signum(), $vec3::ZERO);
+            assert_eq!($vec3::ONE.signum(), $vec3::ONE);
+            assert_eq!((-$vec3::ONE).signum(), -$vec3::ONE);
+        });
     };
 }
 
@@ -547,19 +644,13 @@
         glam_test!(test_length, {
             let x = $new(1.0, 0.0);
             let y = $new(0.0, 1.0);
-            assert_eq!(4.0, (2.0 * x).length_squared());
-            assert_eq!(9.0, (-3.0 * y).length_squared());
             assert_eq!(2.0, (-2.0 * x).length());
             assert_eq!(3.0, (3.0 * y).length());
-            assert_eq!(2.0, x.distance_squared(y));
-            assert_eq!(13.0, (2.0 * x).distance_squared(-3.0 * y));
             assert_eq!((2.0 as $t).sqrt(), x.distance(y));
             assert_eq!(5.0, (3.0 * x).distance(-4.0 * y));
             assert_eq!(13.0, (-5.0 * x).distance(12.0 * y));
             assert_eq!(x, (2.0 * x).normalize());
             assert_eq!(1.0 * 3.0 + 2.0 * 4.0, $new(1.0, 2.0).dot($new(3.0, 4.0)));
-            assert_eq!($new(8.0, 8.0), $new(1.0, 2.0).dot_into_vec($new(4.0, 2.0)));
-            assert_eq!(2.0 * 2.0 + 3.0 * 3.0, $new(2.0, 3.0).length_squared());
             assert_eq!(
                 (2.0 as $t * 2.0 + 3.0 * 3.0).sqrt(),
                 $new(2.0, 3.0).length()
@@ -598,9 +689,9 @@
             assert_eq!((-$vec2::ZERO).signum(), -$vec2::ONE);
             assert_eq!($vec2::ONE.signum(), $vec2::ONE);
             assert_eq!((-$vec2::ONE).signum(), -$vec2::ONE);
-            assert_eq!($vec2::splat(INFINITY).signum(), $vec2::ONE);
-            assert_eq!($vec2::splat(NEG_INFINITY).signum(), -$vec2::ONE);
-            assert!($vec2::splat(NAN).signum().is_nan_mask().all());
+            assert_eq!($vec2::INFINITY.signum(), $vec2::ONE);
+            assert_eq!($vec2::NEG_INFINITY.signum(), -$vec2::ONE);
+            assert!($vec2::NAN.signum().is_nan_mask().all());
         });
 
         glam_test!(test_copysign, {
@@ -620,41 +711,26 @@
             assert_eq!((-$vec2::ONE).copysign(-$vec2::ONE), -$vec2::ONE);
             assert_eq!($vec2::ONE.copysign($vec2::ONE), $vec2::ONE);
             assert_eq!((-$vec2::ONE).copysign($vec2::ONE), $vec2::ONE);
+            assert_eq!($vec2::INFINITY.copysign($vec2::ONE), $vec2::INFINITY);
+            assert_eq!($vec2::INFINITY.copysign(-$vec2::ONE), $vec2::NEG_INFINITY);
+            assert_eq!($vec2::NEG_INFINITY.copysign($vec2::ONE), $vec2::INFINITY);
             assert_eq!(
-                $vec2::splat(INFINITY).copysign($vec2::ONE),
-                $vec2::splat(INFINITY)
+                $vec2::NEG_INFINITY.copysign(-$vec2::ONE),
+                $vec2::NEG_INFINITY
             );
-            assert_eq!(
-                $vec2::splat(INFINITY).copysign(-$vec2::ONE),
-                $vec2::splat(NEG_INFINITY)
-            );
-            assert_eq!(
-                $vec2::splat(NEG_INFINITY).copysign($vec2::ONE),
-                $vec2::splat(INFINITY)
-            );
-            assert_eq!(
-                $vec2::splat(NEG_INFINITY).copysign(-$vec2::ONE),
-                $vec2::splat(NEG_INFINITY)
-            );
-            assert!($vec2::splat(NAN).copysign($vec2::ONE).is_nan_mask().all());
-            assert!($vec2::splat(NAN).copysign(-$vec2::ONE).is_nan_mask().all());
+            assert!($vec2::NAN.copysign($vec2::ONE).is_nan_mask().all());
+            assert!($vec2::NAN.copysign(-$vec2::ONE).is_nan_mask().all());
         });
 
-        glam_test!(test_is_negative_bitmask, {
+        glam_test!(test_float_is_negative_bitmask, {
             assert_eq!($vec2::ZERO.is_negative_bitmask(), 0b00);
             assert_eq!((-$vec2::ZERO).is_negative_bitmask(), 0b11);
             assert_eq!($vec2::ONE.is_negative_bitmask(), 0b00);
             assert_eq!((-$vec2::ONE).is_negative_bitmask(), 0b11);
-            assert_eq!($vec2::new(-0.1, 0.2).is_negative_bitmask(), 0b01);
-            assert_eq!($vec2::new(0.8, 0.3).is_negative_bitmask(), 0b00);
-            assert_eq!($vec2::new(0.3, -0.4).is_negative_bitmask(), 0b10);
-            assert_eq!($vec2::new(-0.2, -0.6).is_negative_bitmask(), 0b11);
-        });
-
-        glam_test!(test_abs, {
-            assert_eq!($vec2::ZERO.abs(), $vec2::ZERO);
-            assert_eq!($vec2::ONE.abs(), $vec2::ONE);
-            assert_eq!((-$vec2::ONE).abs(), $vec2::ONE);
+            assert_eq!($vec2::new(-1.0, 2.0).is_negative_bitmask(), 0b01);
+            assert_eq!($vec2::new(8.0, 3.0).is_negative_bitmask(), 0b00);
+            assert_eq!($vec2::new(3.0, -4.0).is_negative_bitmask(), 0b10);
+            assert_eq!($vec2::new(-2.0, -6.0).is_negative_bitmask(), 0b11);
         });
 
         glam_test!(test_round, {
@@ -707,6 +783,19 @@
             );
         });
 
+        glam_test!(test_trunc, {
+            assert_eq!($vec2::new(1.35, -1.5).trunc(), $vec2::new(1.0, -1.0));
+            assert_eq!(
+                $vec2::new(INFINITY, NEG_INFINITY).trunc(),
+                $vec2::new(INFINITY, NEG_INFINITY)
+            );
+            assert!($vec2::new(0.0, NAN).trunc().y.is_nan());
+            assert_eq!(
+                $vec2::new(-0.0, -2000000.123).trunc(),
+                $vec2::new(-0.0, -2000000.0)
+            );
+        });
+
         glam_test!(test_lerp, {
             let v0 = $vec2::new(-1.0, -1.0);
             let v1 = $vec2::new(1.0, 1.0);
@@ -722,6 +811,8 @@
             assert!(!$vec2::new(0.0, NAN).is_finite());
             assert!(!$vec2::new(0.0, NEG_INFINITY).is_finite());
             assert!(!$vec2::new(INFINITY, NEG_INFINITY).is_finite());
+            assert!(!$vec2::INFINITY.is_finite());
+            assert!(!$vec2::NEG_INFINITY.is_finite());
         });
 
         glam_test!(test_powf, {
@@ -805,20 +896,27 @@
             );
         });
 
-        glam_test!(test_from_angle, {
-            assert_approx_eq!($vec2::from_angle(0.0), $vec2::new(1.0, 0.0));
-            assert_approx_eq!(
-                $vec2::from_angle(core::$t::consts::FRAC_PI_2),
-                $vec2::new(0.0, 1.0)
-            );
-            assert_approx_eq!(
-                $vec2::from_angle(core::$t::consts::PI),
-                $vec2::new(-1.0, 0.0)
-            );
-            assert_approx_eq!(
-                $vec2::from_angle(-core::$t::consts::FRAC_PI_2),
-                $vec2::new(0.0, -1.0)
-            );
+        glam_test!(test_angle_conversion, {
+            let angle = 0.;
+            let vec = $vec2::from_angle(angle);
+            assert_approx_eq!(vec, $vec2::new(1.0, 0.0));
+            assert_approx_eq!(vec.to_angle(), angle);
+
+            let angle = core::$t::consts::FRAC_PI_2;
+            let vec = $vec2::from_angle(angle);
+            assert_approx_eq!(vec, $vec2::new(0.0, 1.0));
+            assert_approx_eq!(vec.to_angle(), angle);
+
+            let angle = core::$t::consts::PI;
+            let vec = $vec2::from_angle(angle);
+            assert_approx_eq!(vec, $vec2::new(-1.0, 0.0));
+            // The sign of the angle PI gets flipped and is slightly less precise but correct
+            assert_approx_eq!(vec.to_angle().abs(), angle, 1e-6);
+
+            let angle = -core::$t::consts::FRAC_PI_2;
+            let vec = $vec2::from_angle(angle);
+            assert_approx_eq!(vec, $vec2::new(0.0, -1.0));
+            assert_approx_eq!(vec.to_angle(), angle);
         });
     };
 }
@@ -852,6 +950,10 @@
             use glam::$vec2;
             impl_vec2_scalar_shift_op_test!($vec2, $t_min, $t_max, 0i32, 2);
         }
+        mod shift_by_i64 {
+            use glam::$vec2;
+            impl_vec2_scalar_shift_op_test!($vec2, $t_min, $t_max, 0i64, 2);
+        }
         mod shift_by_u8 {
             use glam::$vec2;
             impl_vec2_scalar_shift_op_test!($vec2, $t_min, $t_max, 0u8, 2);
@@ -864,6 +966,10 @@
             use glam::$vec2;
             impl_vec2_scalar_shift_op_test!($vec2, $t_min, $t_max, 0u32, 2);
         }
+        mod shift_by_u64 {
+            use glam::$vec2;
+            impl_vec2_scalar_shift_op_test!($vec2, $t_min, $t_max, 0u64, 2);
+        }
     };
 }
 
@@ -963,29 +1069,77 @@
     });
 
     glam_test!(test_as, {
-        use glam::{DVec2, IVec2, UVec2};
+        use glam::{DVec2, I16Vec2, I64Vec2, IVec2, U16Vec2, U64Vec2, UVec2};
         assert_eq!(DVec2::new(-1.0, -2.0), Vec2::new(-1.0, -2.0).as_dvec2());
+        assert_eq!(I16Vec2::new(-1, -2), Vec2::new(-1.0, -2.0).as_i16vec2());
+        assert_eq!(U16Vec2::new(1, 2), Vec2::new(1.0, 2.0).as_u16vec2());
         assert_eq!(IVec2::new(-1, -2), Vec2::new(-1.0, -2.0).as_ivec2());
         assert_eq!(UVec2::new(1, 2), Vec2::new(1.0, 2.0).as_uvec2());
+        assert_eq!(I64Vec2::new(-1, -2), Vec2::new(-1.0, -2.0).as_i64vec2());
+        assert_eq!(U64Vec2::new(1, 2), Vec2::new(1.0, 2.0).as_u64vec2());
 
+        assert_eq!(Vec2::new(-1.0, -2.0), DVec2::new(-1.0, -2.0).as_vec2());
+        assert_eq!(I16Vec2::new(-1, -2), DVec2::new(-1.0, -2.0).as_i16vec2());
+        assert_eq!(U16Vec2::new(1, 2), DVec2::new(1.0, 2.0).as_u16vec2());
         assert_eq!(IVec2::new(-1, -2), DVec2::new(-1.0, -2.0).as_ivec2());
         assert_eq!(UVec2::new(1, 2), DVec2::new(1.0, 2.0).as_uvec2());
-        assert_eq!(Vec2::new(-1.0, -2.0), DVec2::new(-1.0, -2.0).as_vec2());
+        assert_eq!(I64Vec2::new(-1, -2), DVec2::new(-1.0, -2.0).as_i64vec2());
+        assert_eq!(U64Vec2::new(1, 2), DVec2::new(1.0, 2.0).as_u64vec2());
 
+        assert_eq!(Vec2::new(-1.0, -2.0), I16Vec2::new(-1, -2).as_vec2());
+        assert_eq!(DVec2::new(-1.0, -2.0), I16Vec2::new(-1, -2).as_dvec2());
+        assert_eq!(U16Vec2::new(1, 2), I16Vec2::new(1, 2).as_u16vec2());
+        assert_eq!(IVec2::new(-1, -2), I16Vec2::new(-1, -2).as_ivec2());
+        assert_eq!(UVec2::new(1, 2), I16Vec2::new(1, 2).as_uvec2());
+        assert_eq!(I64Vec2::new(-1, -2), I16Vec2::new(-1, -2).as_i64vec2());
+        assert_eq!(U64Vec2::new(1, 2), I16Vec2::new(1, 2).as_u64vec2());
+
+        assert_eq!(Vec2::new(1.0, 2.0), U16Vec2::new(1, 2).as_vec2());
+        assert_eq!(DVec2::new(1.0, 2.0), U16Vec2::new(1, 2).as_dvec2());
+        assert_eq!(I16Vec2::new(1, 2), U16Vec2::new(1, 2).as_i16vec2());
+        assert_eq!(IVec2::new(1, 2), U16Vec2::new(1, 2).as_ivec2());
+        assert_eq!(UVec2::new(1, 2), U16Vec2::new(1, 2).as_uvec2());
+        assert_eq!(I64Vec2::new(1, 2), U16Vec2::new(1, 2).as_i64vec2());
+        assert_eq!(U64Vec2::new(1, 2), U16Vec2::new(1, 2).as_u64vec2());
+
+        assert_eq!(Vec2::new(-1.0, -2.0), IVec2::new(-1, -2).as_vec2());
         assert_eq!(DVec2::new(-1.0, -2.0), IVec2::new(-1, -2).as_dvec2());
         assert_eq!(UVec2::new(1, 2), IVec2::new(1, 2).as_uvec2());
-        assert_eq!(Vec2::new(-1.0, -2.0), IVec2::new(-1, -2).as_vec2());
+        assert_eq!(I16Vec2::new(-1, -2), IVec2::new(-1, -2).as_i16vec2());
+        assert_eq!(U16Vec2::new(1, 2), IVec2::new(1, 2).as_u16vec2());
+        assert_eq!(I64Vec2::new(-1, -2), IVec2::new(-1, -2).as_i64vec2());
+        assert_eq!(U64Vec2::new(1, 2), IVec2::new(1, 2).as_u64vec2());
 
-        assert_eq!(DVec2::new(1.0, 2.0), UVec2::new(1, 2).as_dvec2());
-        assert_eq!(IVec2::new(1, 2), UVec2::new(1, 2).as_ivec2());
         assert_eq!(Vec2::new(1.0, 2.0), UVec2::new(1, 2).as_vec2());
+        assert_eq!(DVec2::new(1.0, 2.0), UVec2::new(1, 2).as_dvec2());
+        assert_eq!(I16Vec2::new(1, 2), UVec2::new(1, 2).as_i16vec2());
+        assert_eq!(U16Vec2::new(1, 2), UVec2::new(1, 2).as_u16vec2());
+        assert_eq!(IVec2::new(1, 2), UVec2::new(1, 2).as_ivec2());
+        assert_eq!(I64Vec2::new(1, 2), UVec2::new(1, 2).as_i64vec2());
+        assert_eq!(U64Vec2::new(1, 2), UVec2::new(1, 2).as_u64vec2());
+
+        assert_eq!(Vec2::new(-1.0, -2.0), I64Vec2::new(-1, -2).as_vec2());
+        assert_eq!(DVec2::new(-1.0, -2.0), I64Vec2::new(-1, -2).as_dvec2());
+        assert_eq!(U16Vec2::new(1, 2), I64Vec2::new(1, 2).as_u16vec2());
+        assert_eq!(I16Vec2::new(-1, -2), I64Vec2::new(-1, -2).as_i16vec2());
+        assert_eq!(UVec2::new(1, 2), I64Vec2::new(1, 2).as_uvec2());
+        assert_eq!(IVec2::new(-1, -2), I64Vec2::new(-1, -2).as_ivec2());
+        assert_eq!(U64Vec2::new(1, 2), I64Vec2::new(1, 2).as_u64vec2());
+
+        assert_eq!(Vec2::new(1.0, 2.0), U64Vec2::new(1, 2).as_vec2());
+        assert_eq!(DVec2::new(1.0, 2.0), U64Vec2::new(1, 2).as_dvec2());
+        assert_eq!(I16Vec2::new(1, 2), U64Vec2::new(1, 2).as_i16vec2());
+        assert_eq!(U16Vec2::new(1, 2), U64Vec2::new(1, 2).as_u16vec2());
+        assert_eq!(IVec2::new(1, 2), U64Vec2::new(1, 2).as_ivec2());
+        assert_eq!(UVec2::new(1, 2), U64Vec2::new(1, 2).as_uvec2());
+        assert_eq!(I64Vec2::new(1, 2), U64Vec2::new(1, 2).as_i64vec2());
     });
 
     impl_vec2_float_tests!(f32, vec2, Vec2, Vec3, BVec2);
 }
 
 mod dvec2 {
-    use glam::{dvec2, BVec2, DVec2, DVec3};
+    use glam::{dvec2, BVec2, DVec2, DVec3, IVec2, UVec2, Vec2};
 
     glam_test!(test_align, {
         use core::mem;
@@ -998,11 +1152,253 @@
         assert_eq!(1, mem::align_of::<BVec2>());
     });
 
+    glam_test!(test_try_from, {
+        assert_eq!(DVec2::new(1.0, 2.0), DVec2::from(Vec2::new(1.0, 2.0)));
+        assert_eq!(DVec2::new(1.0, 2.0), DVec2::from(IVec2::new(1, 2)));
+        assert_eq!(DVec2::new(1.0, 2.0), DVec2::from(UVec2::new(1, 2)));
+    });
+
     impl_vec2_float_tests!(f64, dvec2, DVec2, DVec3, BVec2);
 }
 
+mod i16vec2 {
+    use glam::{i16vec2, BVec2, I16Vec2, I16Vec3, I64Vec2, IVec2, U16Vec2, U64Vec2, UVec2};
+
+    glam_test!(test_align, {
+        use core::mem;
+        assert_eq!(4, mem::size_of::<I16Vec2>());
+        #[cfg(not(feature = "cuda"))]
+        assert_eq!(2, mem::align_of::<I16Vec2>());
+        #[cfg(feature = "cuda")]
+        assert_eq!(4, mem::align_of::<I16Vec2>());
+    });
+
+    glam_test!(test_try_from, {
+        assert_eq!(
+            I16Vec2::new(1, 2),
+            I16Vec2::try_from(U16Vec2::new(1, 2)).unwrap()
+        );
+        assert!(I16Vec2::try_from(U16Vec2::new(u16::MAX, 2)).is_err());
+        assert!(I16Vec2::try_from(U16Vec2::new(1, u16::MAX)).is_err());
+
+        assert_eq!(
+            I16Vec2::new(1, 2),
+            I16Vec2::try_from(IVec2::new(1, 2)).unwrap()
+        );
+        assert!(I16Vec2::try_from(IVec2::new(i32::MAX, 2)).is_err());
+        assert!(I16Vec2::try_from(IVec2::new(1, i32::MAX)).is_err());
+
+        assert_eq!(
+            I16Vec2::new(1, 2),
+            I16Vec2::try_from(UVec2::new(1, 2)).unwrap()
+        );
+        assert!(I16Vec2::try_from(UVec2::new(u32::MAX, 2)).is_err());
+        assert!(I16Vec2::try_from(UVec2::new(1, u32::MAX)).is_err());
+
+        assert_eq!(
+            I16Vec2::new(1, 2),
+            I16Vec2::try_from(I64Vec2::new(1, 2)).unwrap()
+        );
+        assert!(I16Vec2::try_from(I64Vec2::new(i64::MAX, 2)).is_err());
+        assert!(I16Vec2::try_from(I64Vec2::new(1, i64::MAX)).is_err());
+
+        assert_eq!(
+            I16Vec2::new(1, 2),
+            I16Vec2::try_from(U64Vec2::new(1, 2)).unwrap()
+        );
+        assert!(I16Vec2::try_from(U64Vec2::new(u64::MAX, 2)).is_err());
+        assert!(I16Vec2::try_from(U64Vec2::new(1, u64::MAX)).is_err());
+    });
+
+    glam_test!(test_wrapping_add, {
+        assert_eq!(
+            I16Vec2::new(i16::MAX, 5).wrapping_add(I16Vec2::new(1, 3)),
+            I16Vec2::new(i16::MIN, 8),
+        );
+    });
+
+    glam_test!(test_wrapping_sub, {
+        assert_eq!(
+            I16Vec2::new(i16::MAX, 5).wrapping_sub(I16Vec2::new(1, 3)),
+            I16Vec2::new(32766, 2)
+        );
+    });
+
+    glam_test!(test_wrapping_mul, {
+        assert_eq!(
+            I16Vec2::new(i16::MAX, 5).wrapping_mul(I16Vec2::new(3, 3)),
+            I16Vec2::new(32765, 15)
+        );
+    });
+
+    glam_test!(test_wrapping_div, {
+        assert_eq!(
+            I16Vec2::new(i16::MAX, 5).wrapping_div(I16Vec2::new(3, 3)),
+            I16Vec2::new(10922, 1)
+        );
+    });
+
+    glam_test!(test_saturating_add, {
+        assert_eq!(
+            I16Vec2::new(i16::MAX, i16::MIN,).saturating_add(I16Vec2::new(1, -1)),
+            I16Vec2::new(i16::MAX, i16::MIN)
+        );
+    });
+
+    glam_test!(test_saturating_sub, {
+        assert_eq!(
+            I16Vec2::new(i16::MIN, i16::MAX).saturating_sub(I16Vec2::new(1, -1)),
+            I16Vec2::new(i16::MIN, i16::MAX)
+        );
+    });
+
+    glam_test!(test_saturating_mul, {
+        assert_eq!(
+            I16Vec2::new(i16::MAX, i16::MIN).saturating_mul(I16Vec2::new(2, 2)),
+            I16Vec2::new(i16::MAX, i16::MIN)
+        );
+    });
+
+    glam_test!(test_saturating_div, {
+        assert_eq!(
+            I16Vec2::new(i16::MAX, i16::MIN).saturating_div(I16Vec2::new(2, 2)),
+            I16Vec2::new(16383, -16384)
+        );
+    });
+
+    impl_vec2_signed_integer_tests!(i16, i16vec2, I16Vec2, I16Vec3, BVec2);
+    impl_vec2_eq_hash_tests!(i16, i16vec2);
+
+    impl_vec2_scalar_shift_op_tests!(I16Vec2, -2, 2);
+    impl_vec2_shift_op_tests!(I16Vec2);
+
+    impl_vec2_scalar_bit_op_tests!(I16Vec2, -2, 2);
+    impl_vec2_bit_op_tests!(I16Vec2, -2, 2);
+}
+
+mod u16vec2 {
+    use glam::{u16vec2, BVec2, I16Vec2, I64Vec2, IVec2, U16Vec2, U16Vec3, U64Vec2, UVec2};
+
+    glam_test!(test_align, {
+        use core::mem;
+        assert_eq!(4, mem::size_of::<U16Vec2>());
+        #[cfg(not(feature = "cuda"))]
+        assert_eq!(2, mem::align_of::<U16Vec2>());
+        #[cfg(feature = "cuda")]
+        assert_eq!(4, mem::align_of::<U16Vec2>());
+    });
+
+    glam_test!(test_try_from, {
+        assert_eq!(
+            U16Vec2::new(1, 2),
+            U16Vec2::try_from(I16Vec2::new(1, 2)).unwrap()
+        );
+        assert!(U16Vec2::try_from(I16Vec2::new(-1, 2)).is_err());
+        assert!(U16Vec2::try_from(I16Vec2::new(1, -2)).is_err());
+
+        assert_eq!(
+            U16Vec2::new(1, 2),
+            U16Vec2::try_from(IVec2::new(1, 2)).unwrap()
+        );
+        assert!(U16Vec2::try_from(IVec2::new(-1, 2)).is_err());
+        assert!(U16Vec2::try_from(IVec2::new(1, -2)).is_err());
+
+        assert!(U16Vec2::try_from(IVec2::new(i32::MAX, 2)).is_err());
+        assert!(U16Vec2::try_from(IVec2::new(1, i32::MAX)).is_err());
+
+        assert_eq!(
+            U16Vec2::new(1, 2),
+            U16Vec2::try_from(UVec2::new(1, 2)).unwrap()
+        );
+        assert!(U16Vec2::try_from(UVec2::new(u32::MAX, 2)).is_err());
+        assert!(U16Vec2::try_from(UVec2::new(1, u32::MAX)).is_err());
+
+        assert_eq!(
+            U16Vec2::new(1, 2),
+            U16Vec2::try_from(I64Vec2::new(1, 2)).unwrap()
+        );
+        assert!(U16Vec2::try_from(I64Vec2::new(-1, 2)).is_err());
+        assert!(U16Vec2::try_from(I64Vec2::new(1, -2)).is_err());
+
+        assert!(U16Vec2::try_from(I64Vec2::new(i64::MAX, 2)).is_err());
+        assert!(U16Vec2::try_from(I64Vec2::new(1, i64::MAX)).is_err());
+
+        assert_eq!(
+            U16Vec2::new(1, 2),
+            U16Vec2::try_from(U64Vec2::new(1, 2)).unwrap()
+        );
+        assert!(U16Vec2::try_from(U64Vec2::new(u64::MAX, 2)).is_err());
+        assert!(U16Vec2::try_from(U64Vec2::new(1, u64::MAX)).is_err());
+    });
+
+    glam_test!(test_wrapping_add, {
+        assert_eq!(
+            U16Vec2::new(u16::MAX, 5).wrapping_add(U16Vec2::new(1, 3)),
+            U16Vec2::new(0, 8),
+        );
+    });
+
+    glam_test!(test_wrapping_sub, {
+        assert_eq!(
+            U16Vec2::new(u16::MAX, 5).wrapping_sub(U16Vec2::new(1, 3)),
+            U16Vec2::new(65534, 2)
+        );
+    });
+
+    glam_test!(test_wrapping_mul, {
+        assert_eq!(
+            U16Vec2::new(u16::MAX, 5).wrapping_mul(U16Vec2::new(3, 3)),
+            U16Vec2::new(65533, 15)
+        );
+    });
+
+    glam_test!(test_wrapping_div, {
+        assert_eq!(
+            U16Vec2::new(u16::MAX, 5).wrapping_div(U16Vec2::new(3, 3)),
+            U16Vec2::new(21845, 1)
+        );
+    });
+
+    glam_test!(test_saturating_add, {
+        assert_eq!(
+            U16Vec2::new(u16::MAX, u16::MAX).saturating_add(U16Vec2::new(1, u16::MAX)),
+            U16Vec2::new(u16::MAX, u16::MAX)
+        );
+    });
+
+    glam_test!(test_saturating_sub, {
+        assert_eq!(
+            U16Vec2::new(0, u16::MAX).saturating_sub(U16Vec2::new(1, 1)),
+            U16Vec2::new(0, 65534)
+        );
+    });
+
+    glam_test!(test_saturating_mul, {
+        assert_eq!(
+            U16Vec2::new(u16::MAX, u16::MAX).saturating_mul(U16Vec2::new(2, u16::MAX)),
+            U16Vec2::new(u16::MAX, u16::MAX)
+        );
+    });
+
+    glam_test!(test_saturating_div, {
+        assert_eq!(
+            U16Vec2::new(u16::MAX, u16::MAX).saturating_div(U16Vec2::new(2, u16::MAX)),
+            U16Vec2::new(32767, 1)
+        );
+    });
+
+    impl_vec2_tests!(u16, u16vec2, U16Vec2, U16Vec3, BVec2);
+    impl_vec2_eq_hash_tests!(u16, u16vec2);
+
+    impl_vec2_scalar_shift_op_tests!(U16Vec2, 0, 2);
+    impl_vec2_shift_op_tests!(U16Vec2);
+
+    impl_vec2_scalar_bit_op_tests!(U16Vec2, 0, 2);
+    impl_vec2_bit_op_tests!(U16Vec2, 0, 2);
+}
+
 mod ivec2 {
-    use glam::{ivec2, BVec2, IVec2, IVec3, UVec2};
+    use glam::{ivec2, BVec2, I16Vec2, I64Vec2, IVec2, IVec3, U16Vec2, U64Vec2, UVec2};
 
     glam_test!(test_align, {
         use core::mem;
@@ -1015,7 +1411,86 @@
         assert_eq!(1, mem::align_of::<BVec2>());
     });
 
-    impl_vec2_signed_tests!(i32, ivec2, IVec2, IVec3, BVec2);
+    glam_test!(test_try_from, {
+        assert_eq!(IVec2::new(1, 2), IVec2::from(U16Vec2::new(1, 2)));
+        assert_eq!(IVec2::new(1, 2), IVec2::from(I16Vec2::new(1, 2)));
+
+        assert_eq!(IVec2::new(1, 2), IVec2::try_from(UVec2::new(1, 2)).unwrap());
+        assert!(IVec2::try_from(UVec2::new(u32::MAX, 2)).is_err());
+        assert!(IVec2::try_from(UVec2::new(1, u32::MAX)).is_err());
+
+        assert_eq!(
+            IVec2::new(1, 2),
+            IVec2::try_from(I64Vec2::new(1, 2)).unwrap()
+        );
+        assert!(IVec2::try_from(I64Vec2::new(i64::MAX, 2)).is_err());
+        assert!(IVec2::try_from(I64Vec2::new(1, i64::MAX)).is_err());
+
+        assert_eq!(
+            IVec2::new(1, 2),
+            IVec2::try_from(U64Vec2::new(1, 2)).unwrap()
+        );
+        assert!(IVec2::try_from(U64Vec2::new(u64::MAX, 2)).is_err());
+        assert!(IVec2::try_from(U64Vec2::new(1, u64::MAX)).is_err());
+    });
+
+    glam_test!(test_wrapping_add, {
+        assert_eq!(
+            IVec2::new(i32::MAX, 5).wrapping_add(IVec2::new(1, 3)),
+            IVec2::new(i32::MIN, 8),
+        );
+    });
+
+    glam_test!(test_wrapping_sub, {
+        assert_eq!(
+            IVec2::new(i32::MAX, 5).wrapping_sub(IVec2::new(1, 3)),
+            IVec2::new(2147483646, 2)
+        );
+    });
+
+    glam_test!(test_wrapping_mul, {
+        assert_eq!(
+            IVec2::new(i32::MAX, 5).wrapping_mul(IVec2::new(3, 3)),
+            IVec2::new(2147483645, 15)
+        );
+    });
+
+    glam_test!(test_wrapping_div, {
+        assert_eq!(
+            IVec2::new(i32::MAX, 5).wrapping_div(IVec2::new(3, 3)),
+            IVec2::new(715827882, 1)
+        );
+    });
+
+    glam_test!(test_saturating_add, {
+        assert_eq!(
+            IVec2::new(i32::MAX, i32::MIN,).saturating_add(IVec2::new(1, -1)),
+            IVec2::new(i32::MAX, i32::MIN)
+        );
+    });
+
+    glam_test!(test_saturating_sub, {
+        assert_eq!(
+            IVec2::new(i32::MIN, i32::MAX).saturating_sub(IVec2::new(1, -1)),
+            IVec2::new(i32::MIN, i32::MAX)
+        );
+    });
+
+    glam_test!(test_saturating_mul, {
+        assert_eq!(
+            IVec2::new(i32::MAX, i32::MIN).saturating_mul(IVec2::new(2, 2)),
+            IVec2::new(i32::MAX, i32::MIN)
+        );
+    });
+
+    glam_test!(test_saturating_div, {
+        assert_eq!(
+            IVec2::new(i32::MAX, i32::MIN).saturating_div(IVec2::new(2, 2)),
+            IVec2::new(1073741823, -1073741824)
+        );
+    });
+
+    impl_vec2_signed_integer_tests!(i32, ivec2, IVec2, IVec3, BVec2);
     impl_vec2_eq_hash_tests!(i32, ivec2);
 
     impl_vec2_scalar_shift_op_tests!(IVec2, -2, 2);
@@ -1026,7 +1501,7 @@
 }
 
 mod uvec2 {
-    use glam::{uvec2, BVec2, IVec2, UVec2, UVec3};
+    use glam::{uvec2, BVec2, I16Vec2, I64Vec2, IVec2, U16Vec2, U64Vec2, UVec2, UVec3};
 
     glam_test!(test_align, {
         use core::mem;
@@ -1039,6 +1514,94 @@
         assert_eq!(1, mem::align_of::<BVec2>());
     });
 
+    glam_test!(test_try_from, {
+        assert_eq!(
+            UVec2::new(1, 2),
+            UVec2::try_from(I16Vec2::new(1, 2)).unwrap()
+        );
+        assert!(UVec2::try_from(I16Vec2::new(-1, 2)).is_err());
+        assert!(UVec2::try_from(I16Vec2::new(1, -2)).is_err());
+
+        assert_eq!(UVec2::new(1, 2), UVec2::from(U16Vec2::new(1, 2)));
+
+        assert_eq!(UVec2::new(1, 2), UVec2::try_from(IVec2::new(1, 2)).unwrap());
+        assert!(UVec2::try_from(IVec2::new(-1, 2)).is_err());
+        assert!(UVec2::try_from(IVec2::new(1, -2)).is_err());
+
+        assert_eq!(
+            UVec2::new(1, 2),
+            UVec2::try_from(I64Vec2::new(1, 2)).unwrap()
+        );
+        assert!(UVec2::try_from(I64Vec2::new(-1, 2)).is_err());
+        assert!(UVec2::try_from(I64Vec2::new(1, -2)).is_err());
+
+        assert!(UVec2::try_from(I64Vec2::new(i64::MAX, 2)).is_err());
+        assert!(UVec2::try_from(I64Vec2::new(1, i64::MAX)).is_err());
+
+        assert_eq!(
+            UVec2::new(1, 2),
+            UVec2::try_from(U64Vec2::new(1, 2)).unwrap()
+        );
+        assert!(UVec2::try_from(U64Vec2::new(u64::MAX, 2)).is_err());
+        assert!(UVec2::try_from(U64Vec2::new(1, u64::MAX)).is_err());
+    });
+
+    glam_test!(test_wrapping_add, {
+        assert_eq!(
+            UVec2::new(u32::MAX, 5).wrapping_add(UVec2::new(1, 3)),
+            UVec2::new(0, 8),
+        );
+    });
+
+    glam_test!(test_wrapping_sub, {
+        assert_eq!(
+            UVec2::new(u32::MAX, 5).wrapping_sub(UVec2::new(1, 3)),
+            UVec2::new(4294967294, 2)
+        );
+    });
+
+    glam_test!(test_wrapping_mul, {
+        assert_eq!(
+            UVec2::new(u32::MAX, 5).wrapping_mul(UVec2::new(3, 3)),
+            UVec2::new(4294967293, 15)
+        );
+    });
+
+    glam_test!(test_wrapping_div, {
+        assert_eq!(
+            UVec2::new(u32::MAX, 5).wrapping_div(UVec2::new(3, 3)),
+            UVec2::new(1431655765, 1)
+        );
+    });
+
+    glam_test!(test_saturating_add, {
+        assert_eq!(
+            UVec2::new(u32::MAX, u32::MAX).saturating_add(UVec2::new(1, u32::MAX)),
+            UVec2::new(u32::MAX, u32::MAX)
+        );
+    });
+
+    glam_test!(test_saturating_sub, {
+        assert_eq!(
+            UVec2::new(0, u32::MAX).saturating_sub(UVec2::new(1, 1)),
+            UVec2::new(0, 4294967294)
+        );
+    });
+
+    glam_test!(test_saturating_mul, {
+        assert_eq!(
+            UVec2::new(u32::MAX, u32::MAX).saturating_mul(UVec2::new(2, u32::MAX)),
+            UVec2::new(u32::MAX, u32::MAX)
+        );
+    });
+
+    glam_test!(test_saturating_div, {
+        assert_eq!(
+            UVec2::new(u32::MAX, u32::MAX).saturating_div(UVec2::new(2, u32::MAX)),
+            UVec2::new(2147483647, 1)
+        );
+    });
+
     impl_vec2_tests!(u32, uvec2, UVec2, UVec3, BVec2);
     impl_vec2_eq_hash_tests!(u32, uvec2);
 
@@ -1048,3 +1611,92 @@
     impl_vec2_scalar_bit_op_tests!(UVec2, 0, 2);
     impl_vec2_bit_op_tests!(UVec2, 0, 2);
 }
+
+mod i64vec2 {
+    use glam::{i64vec2, BVec2, I16Vec2, I64Vec2, I64Vec3, IVec2, U16Vec2, U64Vec2, UVec2};
+
+    glam_test!(test_align, {
+        use core::mem;
+        assert_eq!(16, mem::size_of::<I64Vec2>());
+        #[cfg(not(feature = "cuda"))]
+        assert_eq!(8, mem::align_of::<I64Vec2>());
+        #[cfg(feature = "cuda")]
+        assert_eq!(16, mem::align_of::<I64Vec2>());
+        assert_eq!(2, mem::size_of::<BVec2>());
+        assert_eq!(1, mem::align_of::<BVec2>());
+    });
+
+    glam_test!(test_try_from, {
+        assert_eq!(I64Vec2::new(1, 2), I64Vec2::from(I16Vec2::new(1, 2)));
+        assert_eq!(I64Vec2::new(1, 2), I64Vec2::from(U16Vec2::new(1, 2)));
+        assert_eq!(I64Vec2::new(1, 2), I64Vec2::from(IVec2::new(1, 2)));
+        assert_eq!(I64Vec2::new(1, 2), I64Vec2::from(UVec2::new(1, 2)));
+
+        assert_eq!(
+            I64Vec2::new(1, 2),
+            I64Vec2::try_from(U64Vec2::new(1, 2)).unwrap()
+        );
+        assert!(I64Vec2::try_from(U64Vec2::new(u64::MAX, 2)).is_err());
+        assert!(I64Vec2::try_from(U64Vec2::new(1, u64::MAX)).is_err());
+    });
+
+    impl_vec2_signed_integer_tests!(i64, i64vec2, I64Vec2, I64Vec3, BVec2);
+    impl_vec2_eq_hash_tests!(i64, i64vec2);
+
+    impl_vec2_scalar_shift_op_tests!(I64Vec2, -2, 2);
+    impl_vec2_shift_op_tests!(I64Vec2);
+
+    impl_vec2_scalar_bit_op_tests!(I64Vec2, -2, 2);
+    impl_vec2_bit_op_tests!(I64Vec2, -2, 2);
+}
+
+mod u64vec2 {
+    use glam::{u64vec2, BVec2, I16Vec2, I64Vec2, IVec2, U16Vec2, U64Vec2, U64Vec3, UVec2};
+
+    glam_test!(test_align, {
+        use core::mem;
+        assert_eq!(16, mem::size_of::<U64Vec2>());
+        #[cfg(not(feature = "cuda"))]
+        assert_eq!(8, mem::align_of::<U64Vec2>());
+        #[cfg(feature = "cuda")]
+        assert_eq!(16, mem::align_of::<U64Vec2>());
+        assert_eq!(2, mem::size_of::<BVec2>());
+        assert_eq!(1, mem::align_of::<BVec2>());
+    });
+
+    glam_test!(test_try_from, {
+        assert_eq!(
+            U64Vec2::new(1, 2),
+            U64Vec2::try_from(I16Vec2::new(1, 2)).unwrap()
+        );
+        assert!(U64Vec2::try_from(I16Vec2::new(-1, 2)).is_err());
+        assert!(U64Vec2::try_from(I16Vec2::new(1, -2)).is_err());
+
+        assert_eq!(U64Vec2::new(1, 2), U64Vec2::from(U16Vec2::new(1, 2)));
+
+        assert_eq!(
+            U64Vec2::new(1, 2),
+            U64Vec2::try_from(IVec2::new(1, 2)).unwrap()
+        );
+        assert!(U64Vec2::try_from(IVec2::new(-1, 2)).is_err());
+        assert!(U64Vec2::try_from(IVec2::new(1, -2)).is_err());
+
+        assert_eq!(U64Vec2::new(1, 2), U64Vec2::from(UVec2::new(1, 2)));
+
+        assert_eq!(
+            U64Vec2::new(1, 2),
+            U64Vec2::try_from(I64Vec2::new(1, 2)).unwrap()
+        );
+        assert!(U64Vec2::try_from(I64Vec2::new(-1, 2)).is_err());
+        assert!(U64Vec2::try_from(I64Vec2::new(1, -2)).is_err());
+    });
+
+    impl_vec2_tests!(u64, u64vec2, U64Vec2, U64Vec3, BVec2);
+    impl_vec2_eq_hash_tests!(u64, u64vec2);
+
+    impl_vec2_scalar_shift_op_tests!(U64Vec2, 0, 2);
+    impl_vec2_shift_op_tests!(U64Vec2);
+
+    impl_vec2_scalar_bit_op_tests!(U64Vec2, 0, 2);
+    impl_vec2_bit_op_tests!(U64Vec2, 0, 2);
+}
diff --git a/tests/vec3.rs b/tests/vec3.rs
index 5df8d09..0997826 100644
--- a/tests/vec3.rs
+++ b/tests/vec3.rs
@@ -20,6 +20,8 @@
             assert_eq!($vec3::X, $new(1 as $t, 0 as $t, 0 as $t));
             assert_eq!($vec3::Y, $new(0 as $t, 1 as $t, 0 as $t));
             assert_eq!($vec3::Z, $new(0 as $t, 0 as $t, 1 as $t));
+            assert_eq!($vec3::MIN, $new($t::MIN, $t::MIN, $t::MIN));
+            assert_eq!($vec3::MAX, $new($t::MAX, $t::MAX, $t::MAX));
         });
 
         glam_test!(test_new, {
@@ -108,6 +110,18 @@
             let y = $new(0 as $t, 1 as $t, 0 as $t);
             assert_eq!(1 as $t, x.dot(x));
             assert_eq!(0 as $t, x.dot(y));
+
+            assert_eq!(
+                $new(14 as $t, 14 as $t, 14 as $t),
+                $new(0 as $t, 4 as $t, 6 as $t).dot_into_vec($new(3 as $t, 2 as $t, 1 as $t))
+            );
+        });
+
+        glam_test!(test_length_squared_unsigned, {
+            let x = $new(1 as $t, 0 as $t, 0 as $t);
+            let z = $new(0 as $t, 0 as $t, 1 as $t);
+            assert_eq!(4 as $t, (2 as $t * x).length_squared());
+            assert_eq!(16 as $t, (4 as $t * z).length_squared());
         });
 
         glam_test!(test_cross, {
@@ -462,6 +476,36 @@
             assert_ne!(b, c);
         });
 
+        glam_test!(test_mask_test, {
+            let a = $mask::new(true, false, true);
+            assert_eq!(a.test(0), true);
+            assert_eq!(a.test(1), false);
+            assert_eq!(a.test(2), true);
+
+            let b = $mask::new(false, true, false);
+            assert_eq!(b.test(0), false);
+            assert_eq!(b.test(1), true);
+            assert_eq!(b.test(2), false);
+        });
+
+        glam_test!(test_mask_set, {
+            let mut a = $mask::new(false, true, false);
+            a.set(0, true);
+            assert_eq!(a.test(0), true);
+            a.set(1, false);
+            assert_eq!(a.test(1), false);
+            a.set(2, true);
+            assert_eq!(a.test(2), true);
+
+            let mut b = $mask::new(true, false, true);
+            b.set(0, false);
+            assert_eq!(b.test(0), false);
+            b.set(1, true);
+            assert_eq!(b.test(1), true);
+            b.set(2, false);
+            assert_eq!(b.test(2), false);
+        });
+
         glam_test!(test_mask_hash, {
             use std::collections::hash_map::DefaultHasher;
             use std::hash::Hash;
@@ -501,14 +545,14 @@
 
         glam_test!(test_sum, {
             let one = $vec3::ONE;
-            assert_eq!(vec![one, one].iter().sum::<$vec3>(), one + one);
-            assert_eq!(vec![one, one].into_iter().sum::<$vec3>(), one + one);
+            assert_eq!([one, one].iter().sum::<$vec3>(), one + one);
+            assert_eq!([one, one].into_iter().sum::<$vec3>(), one + one);
         });
 
         glam_test!(test_product, {
             let two = $vec3::new(2 as $t, 2 as $t, 2 as $t);
-            assert_eq!(vec![two, two].iter().product::<$vec3>(), two * two);
-            assert_eq!(vec![two, two].into_iter().product::<$vec3>(), two * two);
+            assert_eq!([two, two].iter().product::<$vec3>(), two * two);
+            assert_eq!([two, two].into_iter().product::<$vec3>(), two * two);
         });
     };
 }
@@ -530,6 +574,38 @@
             );
         });
 
+        glam_test!(test_is_negative_bitmask, {
+            assert_eq!($vec3::ZERO.is_negative_bitmask(), 0b000);
+            assert_eq!($vec3::ONE.is_negative_bitmask(), 0b000);
+            assert_eq!((-$vec3::ONE).is_negative_bitmask(), 0b111);
+            assert_eq!(
+                $vec3::new(-1 as $t, 2 as $t, 3 as $t).is_negative_bitmask(),
+                0b001
+            );
+            assert_eq!(
+                $vec3::new(8 as $t, 3 as $t, 1 as $t).is_negative_bitmask(),
+                0b000
+            );
+            assert_eq!(
+                $vec3::new(1 as $t, 5 as $t, -3 as $t).is_negative_bitmask(),
+                0b100
+            );
+            assert_eq!(
+                $vec3::new(3 as $t, -4 as $t, 1 as $t).is_negative_bitmask(),
+                0b010
+            );
+            assert_eq!(
+                $vec3::new(-2 as $t, 6 as $t, -5 as $t).is_negative_bitmask(),
+                0b101
+            );
+        });
+
+        glam_test!(test_abs, {
+            assert_eq!($vec3::ZERO.abs(), $vec3::ZERO);
+            assert_eq!($vec3::ONE.abs(), $vec3::ONE);
+            assert_eq!((-$vec3::ONE).abs(), $vec3::ONE);
+        });
+
         glam_test!(test_dot_signed, {
             let x = $new(1 as $t, 0 as $t, 0 as $t);
             let y = $new(0 as $t, 1 as $t, 0 as $t);
@@ -538,6 +614,52 @@
             assert_eq!(0 as $t, x.dot(y));
             assert_eq!(-1 as $t, z.dot(-z));
         });
+
+        glam_test!(test_length_squared_signed, {
+            let x = $new(1 as $t, 0 as $t, 0 as $t);
+            let y = $new(0 as $t, 1 as $t, 0 as $t);
+            let z = $new(0 as $t, 0 as $t, 1 as $t);
+            assert_eq!(9 as $t, (-3 as $t * y).length_squared());
+            assert_eq!(
+                2 as $t * 2 as $t + 3 as $t * 3 as $t + 4 as $t * 4 as $t,
+                $new(2 as $t, 3 as $t, 4 as $t).length_squared()
+            );
+            assert_eq!(2 as $t, x.distance_squared(y));
+            assert_eq!(13 as $t, (2 as $t * x).distance_squared(-3 as $t * z));
+        });
+
+        glam_test!(test_div_euclid, {
+            let one = $vec3::ONE;
+            let two = one + one;
+            let three = two + one;
+            assert_eq!(three.div_euclid(two), one);
+            assert_eq!((-three).div_euclid(two), -two);
+            assert_eq!(three.div_euclid(-two), -one);
+            assert_eq!((-three).div_euclid(-two), two);
+        });
+
+        glam_test!(test_rem_euclid, {
+            let one = $vec3::ONE;
+            let two = one + one;
+            let three = two + one;
+            let four = three + one;
+            assert_eq!(four.rem_euclid(three), one);
+            assert_eq!((-four).rem_euclid(three), two);
+            assert_eq!(four.rem_euclid(-three), one);
+            assert_eq!((-four).rem_euclid(-three), two);
+        });
+    };
+}
+
+macro_rules! impl_vec3_signed_integer_tests {
+    ($t:ident, $new:ident, $vec3:ident, $mask:ident) => {
+        impl_vec3_signed_tests!($t, $new, $vec3, $mask);
+
+        glam_test!(test_signum, {
+            assert_eq!($vec3::ZERO.signum(), $vec3::ZERO);
+            assert_eq!($vec3::ONE.signum(), $vec3::ONE);
+            assert_eq!((-$vec3::ONE).signum(), -$vec3::ONE);
+        });
     };
 }
 
@@ -592,14 +714,9 @@
             let z = $new(0.0, 0.0, 1.0);
             assert_eq!(y, z.cross(x));
             assert_eq!(z, x.cross(y));
-            assert_eq!(4.0, (2.0 * x).length_squared());
-            assert_eq!(9.0, (-3.0 * y).length_squared());
-            assert_eq!(16.0, (4.0 * z).length_squared());
             assert_eq!(2.0, (-2.0 * x).length());
             assert_eq!(3.0, (3.0 * y).length());
             assert_eq!(4.0, (-4.0 * z).length());
-            assert_eq!(2.0, x.distance_squared(y));
-            assert_eq!(13.0, (2.0 * x).distance_squared(-3.0 * z));
             assert_eq!((2.0 as $t).sqrt(), x.distance(y));
             assert_eq!(5.0, (3.0 * x).distance(-4.0 * y));
             assert_eq!(13.0, (-5.0 * z).distance(12.0 * y));
@@ -609,14 +726,6 @@
                 $new(1.0, 2.0, 3.0).dot($new(4.0, 5.0, 6.0))
             );
             assert_eq!(
-                $new(14.0, 14.0, 14.0),
-                $new(0.0, 4.0, 6.0).dot_into_vec($new(3.0, 2.0, 1.0))
-            );
-            assert_eq!(
-                2.0 * 2.0 + 3.0 * 3.0 + 4.0 * 4.0,
-                $new(2.0, 3.0, 4.0).length_squared()
-            );
-            assert_eq!(
                 (2.0 as $t * 2.0 + 3.0 * 3.0 + 4.0 * 4.0).sqrt(),
                 $new(2.0, 3.0, 4.0).length()
             );
@@ -660,9 +769,9 @@
             assert_eq!((-$vec3::ZERO).signum(), -$vec3::ONE);
             assert_eq!($vec3::ONE.signum(), $vec3::ONE);
             assert_eq!((-$vec3::ONE).signum(), -$vec3::ONE);
-            assert_eq!($vec3::splat(INFINITY).signum(), $vec3::ONE);
-            assert_eq!($vec3::splat(NEG_INFINITY).signum(), -$vec3::ONE);
-            assert!($vec3::splat(NAN).signum().is_nan_mask().all());
+            assert_eq!($vec3::INFINITY.signum(), $vec3::ONE);
+            assert_eq!($vec3::NEG_INFINITY.signum(), -$vec3::ONE);
+            assert!($vec3::NAN.signum().is_nan_mask().all());
         });
 
         glam_test!(test_copysign, {
@@ -682,42 +791,27 @@
             assert_eq!((-$vec3::ONE).copysign(-$vec3::ONE), -$vec3::ONE);
             assert_eq!($vec3::ONE.copysign($vec3::ONE), $vec3::ONE);
             assert_eq!((-$vec3::ONE).copysign($vec3::ONE), $vec3::ONE);
+            assert_eq!($vec3::INFINITY.copysign($vec3::ONE), $vec3::INFINITY);
+            assert_eq!($vec3::INFINITY.copysign(-$vec3::ONE), $vec3::NEG_INFINITY);
+            assert_eq!($vec3::NEG_INFINITY.copysign($vec3::ONE), $vec3::INFINITY);
             assert_eq!(
-                $vec3::splat(INFINITY).copysign($vec3::ONE),
-                $vec3::splat(INFINITY)
+                $vec3::NEG_INFINITY.copysign(-$vec3::ONE),
+                $vec3::NEG_INFINITY
             );
-            assert_eq!(
-                $vec3::splat(INFINITY).copysign(-$vec3::ONE),
-                $vec3::splat(NEG_INFINITY)
-            );
-            assert_eq!(
-                $vec3::splat(NEG_INFINITY).copysign($vec3::ONE),
-                $vec3::splat(INFINITY)
-            );
-            assert_eq!(
-                $vec3::splat(NEG_INFINITY).copysign(-$vec3::ONE),
-                $vec3::splat(NEG_INFINITY)
-            );
-            assert!($vec3::splat(NAN).copysign($vec3::ONE).is_nan_mask().all());
-            assert!($vec3::splat(NAN).copysign(-$vec3::ONE).is_nan_mask().all());
+            assert!($vec3::NAN.copysign($vec3::ONE).is_nan_mask().all());
+            assert!($vec3::NAN.copysign(-$vec3::ONE).is_nan_mask().all());
         });
 
-        glam_test!(test_is_negative_bitmask, {
+        glam_test!(test_float_is_negative_bitmask, {
             assert_eq!($vec3::ZERO.is_negative_bitmask(), 0b000);
             assert_eq!((-$vec3::ZERO).is_negative_bitmask(), 0b111);
             assert_eq!($vec3::ONE.is_negative_bitmask(), 0b000);
             assert_eq!((-$vec3::ONE).is_negative_bitmask(), 0b111);
-            assert_eq!($vec3::new(-0.1, 0.2, 0.3).is_negative_bitmask(), 0b001);
-            assert_eq!($vec3::new(0.8, 0.3, 0.1).is_negative_bitmask(), 0b000);
-            assert_eq!($vec3::new(0.1, 0.5, -0.3).is_negative_bitmask(), 0b100);
-            assert_eq!($vec3::new(0.3, -0.4, 0.1).is_negative_bitmask(), 0b010);
-            assert_eq!($vec3::new(-0.2, 0.6, -0.5).is_negative_bitmask(), 0b101);
-        });
-
-        glam_test!(test_abs, {
-            assert_eq!($vec3::ZERO.abs(), $vec3::ZERO);
-            assert_eq!($vec3::ONE.abs(), $vec3::ONE);
-            assert_eq!((-$vec3::ONE).abs(), $vec3::ONE);
+            assert_eq!($vec3::new(-1.0, 2.0, 3.0).is_negative_bitmask(), 0b001);
+            assert_eq!($vec3::new(8.0, 3.0, 1.0).is_negative_bitmask(), 0b000);
+            assert_eq!($vec3::new(1.0, 5.0, -3.0).is_negative_bitmask(), 0b100);
+            assert_eq!($vec3::new(3.0, -4.0, 1.0).is_negative_bitmask(), 0b010);
+            assert_eq!($vec3::new(-2.0, 6.0, -5.0).is_negative_bitmask(), 0b101);
         });
 
         glam_test!(test_round, {
@@ -779,6 +873,22 @@
             );
         });
 
+        glam_test!(test_trunc, {
+            assert_eq!(
+                $vec3::new(1.35, 1.5, -1.5).trunc(),
+                $vec3::new(1.0, 1.0, -1.0)
+            );
+            assert_eq!(
+                $vec3::new(INFINITY, NEG_INFINITY, 0.0).trunc(),
+                $vec3::new(INFINITY, NEG_INFINITY, 0.0)
+            );
+            assert!($vec3::new(0.0, NAN, 0.0).trunc().y.is_nan());
+            assert_eq!(
+                $vec3::new(-0.0, -2000000.123, 10000000.123).trunc(),
+                $vec3::new(-0.0, -2000000.0, 10000000.0)
+            );
+        });
+
         glam_test!(test_lerp, {
             let v0 = $vec3::new(-1.0, -1.0, -1.0);
             let v1 = $vec3::new(1.0, 1.0, 1.0);
@@ -793,7 +903,9 @@
             assert!(!$vec3::new(INFINITY, 0.0, 0.0).is_finite());
             assert!(!$vec3::new(0.0, NAN, 0.0).is_finite());
             assert!(!$vec3::new(0.0, 0.0, NEG_INFINITY).is_finite());
-            assert!(!$vec3::splat(NAN).is_finite());
+            assert!(!$vec3::NAN.is_finite());
+            assert!(!$vec3::INFINITY.is_finite());
+            assert!(!$vec3::NEG_INFINITY.is_finite());
         });
 
         glam_test!(test_powf, {
@@ -933,6 +1045,10 @@
             use glam::$vec3;
             impl_vec3_scalar_shift_op_test!($vec3, $t_min, $t_max, 0i32, 2);
         }
+        mod shift_by_i64 {
+            use glam::$vec3;
+            impl_vec3_scalar_shift_op_test!($vec3, $t_min, $t_max, 0i64, 2);
+        }
         mod shift_by_u8 {
             use glam::$vec3;
             impl_vec3_scalar_shift_op_test!($vec3, $t_min, $t_max, 0u8, 2);
@@ -945,6 +1061,10 @@
             use glam::$vec3;
             impl_vec3_scalar_shift_op_test!($vec3, $t_min, $t_max, 0u32, 2);
         }
+        mod shift_by_u64 {
+            use glam::$vec3;
+            impl_vec3_scalar_shift_op_test!($vec3, $t_min, $t_max, 0u64, 2);
+        }
     };
 }
 
@@ -1060,33 +1180,75 @@
     });
 
     glam_test!(test_as, {
-        use glam::{DVec3, IVec3, UVec3, Vec3A};
+        use glam::{DVec3, I16Vec3, I64Vec3, IVec3, U16Vec3, U64Vec3, UVec3, Vec3A};
         assert_eq!(
             DVec3::new(-1.0, -2.0, -3.0),
             Vec3::new(-1.0, -2.0, -3.0).as_dvec3()
         );
         assert_eq!(
+            I16Vec3::new(-1, -2, -3),
+            Vec3::new(-1.0, -2.0, -3.0).as_i16vec3()
+        );
+        assert_eq!(U16Vec3::new(1, 2, 3), Vec3::new(1.0, 2.0, 3.0).as_u16vec3());
+        assert_eq!(
             IVec3::new(-1, -2, -3),
             Vec3::new(-1.0, -2.0, -3.0).as_ivec3()
         );
         assert_eq!(UVec3::new(1, 2, 3), Vec3::new(1.0, 2.0, 3.0).as_uvec3());
+        assert_eq!(
+            I64Vec3::new(-1, -2, -3),
+            Vec3::new(-1.0, -2.0, -3.0).as_i64vec3()
+        );
+        assert_eq!(U64Vec3::new(1, 2, 3), Vec3::new(1.0, 2.0, 3.0).as_u64vec3());
 
         assert_eq!(
             DVec3::new(-1.0, -2.0, -3.0),
             Vec3A::new(-1.0, -2.0, -3.0).as_dvec3()
         );
         assert_eq!(
+            I16Vec3::new(-1, -2, -3),
+            Vec3A::new(-1.0, -2.0, -3.0).as_i16vec3()
+        );
+        assert_eq!(
+            U16Vec3::new(1, 2, 3),
+            Vec3A::new(1.0, 2.0, 3.0).as_u16vec3()
+        );
+        assert_eq!(
             IVec3::new(-1, -2, -3),
             Vec3A::new(-1.0, -2.0, -3.0).as_ivec3()
         );
         assert_eq!(UVec3::new(1, 2, 3), Vec3A::new(1.0, 2.0, 3.0).as_uvec3());
+        assert_eq!(
+            I64Vec3::new(-1, -2, -3),
+            Vec3A::new(-1.0, -2.0, -3.0).as_i64vec3()
+        );
+        assert_eq!(
+            U64Vec3::new(1, 2, 3),
+            Vec3A::new(1.0, 2.0, 3.0).as_u64vec3()
+        );
 
         assert_eq!(
+            I16Vec3::new(-1, -2, -3),
+            DVec3::new(-1.0, -2.0, -3.0).as_i16vec3()
+        );
+        assert_eq!(
+            U16Vec3::new(1, 2, 3),
+            DVec3::new(1.0, 2.0, 3.0).as_u16vec3()
+        );
+        assert_eq!(
             IVec3::new(-1, -2, -3),
             DVec3::new(-1.0, -2.0, -3.0).as_ivec3()
         );
         assert_eq!(UVec3::new(1, 2, 3), DVec3::new(1.0, 2.0, 3.0).as_uvec3());
         assert_eq!(
+            I64Vec3::new(-1, -2, -3),
+            DVec3::new(-1.0, -2.0, -3.0).as_i64vec3()
+        );
+        assert_eq!(
+            U64Vec3::new(1, 2, 3),
+            DVec3::new(1.0, 2.0, 3.0).as_u64vec3()
+        );
+        assert_eq!(
             Vec3::new(-1.0, -2.0, -3.0),
             DVec3::new(-1.0, -2.0, -3.0).as_vec3()
         );
@@ -1097,10 +1259,50 @@
 
         assert_eq!(
             DVec3::new(-1.0, -2.0, -3.0),
+            I16Vec3::new(-1, -2, -3).as_dvec3()
+        );
+        assert_eq!(U16Vec3::new(1, 2, 3), I16Vec3::new(1, 2, 3).as_u16vec3());
+        assert_eq!(IVec3::new(-1, -2, -3), I16Vec3::new(-1, -2, -3).as_ivec3());
+        assert_eq!(UVec3::new(1, 2, 3), I16Vec3::new(1, 2, 3).as_uvec3());
+        assert_eq!(
+            I64Vec3::new(-1, -2, -3),
+            I16Vec3::new(-1, -2, -3).as_i64vec3()
+        );
+        assert_eq!(U64Vec3::new(1, 2, 3), I16Vec3::new(1, 2, 3).as_u64vec3());
+        assert_eq!(
+            Vec3::new(-1.0, -2.0, -3.0),
+            I16Vec3::new(-1, -2, -3).as_vec3()
+        );
+        assert_eq!(
+            Vec3A::new(-1.0, -2.0, -3.0),
+            I16Vec3::new(-1, -2, -3).as_vec3a()
+        );
+
+        assert_eq!(DVec3::new(1.0, 2.0, 3.0), U16Vec3::new(1, 2, 3).as_dvec3());
+        assert_eq!(I16Vec3::new(1, 2, 3), U16Vec3::new(1, 2, 3).as_i16vec3());
+        assert_eq!(IVec3::new(1, 2, 3), U16Vec3::new(1, 2, 3).as_ivec3());
+        assert_eq!(UVec3::new(1, 2, 3), U16Vec3::new(1, 2, 3).as_uvec3());
+        assert_eq!(I64Vec3::new(1, 2, 3), U16Vec3::new(1, 2, 3).as_i64vec3());
+        assert_eq!(U64Vec3::new(1, 2, 3), U16Vec3::new(1, 2, 3).as_u64vec3());
+        assert_eq!(Vec3::new(1.0, 2.0, 3.0), U16Vec3::new(1, 2, 3).as_vec3());
+        assert_eq!(Vec3A::new(1.0, 2.0, 3.0), U16Vec3::new(1, 2, 3).as_vec3a());
+
+        assert_eq!(
+            DVec3::new(-1.0, -2.0, -3.0),
             IVec3::new(-1, -2, -3).as_dvec3()
         );
+        assert_eq!(
+            I16Vec3::new(-1, -2, -3),
+            IVec3::new(-1, -2, -3).as_i16vec3()
+        );
+        assert_eq!(U16Vec3::new(1, 2, 3), IVec3::new(1, 2, 3).as_u16vec3());
         assert_eq!(UVec3::new(1, 2, 3), IVec3::new(1, 2, 3).as_uvec3());
         assert_eq!(
+            I64Vec3::new(-1, -2, -3),
+            IVec3::new(-1, -2, -3).as_i64vec3()
+        );
+        assert_eq!(U64Vec3::new(1, 2, 3), IVec3::new(1, 2, 3).as_u64vec3());
+        assert_eq!(
             Vec3::new(-1.0, -2.0, -3.0),
             IVec3::new(-1, -2, -3).as_vec3()
         );
@@ -1110,9 +1312,43 @@
         );
 
         assert_eq!(DVec3::new(1.0, 2.0, 3.0), UVec3::new(1, 2, 3).as_dvec3());
+        assert_eq!(I16Vec3::new(1, 2, 3), UVec3::new(1, 2, 3).as_i16vec3());
+        assert_eq!(U16Vec3::new(1, 2, 3), UVec3::new(1, 2, 3).as_u16vec3());
         assert_eq!(IVec3::new(1, 2, 3), UVec3::new(1, 2, 3).as_ivec3());
+        assert_eq!(I64Vec3::new(1, 2, 3), UVec3::new(1, 2, 3).as_i64vec3());
+        assert_eq!(U64Vec3::new(1, 2, 3), UVec3::new(1, 2, 3).as_u64vec3());
         assert_eq!(Vec3::new(1.0, 2.0, 3.0), UVec3::new(1, 2, 3).as_vec3());
         assert_eq!(Vec3A::new(1.0, 2.0, 3.0), UVec3::new(1, 2, 3).as_vec3a());
+
+        assert_eq!(
+            DVec3::new(-1.0, -2.0, -3.0),
+            I64Vec3::new(-1, -2, -3).as_dvec3()
+        );
+        assert_eq!(U16Vec3::new(1, 2, 3), I64Vec3::new(1, 2, 3).as_u16vec3());
+        assert_eq!(
+            I16Vec3::new(-1, -2, -3),
+            I64Vec3::new(-1, -2, -3).as_i16vec3()
+        );
+        assert_eq!(UVec3::new(1, 2, 3), I64Vec3::new(1, 2, 3).as_uvec3());
+        assert_eq!(IVec3::new(-1, -2, -3), I64Vec3::new(-1, -2, -3).as_ivec3());
+        assert_eq!(U64Vec3::new(1, 2, 3), I64Vec3::new(1, 2, 3).as_u64vec3());
+        assert_eq!(
+            Vec3::new(-1.0, -2.0, -3.0),
+            I64Vec3::new(-1, -2, -3).as_vec3()
+        );
+        assert_eq!(
+            Vec3A::new(-1.0, -2.0, -3.0),
+            I64Vec3::new(-1, -2, -3).as_vec3a()
+        );
+
+        assert_eq!(DVec3::new(1.0, 2.0, 3.0), U64Vec3::new(1, 2, 3).as_dvec3());
+        assert_eq!(I16Vec3::new(1, 2, 3), U64Vec3::new(1, 2, 3).as_i16vec3());
+        assert_eq!(U16Vec3::new(1, 2, 3), U64Vec3::new(1, 2, 3).as_u16vec3());
+        assert_eq!(IVec3::new(1, 2, 3), U64Vec3::new(1, 2, 3).as_ivec3());
+        assert_eq!(UVec3::new(1, 2, 3), U64Vec3::new(1, 2, 3).as_uvec3());
+        assert_eq!(I64Vec3::new(1, 2, 3), U64Vec3::new(1, 2, 3).as_i64vec3());
+        assert_eq!(Vec3::new(1.0, 2.0, 3.0), U64Vec3::new(1, 2, 3).as_vec3());
+        assert_eq!(Vec3A::new(1.0, 2.0, 3.0), U64Vec3::new(1, 2, 3).as_vec3a());
     });
 
     impl_vec3_float_tests!(f32, vec3, Vec3, BVec3);
@@ -1189,7 +1425,7 @@
 }
 
 mod dvec3 {
-    use glam::{dvec3, BVec3, DVec3};
+    use glam::{dvec3, BVec3, DVec3, IVec3, UVec3, Vec3};
 
     glam_test!(test_align, {
         use std::mem;
@@ -1199,11 +1435,262 @@
         assert_eq!(1, mem::align_of::<BVec3>());
     });
 
+    glam_test!(test_try_from, {
+        assert_eq!(
+            DVec3::new(1.0, 2.0, 3.0),
+            DVec3::from(Vec3::new(1.0, 2.0, 3.0))
+        );
+        assert_eq!(DVec3::new(1.0, 2.0, 3.0), DVec3::from(IVec3::new(1, 2, 3)));
+        assert_eq!(DVec3::new(1.0, 2.0, 3.0), DVec3::from(UVec3::new(1, 2, 3)));
+    });
+
     impl_vec3_float_tests!(f64, dvec3, DVec3, BVec3);
 }
 
+mod i16vec3 {
+    use glam::{i16vec3, BVec3, I16Vec3, I64Vec3, IVec3, U16Vec3, U64Vec3, UVec3};
+
+    glam_test!(test_align, {
+        use std::mem;
+        assert_eq!(6, mem::size_of::<I16Vec3>());
+        assert_eq!(2, mem::align_of::<I16Vec3>());
+    });
+
+    glam_test!(test_try_from, {
+        assert_eq!(
+            I16Vec3::new(1, 2, 3),
+            I16Vec3::try_from(U16Vec3::new(1, 2, 3)).unwrap()
+        );
+        assert!(I16Vec3::try_from(U16Vec3::new(u16::MAX, 2, 3)).is_err());
+        assert!(I16Vec3::try_from(U16Vec3::new(1, u16::MAX, 3)).is_err());
+        assert!(I16Vec3::try_from(U16Vec3::new(1, 2, u16::MAX)).is_err());
+
+        assert_eq!(
+            I16Vec3::new(1, 2, 3),
+            I16Vec3::try_from(IVec3::new(1, 2, 3)).unwrap()
+        );
+        assert!(I16Vec3::try_from(IVec3::new(i32::MAX, 2, 3)).is_err());
+        assert!(I16Vec3::try_from(IVec3::new(1, i32::MAX, 3)).is_err());
+        assert!(I16Vec3::try_from(IVec3::new(1, 2, i32::MAX)).is_err());
+
+        assert_eq!(
+            I16Vec3::new(1, 2, 3),
+            I16Vec3::try_from(UVec3::new(1, 2, 3)).unwrap()
+        );
+        assert!(I16Vec3::try_from(UVec3::new(u32::MAX, 2, 3)).is_err());
+        assert!(I16Vec3::try_from(UVec3::new(1, u32::MAX, 3)).is_err());
+        assert!(I16Vec3::try_from(UVec3::new(1, 2, u32::MAX)).is_err());
+
+        assert_eq!(
+            I16Vec3::new(1, 2, 3),
+            I16Vec3::try_from(I64Vec3::new(1, 2, 3)).unwrap()
+        );
+        assert!(I16Vec3::try_from(I64Vec3::new(i64::MAX, 2, 3)).is_err());
+        assert!(I16Vec3::try_from(I64Vec3::new(1, i64::MAX, 3)).is_err());
+        assert!(I16Vec3::try_from(I64Vec3::new(1, 2, i64::MAX)).is_err());
+
+        assert_eq!(
+            I16Vec3::new(1, 2, 3),
+            I16Vec3::try_from(U64Vec3::new(1, 2, 3)).unwrap()
+        );
+        assert!(I16Vec3::try_from(U64Vec3::new(u64::MAX, 2, 3)).is_err());
+        assert!(I16Vec3::try_from(U64Vec3::new(1, u64::MAX, 3)).is_err());
+        assert!(I16Vec3::try_from(U64Vec3::new(1, 2, u64::MAX)).is_err());
+    });
+
+    glam_test!(test_wrapping_add, {
+        assert_eq!(
+            I16Vec3::new(i16::MAX, 5, i16::MIN).wrapping_add(I16Vec3::new(1, 3, i16::MAX)),
+            I16Vec3::new(i16::MIN, 8, -1),
+        );
+    });
+
+    glam_test!(test_wrapping_sub, {
+        assert_eq!(
+            I16Vec3::new(i16::MAX, 5, i16::MIN).wrapping_sub(I16Vec3::new(1, 3, i16::MAX)),
+            I16Vec3::new(32766, 2, 1),
+        );
+    });
+
+    glam_test!(test_wrapping_mul, {
+        assert_eq!(
+            I16Vec3::new(i16::MAX, 5, i16::MIN).wrapping_mul(I16Vec3::new(3, 3, 5)),
+            I16Vec3::new(32765, 15, -32768)
+        );
+    });
+
+    glam_test!(test_wrapping_div, {
+        assert_eq!(
+            I16Vec3::new(i16::MAX, 5, i16::MIN).wrapping_div(I16Vec3::new(3, 3, 5)),
+            I16Vec3::new(10922, 1, -6553)
+        );
+    });
+
+    glam_test!(test_saturating_add, {
+        assert_eq!(
+            I16Vec3::new(i16::MAX, i16::MIN, 0).saturating_add(I16Vec3::new(1, -1, 2)),
+            I16Vec3::new(i16::MAX, i16::MIN, 2)
+        );
+    });
+
+    glam_test!(test_saturating_sub, {
+        assert_eq!(
+            I16Vec3::new(i16::MIN, i16::MAX, 0).saturating_sub(I16Vec3::new(1, -1, 2)),
+            I16Vec3::new(i16::MIN, i16::MAX, -2)
+        );
+    });
+
+    glam_test!(test_saturating_mul, {
+        assert_eq!(
+            I16Vec3::new(i16::MAX, i16::MIN, 0).saturating_mul(I16Vec3::new(2, 2, 0)),
+            I16Vec3::new(i16::MAX, i16::MIN, 0)
+        );
+    });
+
+    glam_test!(test_saturating_div, {
+        assert_eq!(
+            I16Vec3::new(i16::MAX, i16::MIN, 0).saturating_div(I16Vec3::new(2, 2, 3)),
+            I16Vec3::new(16383, -16384, 0)
+        );
+    });
+
+    impl_vec3_signed_integer_tests!(i16, i16vec3, I16Vec3, BVec3);
+    impl_vec3_eq_hash_tests!(i16, i16vec3);
+
+    impl_vec3_scalar_shift_op_tests!(I16Vec3, -2, 2);
+    impl_vec3_shift_op_tests!(I16Vec3);
+
+    impl_vec3_scalar_bit_op_tests!(I16Vec3, -2, 2);
+    impl_vec3_bit_op_tests!(I16Vec3, -2, 2);
+}
+
+mod u16vec3 {
+    use glam::{u16vec3, BVec3, I16Vec3, I64Vec3, IVec3, U16Vec3, U64Vec3, UVec3};
+
+    glam_test!(test_align, {
+        use std::mem;
+        assert_eq!(6, mem::size_of::<U16Vec3>());
+        assert_eq!(2, mem::align_of::<U16Vec3>());
+    });
+
+    glam_test!(test_try_from, {
+        assert_eq!(
+            U16Vec3::new(1, 2, 3),
+            U16Vec3::try_from(I16Vec3::new(1, 2, 3)).unwrap()
+        );
+        assert!(U16Vec3::try_from(I16Vec3::new(-1, 2, 3)).is_err());
+        assert!(U16Vec3::try_from(I16Vec3::new(1, -2, 3)).is_err());
+        assert!(U16Vec3::try_from(I16Vec3::new(1, 2, -3)).is_err());
+
+        assert_eq!(
+            U16Vec3::new(1, 2, 3),
+            U16Vec3::try_from(IVec3::new(1, 2, 3)).unwrap()
+        );
+        assert!(U16Vec3::try_from(IVec3::new(-1, 2, 3)).is_err());
+        assert!(U16Vec3::try_from(IVec3::new(1, -2, 3)).is_err());
+        assert!(U16Vec3::try_from(IVec3::new(1, 2, -3)).is_err());
+
+        assert!(U16Vec3::try_from(IVec3::new(i32::MAX, 2, 3)).is_err());
+        assert!(U16Vec3::try_from(IVec3::new(1, i32::MAX, 3)).is_err());
+        assert!(U16Vec3::try_from(IVec3::new(1, 2, i32::MAX)).is_err());
+
+        assert_eq!(
+            U16Vec3::new(1, 2, 3),
+            U16Vec3::try_from(UVec3::new(1, 2, 3)).unwrap()
+        );
+        assert!(U16Vec3::try_from(UVec3::new(u32::MAX, 2, 3)).is_err());
+        assert!(U16Vec3::try_from(UVec3::new(1, u32::MAX, 3)).is_err());
+        assert!(U16Vec3::try_from(UVec3::new(1, 2, u32::MAX)).is_err());
+
+        assert_eq!(
+            U16Vec3::new(1, 2, 3),
+            U16Vec3::try_from(I64Vec3::new(1, 2, 3)).unwrap()
+        );
+        assert!(U16Vec3::try_from(I64Vec3::new(-1, 2, 3)).is_err());
+        assert!(U16Vec3::try_from(I64Vec3::new(1, -2, 3)).is_err());
+        assert!(U16Vec3::try_from(I64Vec3::new(1, 2, -3)).is_err());
+
+        assert!(U16Vec3::try_from(I64Vec3::new(i64::MAX, 2, 3)).is_err());
+        assert!(U16Vec3::try_from(I64Vec3::new(1, i64::MAX, 3)).is_err());
+        assert!(U16Vec3::try_from(I64Vec3::new(1, 2, i64::MAX)).is_err());
+
+        assert_eq!(
+            U16Vec3::new(1, 2, 3),
+            U16Vec3::try_from(U64Vec3::new(1, 2, 3)).unwrap()
+        );
+        assert!(U16Vec3::try_from(U64Vec3::new(u64::MAX, 2, 3)).is_err());
+        assert!(U16Vec3::try_from(U64Vec3::new(1, u64::MAX, 3)).is_err());
+        assert!(U16Vec3::try_from(U64Vec3::new(1, 2, u64::MAX)).is_err());
+    });
+
+    glam_test!(test_wrapping_add, {
+        assert_eq!(
+            U16Vec3::new(u16::MAX, 5, u16::MAX).wrapping_add(U16Vec3::new(1, 3, u16::MAX)),
+            U16Vec3::new(0, 8, 65534),
+        );
+    });
+
+    glam_test!(test_wrapping_sub, {
+        assert_eq!(
+            U16Vec3::new(u16::MAX, 5, u16::MAX - 1).wrapping_sub(U16Vec3::new(1, 3, u16::MAX)),
+            U16Vec3::new(65534, 2, 65535)
+        );
+    });
+
+    glam_test!(test_wrapping_mul, {
+        assert_eq!(
+            U16Vec3::new(u16::MAX, 5, u16::MAX).wrapping_mul(U16Vec3::new(3, 3, 5)),
+            U16Vec3::new(65533, 15, 65531)
+        );
+    });
+
+    glam_test!(test_wrapping_div, {
+        assert_eq!(
+            U16Vec3::new(u16::MAX, 5, u16::MAX).wrapping_div(U16Vec3::new(3, 3, 5)),
+            U16Vec3::new(21845, 1, 13107)
+        );
+    });
+
+    glam_test!(test_saturating_add, {
+        assert_eq!(
+            U16Vec3::new(u16::MAX, u16::MAX, 0).saturating_add(U16Vec3::new(1, u16::MAX, 2)),
+            U16Vec3::new(u16::MAX, u16::MAX, 2)
+        );
+    });
+
+    glam_test!(test_saturating_sub, {
+        assert_eq!(
+            U16Vec3::new(0, u16::MAX, 0).saturating_sub(U16Vec3::new(1, 1, 2)),
+            U16Vec3::new(0, 65534, 0)
+        );
+    });
+
+    glam_test!(test_saturating_mul, {
+        assert_eq!(
+            U16Vec3::new(u16::MAX, u16::MAX, 0).saturating_mul(U16Vec3::new(2, u16::MAX, 0)),
+            U16Vec3::new(u16::MAX, u16::MAX, 0)
+        );
+    });
+
+    glam_test!(test_saturating_div, {
+        assert_eq!(
+            U16Vec3::new(u16::MAX, u16::MAX, 0).saturating_div(U16Vec3::new(2, u16::MAX, 3)),
+            U16Vec3::new(32767, 1, 0)
+        );
+    });
+
+    impl_vec3_tests!(u16, u16vec3, U16Vec3, BVec3);
+    impl_vec3_eq_hash_tests!(u16, u16vec3);
+
+    impl_vec3_scalar_shift_op_tests!(U16Vec3, 0, 2);
+    impl_vec3_shift_op_tests!(U16Vec3);
+
+    impl_vec3_scalar_bit_op_tests!(U16Vec3, 0, 2);
+    impl_vec3_bit_op_tests!(U16Vec3, 0, 2);
+}
+
 mod ivec3 {
-    use glam::{ivec3, BVec3, IVec3, UVec3};
+    use glam::{ivec3, BVec3, I16Vec3, I64Vec3, IVec3, U16Vec3, U64Vec3, UVec3};
 
     glam_test!(test_align, {
         use std::mem;
@@ -1213,7 +1700,92 @@
         assert_eq!(1, mem::align_of::<BVec3>());
     });
 
-    impl_vec3_signed_tests!(i32, ivec3, IVec3, BVec3);
+    glam_test!(test_try_from, {
+        assert_eq!(IVec3::new(1, 2, 3), IVec3::from(U16Vec3::new(1, 2, 3)));
+        assert_eq!(IVec3::new(1, 2, 3), IVec3::from(I16Vec3::new(1, 2, 3)));
+
+        assert_eq!(
+            IVec3::new(1, 2, 3),
+            IVec3::try_from(UVec3::new(1, 2, 3)).unwrap()
+        );
+        assert!(IVec3::try_from(UVec3::new(u32::MAX, 2, 3)).is_err());
+        assert!(IVec3::try_from(UVec3::new(1, u32::MAX, 3)).is_err());
+        assert!(IVec3::try_from(UVec3::new(1, 2, u32::MAX)).is_err());
+
+        assert_eq!(
+            IVec3::new(1, 2, 3),
+            IVec3::try_from(I64Vec3::new(1, 2, 3)).unwrap()
+        );
+        assert!(IVec3::try_from(I64Vec3::new(i64::MAX, 2, 3)).is_err());
+        assert!(IVec3::try_from(I64Vec3::new(1, i64::MAX, 3)).is_err());
+        assert!(IVec3::try_from(I64Vec3::new(1, 2, i64::MAX)).is_err());
+
+        assert_eq!(
+            IVec3::new(1, 2, 3),
+            IVec3::try_from(U64Vec3::new(1, 2, 3)).unwrap()
+        );
+        assert!(IVec3::try_from(U64Vec3::new(u64::MAX, 2, 3)).is_err());
+        assert!(IVec3::try_from(U64Vec3::new(1, u64::MAX, 3)).is_err());
+        assert!(IVec3::try_from(U64Vec3::new(1, 2, u64::MAX)).is_err());
+    });
+
+    glam_test!(test_wrapping_add, {
+        assert_eq!(
+            IVec3::new(i32::MAX, 5, i32::MIN).wrapping_add(IVec3::new(1, 3, i32::MAX)),
+            IVec3::new(i32::MIN, 8, -1),
+        );
+    });
+
+    glam_test!(test_wrapping_sub, {
+        assert_eq!(
+            IVec3::new(i32::MAX, 5, i32::MIN).wrapping_sub(IVec3::new(1, 3, i32::MAX)),
+            IVec3::new(2147483646, 2, 1),
+        );
+    });
+
+    glam_test!(test_wrapping_mul, {
+        assert_eq!(
+            IVec3::new(i32::MAX, 5, i32::MIN).wrapping_mul(IVec3::new(3, 3, 5)),
+            IVec3::new(2147483645, 15, -2147483648)
+        );
+    });
+
+    glam_test!(test_wrapping_div, {
+        assert_eq!(
+            IVec3::new(i32::MAX, 5, i32::MIN).wrapping_div(IVec3::new(3, 3, 5)),
+            IVec3::new(715827882, 1, -429496729)
+        );
+    });
+
+    glam_test!(test_saturating_add, {
+        assert_eq!(
+            IVec3::new(i32::MAX, i32::MIN, 0).saturating_add(IVec3::new(1, -1, 2)),
+            IVec3::new(i32::MAX, i32::MIN, 2)
+        );
+    });
+
+    glam_test!(test_saturating_sub, {
+        assert_eq!(
+            IVec3::new(i32::MIN, i32::MAX, 0).saturating_sub(IVec3::new(1, -1, 2)),
+            IVec3::new(i32::MIN, i32::MAX, -2)
+        );
+    });
+
+    glam_test!(test_saturating_mul, {
+        assert_eq!(
+            IVec3::new(i32::MAX, i32::MIN, 0).saturating_mul(IVec3::new(2, 2, 0)),
+            IVec3::new(i32::MAX, i32::MIN, 0)
+        );
+    });
+
+    glam_test!(test_saturating_div, {
+        assert_eq!(
+            IVec3::new(i32::MAX, i32::MIN, 0).saturating_div(IVec3::new(2, 2, 3)),
+            IVec3::new(1073741823, -1073741824, 0)
+        );
+    });
+
+    impl_vec3_signed_integer_tests!(i32, ivec3, IVec3, BVec3);
     impl_vec3_eq_hash_tests!(i32, ivec3);
 
     impl_vec3_scalar_shift_op_tests!(IVec3, -2, 2);
@@ -1224,7 +1796,7 @@
 }
 
 mod uvec3 {
-    use glam::{uvec3, BVec3, IVec3, UVec3};
+    use glam::{uvec3, BVec3, I16Vec3, I64Vec3, IVec3, U16Vec3, U64Vec3, UVec3};
 
     glam_test!(test_align, {
         use std::mem;
@@ -1234,6 +1806,102 @@
         assert_eq!(1, mem::align_of::<BVec3>());
     });
 
+    glam_test!(test_try_from, {
+        assert_eq!(
+            UVec3::new(1, 2, 3),
+            UVec3::try_from(I16Vec3::new(1, 2, 3)).unwrap()
+        );
+        assert!(UVec3::try_from(I16Vec3::new(-1, 2, 3)).is_err());
+        assert!(UVec3::try_from(I16Vec3::new(1, -2, 3)).is_err());
+        assert!(UVec3::try_from(I16Vec3::new(1, 2, -3)).is_err());
+
+        assert_eq!(UVec3::new(1, 2, 3), UVec3::from(U16Vec3::new(1, 2, 3)));
+
+        assert_eq!(
+            UVec3::new(1, 2, 3),
+            UVec3::try_from(IVec3::new(1, 2, 3)).unwrap()
+        );
+        assert!(UVec3::try_from(IVec3::new(-1, 2, 3)).is_err());
+        assert!(UVec3::try_from(IVec3::new(1, -2, 3)).is_err());
+        assert!(UVec3::try_from(IVec3::new(1, 2, -3)).is_err());
+
+        assert_eq!(
+            UVec3::new(1, 2, 3),
+            UVec3::try_from(I64Vec3::new(1, 2, 3)).unwrap()
+        );
+        assert!(UVec3::try_from(I64Vec3::new(-1, 2, 3)).is_err());
+        assert!(UVec3::try_from(I64Vec3::new(1, -2, 3)).is_err());
+        assert!(UVec3::try_from(I64Vec3::new(1, 2, -3)).is_err());
+
+        assert!(UVec3::try_from(I64Vec3::new(i64::MAX, 2, 3)).is_err());
+        assert!(UVec3::try_from(I64Vec3::new(1, i64::MAX, 3)).is_err());
+        assert!(UVec3::try_from(I64Vec3::new(1, 2, i64::MAX)).is_err());
+
+        assert_eq!(
+            UVec3::new(1, 2, 3),
+            UVec3::try_from(U64Vec3::new(1, 2, 3)).unwrap()
+        );
+        assert!(UVec3::try_from(U64Vec3::new(u64::MAX, 2, 3)).is_err());
+        assert!(UVec3::try_from(U64Vec3::new(1, u64::MAX, 3)).is_err());
+        assert!(UVec3::try_from(U64Vec3::new(1, 2, u64::MAX)).is_err());
+    });
+
+    glam_test!(test_wrapping_add, {
+        assert_eq!(
+            UVec3::new(u32::MAX, 5, u32::MAX).wrapping_add(UVec3::new(1, 3, u32::MAX)),
+            UVec3::new(0, 8, 4294967294),
+        );
+    });
+
+    glam_test!(test_wrapping_sub, {
+        assert_eq!(
+            UVec3::new(u32::MAX, 5, u32::MAX - 1).wrapping_sub(UVec3::new(1, 3, u32::MAX)),
+            UVec3::new(4294967294, 2, 4294967295)
+        );
+    });
+
+    glam_test!(test_wrapping_mul, {
+        assert_eq!(
+            UVec3::new(u32::MAX, 5, u32::MAX).wrapping_mul(UVec3::new(3, 3, 5)),
+            UVec3::new(4294967293, 15, 4294967291)
+        );
+    });
+
+    glam_test!(test_wrapping_div, {
+        assert_eq!(
+            UVec3::new(u32::MAX, 5, u32::MAX).wrapping_div(UVec3::new(3, 3, 5)),
+            UVec3::new(1431655765, 1, 858993459)
+        );
+    });
+
+    glam_test!(test_saturating_add, {
+        assert_eq!(
+            UVec3::new(u32::MAX, u32::MAX, 0).saturating_add(UVec3::new(1, u32::MAX, 2)),
+            UVec3::new(u32::MAX, u32::MAX, 2)
+        );
+    });
+
+    glam_test!(test_saturating_sub, {
+        assert_eq!(
+            UVec3::new(0, u32::MAX, 0).saturating_sub(UVec3::new(1, 1, 2)),
+            UVec3::new(0, 4294967294, 0)
+        );
+    });
+
+    glam_test!(test_saturating_mul, {
+        assert_eq!(
+            UVec3::new(u32::MAX, u32::MAX, 0).saturating_mul(UVec3::new(2, u32::MAX, 0)),
+            UVec3::new(u32::MAX, u32::MAX, 0)
+        );
+    });
+
+    glam_test!(test_saturating_div, {
+        assert_eq!(
+            UVec3::new(u32::MAX, u32::MAX, 0).saturating_div(UVec3::new(2, u32::MAX, 3)),
+            UVec3::new(2147483647, 1, 0)
+        );
+    });
+
     impl_vec3_tests!(u32, uvec3, UVec3, BVec3);
     impl_vec3_eq_hash_tests!(u32, uvec3);
 
@@ -1243,3 +1911,90 @@
     impl_vec3_scalar_bit_op_tests!(UVec3, 0, 2);
     impl_vec3_bit_op_tests!(UVec3, 0, 2);
 }
+
+mod i64vec3 {
+    use glam::{i64vec3, BVec3, I16Vec3, I64Vec3, IVec3, U16Vec3, U64Vec3, UVec3};
+
+    glam_test!(test_align, {
+        use std::mem;
+        assert_eq!(24, mem::size_of::<I64Vec3>());
+        assert_eq!(8, mem::align_of::<I64Vec3>());
+        assert_eq!(3, mem::size_of::<BVec3>());
+        assert_eq!(1, mem::align_of::<BVec3>());
+    });
+
+    glam_test!(test_try_from, {
+        assert_eq!(I64Vec3::new(1, 2, 3), I64Vec3::from(I16Vec3::new(1, 2, 3)));
+        assert_eq!(I64Vec3::new(1, 2, 3), I64Vec3::from(U16Vec3::new(1, 2, 3)));
+        assert_eq!(I64Vec3::new(1, 2, 3), I64Vec3::from(IVec3::new(1, 2, 3)));
+        assert_eq!(I64Vec3::new(1, 2, 3), I64Vec3::from(UVec3::new(1, 2, 3)));
+
+        assert_eq!(
+            I64Vec3::new(1, 2, 3),
+            I64Vec3::try_from(U64Vec3::new(1, 2, 3)).unwrap()
+        );
+        assert!(I64Vec3::try_from(U64Vec3::new(u64::MAX, 2, 3)).is_err());
+        assert!(I64Vec3::try_from(U64Vec3::new(1, u64::MAX, 3)).is_err());
+        assert!(I64Vec3::try_from(U64Vec3::new(1, 2, u64::MAX)).is_err());
+    });
+
+    impl_vec3_signed_integer_tests!(i64, i64vec3, I64Vec3, BVec3);
+    impl_vec3_eq_hash_tests!(i64, i64vec3);
+
+    impl_vec3_scalar_shift_op_tests!(I64Vec3, -2, 2);
+    impl_vec3_shift_op_tests!(I64Vec3);
+
+    impl_vec3_scalar_bit_op_tests!(I64Vec3, -2, 2);
+    impl_vec3_bit_op_tests!(I64Vec3, -2, 2);
+}
+
+mod u64vec3 {
+    use glam::{u64vec3, BVec3, I16Vec3, I64Vec3, IVec3, U16Vec3, U64Vec3, UVec3};
+
+    glam_test!(test_align, {
+        use std::mem;
+        assert_eq!(24, mem::size_of::<U64Vec3>());
+        assert_eq!(8, mem::align_of::<U64Vec3>());
+        assert_eq!(3, mem::size_of::<BVec3>());
+        assert_eq!(1, mem::align_of::<BVec3>());
+    });
+
+    glam_test!(test_try_from, {
+        assert_eq!(
+            U64Vec3::new(1, 2, 3),
+            U64Vec3::try_from(I16Vec3::new(1, 2, 3)).unwrap()
+        );
+        assert!(U64Vec3::try_from(I16Vec3::new(-1, 2, 3)).is_err());
+        assert!(U64Vec3::try_from(I16Vec3::new(1, -2, 3)).is_err());
+        assert!(U64Vec3::try_from(I16Vec3::new(1, 2, -3)).is_err());
+
+        assert_eq!(U64Vec3::new(1, 2, 3), U64Vec3::from(U16Vec3::new(1, 2, 3)));
+
+        assert_eq!(
+            U64Vec3::new(1, 2, 3),
+            U64Vec3::try_from(IVec3::new(1, 2, 3)).unwrap()
+        );
+        assert!(U64Vec3::try_from(IVec3::new(-1, 2, 3)).is_err());
+        assert!(U64Vec3::try_from(IVec3::new(1, -2, 3)).is_err());
+        assert!(U64Vec3::try_from(IVec3::new(1, 2, -3)).is_err());
+
+        assert_eq!(U64Vec3::new(1, 2, 3), U64Vec3::from(UVec3::new(1, 2, 3)));
+
+        assert_eq!(
+            U64Vec3::new(1, 2, 3),
+            U64Vec3::try_from(I64Vec3::new(1, 2, 3)).unwrap()
+        );
+        assert!(U64Vec3::try_from(I64Vec3::new(-1, 2, 3)).is_err());
+        assert!(U64Vec3::try_from(I64Vec3::new(1, -2, 3)).is_err());
+        assert!(U64Vec3::try_from(I64Vec3::new(1, 2, -3)).is_err());
+    });
+
+    impl_vec3_tests!(u64, u64vec3, U64Vec3, BVec3);
+    impl_vec3_eq_hash_tests!(u64, u64vec3);
+
+    impl_vec3_scalar_shift_op_tests!(U64Vec3, 0, 2);
+    impl_vec3_shift_op_tests!(U64Vec3);
+
+    impl_vec3_scalar_bit_op_tests!(U64Vec3, 0, 2);
+    impl_vec3_bit_op_tests!(U64Vec3, 0, 2);
+}
diff --git a/tests/vec4.rs b/tests/vec4.rs
index ce86019..499c7b8 100644
--- a/tests/vec4.rs
+++ b/tests/vec4.rs
@@ -21,6 +21,8 @@
             assert_eq!($vec4::Y, $new(0 as $t, 1 as $t, 0 as $t, 0 as $t));
             assert_eq!($vec4::Z, $new(0 as $t, 0 as $t, 1 as $t, 0 as $t));
             assert_eq!($vec4::W, $new(0 as $t, 0 as $t, 0 as $t, 1 as $t));
+            assert_eq!($vec4::MIN, $new($t::MIN, $t::MIN, $t::MIN, $t::MIN));
+            assert_eq!($vec4::MAX, $new($t::MAX, $t::MAX, $t::MAX, $t::MAX));
         });
 
         glam_test!(test_new, {
@@ -146,6 +148,25 @@
             assert_eq!(0 as $t, x.dot(y));
             assert_eq!(0 as $t, y.dot(z));
             assert_eq!(0 as $t, z.dot(w));
+
+            assert_eq!(
+                $new(28 as $t, 28 as $t, 28 as $t, 28 as $t),
+                $new(0 as $t, 5 as $t, 3 as $t, 6 as $t)
+                    .dot_into_vec($new(7 as $t, 2 as $t, 4 as $t, 1 as $t))
+            );
+        });
+
+        glam_test!(test_length_squared_unsigned, {
+            let x = $new(1 as $t, 0 as $t, 0 as $t, 0 as $t);
+            let z = $new(0 as $t, 0 as $t, 1 as $t, 0 as $t);
+            let w = $new(0 as $t, 0 as $t, 0 as $t, 1 as $t);
+            assert_eq!(4 as $t, (2 as $t * x).length_squared());
+            assert_eq!(16 as $t, (4 as $t * z).length_squared());
+            assert_eq!(64 as $t, (8 as $t * w).length_squared());
+            assert_eq!(
+                2 as $t * 2 as $t + 3 as $t * 3 as $t + 4 as $t * 4 as $t + 5 as $t * 5 as $t,
+                $new(2 as $t, 3 as $t, 4 as $t, 5 as $t).length_squared()
+            );
         });
 
         glam_test!(test_ops, {
@@ -540,6 +561,42 @@
             assert_ne!(b, c);
         });
 
+        glam_test!(test_mask_test, {
+            let a = $mask::new(true, false, true, false);
+            assert_eq!(a.test(0), true);
+            assert_eq!(a.test(1), false);
+            assert_eq!(a.test(2), true);
+            assert_eq!(a.test(3), false);
+
+            let b = $mask::new(false, true, false, true);
+            assert_eq!(b.test(0), false);
+            assert_eq!(b.test(1), true);
+            assert_eq!(b.test(2), false);
+            assert_eq!(b.test(3), true);
+        });
+
+        glam_test!(test_mask_set, {
+            let mut a = $mask::new(false, true, false, true);
+            a.set(0, true);
+            assert_eq!(a.test(0), true);
+            a.set(1, false);
+            assert_eq!(a.test(1), false);
+            a.set(2, true);
+            assert_eq!(a.test(2), true);
+            a.set(3, false);
+            assert_eq!(a.test(3), false);
+
+            let mut b = $mask::new(true, false, true, false);
+            b.set(0, false);
+            assert_eq!(b.test(0), false);
+            b.set(1, true);
+            assert_eq!(b.test(1), true);
+            b.set(2, false);
+            assert_eq!(b.test(2), false);
+            b.set(3, true);
+            assert_eq!(b.test(3), true);
+        });
+
         glam_test!(test_mask_hash, {
             use std::collections::hash_map::DefaultHasher;
             use std::hash::Hash;
@@ -576,14 +633,14 @@
 
         glam_test!(test_sum, {
             let one = $vec4::ONE;
-            assert_eq!(vec![one, one].iter().sum::<$vec4>(), one + one);
-            assert_eq!(vec![one, one].into_iter().sum::<$vec4>(), one + one);
+            assert_eq!([one, one].iter().sum::<$vec4>(), one + one);
+            assert_eq!([one, one].into_iter().sum::<$vec4>(), one + one);
         });
 
         glam_test!(test_product, {
             let two = $vec4::new(2 as $t, 2 as $t, 2 as $t, 2 as $t);
-            assert_eq!(vec![two, two].iter().product::<$vec4>(), two * two);
-            assert_eq!(vec![two, two].into_iter().product::<$vec4>(), two * two);
+            assert_eq!([two, two].iter().product::<$vec4>(), two * two);
+            assert_eq!([two, two].into_iter().product::<$vec4>(), two * two);
         });
     };
 }
@@ -596,15 +653,43 @@
             let a = $new(1 as $t, 2 as $t, 3 as $t, 4 as $t);
             assert_eq!((-1 as $t, -2 as $t, -3 as $t, -4 as $t), (-a).into());
             assert_eq!(
-                $new(-0.0 as $t, -0.0 as $t, -0.0 as $t, -0.0 as $t),
-                -$new(0.0 as $t, 0.0 as $t, 0.0 as $t, 0.0 as $t)
+                $new(-0 as $t, -0 as $t, -0 as $t, -0 as $t),
+                -$new(0 as $t, 0 as $t, 0 as $t, 0 as $t)
             );
             assert_eq!(
-                $new(0.0 as $t, -0.0 as $t, -0.0 as $t, -0.0 as $t),
-                -$new(-0.0 as $t, 0.0 as $t, 0.0 as $t, 0.0 as $t)
+                $new(0 as $t, -0 as $t, -0 as $t, -0 as $t),
+                -$new(-0 as $t, 0 as $t, 0 as $t, 0 as $t)
             );
         });
 
+        glam_test!(test_is_negative_bitmask, {
+            assert_eq!($vec4::ZERO.is_negative_bitmask(), 0b0000);
+            assert_eq!($vec4::ONE.is_negative_bitmask(), 0b0000);
+            assert_eq!((-$vec4::ONE).is_negative_bitmask(), 0b1111);
+            assert_eq!(
+                $vec4::new(-1 as $t, 2 as $t, 3 as $t, -4 as $t).is_negative_bitmask(),
+                0b1001
+            );
+            assert_eq!(
+                $vec4::new(1 as $t, 5 as $t, -3 as $t, 7 as $t).is_negative_bitmask(),
+                0b0100
+            );
+            assert_eq!(
+                $vec4::new(3 as $t, -4 as $t, 1 as $t, 6 as $t).is_negative_bitmask(),
+                0b0010
+            );
+            assert_eq!(
+                $vec4::new(2 as $t, -6 as $t, 5 as $t, -3 as $t).is_negative_bitmask(),
+                0b1010
+            );
+        });
+
+        glam_test!(test_abs, {
+            assert_eq!($vec4::ZERO.abs(), $vec4::ZERO);
+            assert_eq!($vec4::ONE.abs(), $vec4::ONE);
+            assert_eq!((-$vec4::ONE).abs(), $vec4::ONE);
+        });
+
         glam_test!(test_dot_signed, {
             let x = $new(1 as $t, 0 as $t, 0 as $t, 0 as $t);
             let y = $new(0 as $t, 1 as $t, 0 as $t, 0 as $t);
@@ -615,6 +700,56 @@
             assert_eq!(0 as $t, x.dot(-z));
             assert_eq!(-1 as $t, w.dot(-w));
         });
+
+        glam_test!(test_length_squared_signed, {
+            let x = $new(1 as $t, 0 as $t, 0 as $t, 0 as $t);
+            let y = $new(0 as $t, 1 as $t, 0 as $t, 0 as $t);
+            let z = $new(0 as $t, 0 as $t, 1 as $t, 0 as $t);
+            let w = $new(0 as $t, 0 as $t, 0 as $t, 1 as $t);
+            assert_eq!(4 as $t, (2 as $t * x).length_squared());
+            assert_eq!(9 as $t, (-3 as $t * y).length_squared());
+            assert_eq!(16 as $t, (4 as $t * z).length_squared());
+            assert_eq!(64 as $t, (8 as $t * w).length_squared());
+            assert_eq!(
+                2 as $t * 2 as $t + 3 as $t * 3 as $t + 4 as $t * 4 as $t + 5 as $t * 5 as $t,
+                $new(2 as $t, 3 as $t, 4 as $t, 5 as $t).length_squared()
+            );
+            assert_eq!(2 as $t, x.distance_squared(y));
+            assert_eq!(13 as $t, (2 as $t * x).distance_squared(-3 as $t * z));
+        });
+
+        glam_test!(test_div_euclid, {
+            let one = $vec4::ONE;
+            let two = one + one;
+            let three = two + one;
+            assert_eq!(three.div_euclid(two), one);
+            assert_eq!((-three).div_euclid(two), -two);
+            assert_eq!(three.div_euclid(-two), -one);
+            assert_eq!((-three).div_euclid(-two), two);
+        });
+
+        glam_test!(test_rem_euclid, {
+            let one = $vec4::ONE;
+            let two = one + one;
+            let three = two + one;
+            let four = three + one;
+            assert_eq!(four.rem_euclid(three), one);
+            assert_eq!((-four).rem_euclid(three), two);
+            assert_eq!(four.rem_euclid(-three), one);
+            assert_eq!((-four).rem_euclid(-three), two);
+        });
+    };
+}
+
+macro_rules! impl_vec4_signed_integer_tests {
+    ($t:ident, $new:ident, $vec4:ident, $vec3:ident, $vec2:ident, $mask:ident) => {
+        impl_vec4_signed_tests!($t, $new, $vec4, $vec3, $vec2, $mask);
+
+        glam_test!(test_signum, {
+            assert_eq!($vec4::ZERO.signum(), $vec4::ZERO);
+            assert_eq!($vec4::ONE.signum(), $vec4::ONE);
+            assert_eq!((-$vec4::ONE).signum(), -$vec4::ONE);
+        });
     };
 }
 
@@ -668,16 +803,10 @@
             let y = $new(0.0, 1.0, 0.0, 0.0);
             let z = $new(0.0, 0.0, 1.0, 0.0);
             let w = $new(0.0, 0.0, 0.0, 1.0);
-            assert_eq!(4.0, (2.0 * x).length_squared());
-            assert_eq!(9.0, (-3.0 * y).length_squared());
-            assert_eq!(16.0, (4.0 * z).length_squared());
-            assert_eq!(64.0, (8.0 * w).length_squared());
             assert_eq!(2.0, (-2.0 * x).length());
             assert_eq!(3.0, (3.0 * y).length());
             assert_eq!(4.0, (-4.0 * z).length());
             assert_eq!(5.0, (-5.0 * w).length());
-            assert_eq!(2.0, x.distance_squared(y));
-            assert_eq!(13.0, (2.0 * x).distance_squared(-3.0 * z));
             assert_eq!((2.0 as $t).sqrt(), w.distance(y));
             assert_eq!(5.0, (3.0 * x).distance(-4.0 * y));
             assert_eq!(13.0, (-5.0 * w).distance(12.0 * y));
@@ -687,14 +816,6 @@
                 $new(1.0, 2.0, 3.0, 4.0).dot($new(5.0, 6.0, 7.0, 8.0))
             );
             assert_eq!(
-                $new(28.0, 28.0, 28.0, 28.0),
-                $new(0.0, 5.0, 3.0, 6.0).dot_into_vec($new(7.0, 2.0, 4.0, 1.0))
-            );
-            assert_eq!(
-                2.0 * 2.0 + 3.0 * 3.0 + 4.0 * 4.0 + 5.0 * 5.0,
-                $new(2.0, 3.0, 4.0, 5.0).length_squared()
-            );
-            assert_eq!(
                 (2.0 as $t * 2.0 + 3.0 * 3.0 + 4.0 * 4.0 + 5.0 * 5.0).sqrt(),
                 $new(2.0, 3.0, 4.0, 5.0).length()
             );
@@ -742,9 +863,9 @@
             assert_eq!((-$vec4::ZERO).signum(), -$vec4::ONE);
             assert_eq!($vec4::ONE.signum(), $vec4::ONE);
             assert_eq!((-$vec4::ONE).signum(), -$vec4::ONE);
-            assert_eq!($vec4::splat(INFINITY).signum(), $vec4::ONE);
-            assert_eq!($vec4::splat(NEG_INFINITY).signum(), -$vec4::ONE);
-            assert!($vec4::splat(NAN).signum().is_nan_mask().all());
+            assert_eq!($vec4::INFINITY.signum(), $vec4::ONE);
+            assert_eq!($vec4::NEG_INFINITY.signum(), -$vec4::ONE);
+            assert!($vec4::NAN.signum().is_nan_mask().all());
         });
 
         glam_test!(test_copysign, {
@@ -764,59 +885,44 @@
             assert_eq!((-$vec4::ONE).copysign(-$vec4::ONE), -$vec4::ONE);
             assert_eq!($vec4::ONE.copysign($vec4::ONE), $vec4::ONE);
             assert_eq!((-$vec4::ONE).copysign($vec4::ONE), $vec4::ONE);
+            assert_eq!($vec4::INFINITY.copysign($vec4::ONE), $vec4::INFINITY);
+            assert_eq!($vec4::INFINITY.copysign(-$vec4::ONE), $vec4::NEG_INFINITY);
+            assert_eq!($vec4::NEG_INFINITY.copysign($vec4::ONE), $vec4::INFINITY);
             assert_eq!(
-                $vec4::splat(INFINITY).copysign($vec4::ONE),
-                $vec4::splat(INFINITY)
+                $vec4::NEG_INFINITY.copysign(-$vec4::ONE),
+                $vec4::NEG_INFINITY
             );
-            assert_eq!(
-                $vec4::splat(INFINITY).copysign(-$vec4::ONE),
-                $vec4::splat(NEG_INFINITY)
-            );
-            assert_eq!(
-                $vec4::splat(NEG_INFINITY).copysign($vec4::ONE),
-                $vec4::splat(INFINITY)
-            );
-            assert_eq!(
-                $vec4::splat(NEG_INFINITY).copysign(-$vec4::ONE),
-                $vec4::splat(NEG_INFINITY)
-            );
-            assert!($vec4::splat(NAN).copysign($vec4::ONE).is_nan_mask().all());
-            assert!($vec4::splat(NAN).copysign(-$vec4::ONE).is_nan_mask().all());
+            assert!($vec4::NAN.copysign($vec4::ONE).is_nan_mask().all());
+            assert!($vec4::NAN.copysign(-$vec4::ONE).is_nan_mask().all());
         });
 
-        glam_test!(test_is_negative_bitmask, {
+        glam_test!(test_float_is_negative_bitmask, {
             assert_eq!($vec4::ZERO.is_negative_bitmask(), 0b0000);
             assert_eq!((-$vec4::ZERO).is_negative_bitmask(), 0b1111);
             assert_eq!($vec4::ONE.is_negative_bitmask(), 0b0000);
             assert_eq!((-$vec4::ONE).is_negative_bitmask(), 0b1111);
             assert_eq!(
-                $vec4::new(-0.1, 0.2, 0.3, -0.4).is_negative_bitmask(),
+                $vec4::new(-1.0, 2.0, 3.0, -4.0).is_negative_bitmask(),
                 0b1001
             );
             assert_eq!(
-                $vec4::new(0.8, 0.3, 0.1, -0.0).is_negative_bitmask(),
+                $vec4::new(8.0, 3.0, 1.0, -0.0).is_negative_bitmask(),
                 0b1000
             );
             assert_eq!(
-                $vec4::new(0.1, 0.5, -0.3, 0.7).is_negative_bitmask(),
+                $vec4::new(1.0, 5.0, -3.0, 7.0).is_negative_bitmask(),
                 0b0100
             );
             assert_eq!(
-                $vec4::new(0.3, -0.4, 0.1, 0.6).is_negative_bitmask(),
+                $vec4::new(3.0, -4.0, 1.0, 6.0).is_negative_bitmask(),
                 0b0010
             );
             assert_eq!(
-                $vec4::new(0.2, -0.6, 0.5, -0.3).is_negative_bitmask(),
+                $vec4::new(2.0, -6.0, 5.0, -3.0).is_negative_bitmask(),
                 0b1010
             );
         });
 
-        glam_test!(test_abs, {
-            assert_eq!($vec4::ZERO.abs(), $vec4::ZERO);
-            assert_eq!($vec4::ONE.abs(), $vec4::ONE);
-            assert_eq!((-$vec4::ONE).abs(), $vec4::ONE);
-        });
-
         glam_test!(test_round, {
             assert_eq!($vec4::new(1.35, 0.0, 0.0, 0.0).round().x, 1.0);
             assert_eq!($vec4::new(0.0, 1.5, 0.0, 0.0).round().y, 2.0);
@@ -876,6 +982,22 @@
             );
         });
 
+        glam_test!(test_trunc, {
+            assert_eq!(
+                $vec4::new(1.35, 1.5, -1.5, 1.999).trunc(),
+                $vec4::new(1.0, 1.0, -1.0, 1.0)
+            );
+            assert_eq!(
+                $vec4::new(INFINITY, NEG_INFINITY, 0.0, 0.0).trunc(),
+                $vec4::new(INFINITY, NEG_INFINITY, 0.0, 0.0)
+            );
+            assert!($vec4::new(0.0, NAN, 0.0, 0.0).trunc().y.is_nan());
+            assert_eq!(
+                $vec4::new(-0.0, -2000000.123, 10000000.123, 1000.9).trunc(),
+                $vec4::new(-0.0, -2000000.0, 10000000.0, 1000.0)
+            );
+        });
+
         glam_test!(test_lerp, {
             let v0 = $vec4::new(-1.0, -1.0, -1.0, -1.0);
             let v1 = $vec4::new(1.0, 1.0, 1.0, 1.0);
@@ -891,6 +1013,8 @@
             assert!(!$vec4::new(0.0, NAN, 0.0, 0.0).is_finite());
             assert!(!$vec4::new(0.0, 0.0, NEG_INFINITY, 0.0).is_finite());
             assert!(!$vec4::new(0.0, 0.0, 0.0, NAN).is_finite());
+            assert!(!$vec4::INFINITY.is_finite());
+            assert!(!$vec4::NEG_INFINITY.is_finite());
         });
 
         glam_test!(test_powf, {
@@ -1009,6 +1133,10 @@
             use glam::$vec4;
             impl_vec4_scalar_shift_op_test!($vec4, $t_min, $t_max, 0i32, 2);
         }
+        mod shift_by_i64 {
+            use glam::$vec4;
+            impl_vec4_scalar_shift_op_test!($vec4, $t_min, $t_max, 0i64, 2);
+        }
         mod shift_by_u8 {
             use glam::$vec4;
             impl_vec4_scalar_shift_op_test!($vec4, $t_min, $t_max, 0u8, 2);
@@ -1021,6 +1149,10 @@
             use glam::$vec4;
             impl_vec4_scalar_shift_op_test!($vec4, $t_min, $t_max, 0u32, 2);
         }
+        mod shift_by_u64 {
+            use glam::$vec4;
+            impl_vec4_scalar_shift_op_test!($vec4, $t_min, $t_max, 0u64, 2);
+        }
     };
 }
 
@@ -1138,6 +1270,7 @@
         });
     };
 }
+
 mod vec4 {
     #[cfg(any(
         not(any(target_feature = "sse2", target_feature = "simd128")),
@@ -1205,12 +1338,20 @@
     }
 
     glam_test!(test_as, {
-        use glam::{DVec4, IVec4, UVec4};
+        use glam::{DVec4, I16Vec4, I64Vec4, IVec4, U16Vec4, U64Vec4, UVec4, Vec4};
         assert_eq!(
             DVec4::new(-1.0, -2.0, -3.0, -4.0),
             Vec4::new(-1.0, -2.0, -3.0, -4.0).as_dvec4()
         );
         assert_eq!(
+            I16Vec4::new(-1, -2, -3, -4),
+            Vec4::new(-1.0, -2.0, -3.0, -4.0).as_i16vec4()
+        );
+        assert_eq!(
+            U16Vec4::new(1, 2, 3, 4),
+            Vec4::new(1.0, 2.0, 3.0, 4.0).as_u16vec4()
+        );
+        assert_eq!(
             IVec4::new(-1, -2, -3, -4),
             Vec4::new(-1.0, -2.0, -3.0, -4.0).as_ivec4()
         );
@@ -1218,8 +1359,28 @@
             UVec4::new(1, 2, 3, 4),
             Vec4::new(1.0, 2.0, 3.0, 4.0).as_uvec4()
         );
+        assert_eq!(
+            I64Vec4::new(-1, -2, -3, -4),
+            Vec4::new(-1.0, -2.0, -3.0, -4.0).as_i64vec4()
+        );
+        assert_eq!(
+            U64Vec4::new(1, 2, 3, 4),
+            Vec4::new(1.0, 2.0, 3.0, 4.0).as_u64vec4()
+        );
 
         assert_eq!(
+            Vec4::new(-1.0, -2.0, -3.0, -4.0),
+            DVec4::new(-1.0, -2.0, -3.0, -4.0).as_vec4()
+        );
+        assert_eq!(
+            I16Vec4::new(-1, -2, -3, -4),
+            DVec4::new(-1.0, -2.0, -3.0, -4.0).as_i16vec4()
+        );
+        assert_eq!(
+            U16Vec4::new(1, 2, 3, 4),
+            DVec4::new(1.0, 2.0, 3.0, 4.0).as_u16vec4()
+        );
+        assert_eq!(
             IVec4::new(-1, -2, -3, -4),
             DVec4::new(-1.0, -2.0, -3.0, -4.0).as_ivec4()
         );
@@ -1228,28 +1389,162 @@
             DVec4::new(1.0, 2.0, 3.0, 4.0).as_uvec4()
         );
         assert_eq!(
-            Vec4::new(-1.0, -2.0, -3.0, -4.0),
-            DVec4::new(-1.0, -2.0, -3.0, -4.0).as_vec4()
+            I64Vec4::new(-1, -2, -3, -4),
+            DVec4::new(-1.0, -2.0, -3.0, -4.0).as_i64vec4()
+        );
+        assert_eq!(
+            U64Vec4::new(1, 2, 3, 4),
+            DVec4::new(1.0, 2.0, 3.0, 4.0).as_u64vec4()
         );
 
         assert_eq!(
+            Vec4::new(-1.0, -2.0, -3.0, -4.0),
+            I16Vec4::new(-1, -2, -3, -4).as_vec4()
+        );
+        assert_eq!(
+            DVec4::new(-1.0, -2.0, -3.0, -4.0),
+            I16Vec4::new(-1, -2, -3, -4).as_dvec4()
+        );
+        assert_eq!(
+            U16Vec4::new(1, 2, 3, 4),
+            I16Vec4::new(1, 2, 3, 4).as_u16vec4()
+        );
+        assert_eq!(
+            IVec4::new(-1, -2, -3, -4),
+            I16Vec4::new(-1, -2, -3, -4).as_ivec4()
+        );
+        assert_eq!(UVec4::new(1, 2, 3, 4), I16Vec4::new(1, 2, 3, 4).as_uvec4());
+        assert_eq!(
+            I64Vec4::new(-1, -2, -3, -4),
+            I16Vec4::new(-1, -2, -3, -4).as_i64vec4()
+        );
+        assert_eq!(
+            U64Vec4::new(1, 2, 3, 4),
+            I16Vec4::new(1, 2, 3, 4).as_u64vec4()
+        );
+
+        assert_eq!(
+            Vec4::new(1.0, 2.0, 3.0, 4.0),
+            U16Vec4::new(1, 2, 3, 4).as_vec4()
+        );
+        assert_eq!(
+            DVec4::new(1.0, 2.0, 3.0, 4.0),
+            U16Vec4::new(1, 2, 3, 4).as_dvec4()
+        );
+        assert_eq!(
+            I16Vec4::new(1, 2, 3, 4),
+            U16Vec4::new(1, 2, 3, 4).as_i16vec4()
+        );
+        assert_eq!(IVec4::new(1, 2, 3, 4), U16Vec4::new(1, 2, 3, 4).as_ivec4());
+        assert_eq!(UVec4::new(1, 2, 3, 4), U16Vec4::new(1, 2, 3, 4).as_uvec4());
+        assert_eq!(
+            I64Vec4::new(1, 2, 3, 4),
+            U16Vec4::new(1, 2, 3, 4).as_i64vec4()
+        );
+        assert_eq!(
+            U64Vec4::new(1, 2, 3, 4),
+            U16Vec4::new(1, 2, 3, 4).as_u64vec4()
+        );
+
+        assert_eq!(
+            Vec4::new(-1.0, -2.0, -3.0, -4.0),
+            IVec4::new(-1, -2, -3, -4).as_vec4()
+        );
+        assert_eq!(
             DVec4::new(-1.0, -2.0, -3.0, -4.0),
             IVec4::new(-1, -2, -3, -4).as_dvec4()
         );
         assert_eq!(UVec4::new(1, 2, 3, 4), IVec4::new(1, 2, 3, 4).as_uvec4());
         assert_eq!(
-            Vec4::new(-1.0, -2.0, -3.0, -4.0),
-            IVec4::new(-1, -2, -3, -4).as_vec4()
+            I16Vec4::new(-1, -2, -3, -4),
+            IVec4::new(-1, -2, -3, -4).as_i16vec4()
+        );
+        assert_eq!(
+            U16Vec4::new(1, 2, 3, 4),
+            IVec4::new(1, 2, 3, 4).as_u16vec4()
+        );
+        assert_eq!(
+            I64Vec4::new(-1, -2, -3, -4),
+            IVec4::new(-1, -2, -3, -4).as_i64vec4()
+        );
+        assert_eq!(
+            U64Vec4::new(1, 2, 3, 4),
+            IVec4::new(1, 2, 3, 4).as_u64vec4()
         );
 
         assert_eq!(
+            Vec4::new(1.0, 2.0, 3.0, 4.0),
+            UVec4::new(1, 2, 3, 4).as_vec4()
+        );
+        assert_eq!(
             DVec4::new(1.0, 2.0, 3.0, 4.0),
             UVec4::new(1, 2, 3, 4).as_dvec4()
         );
+        assert_eq!(
+            I16Vec4::new(1, 2, 3, 4),
+            UVec4::new(1, 2, 3, 4).as_i16vec4()
+        );
+        assert_eq!(
+            U16Vec4::new(1, 2, 3, 4),
+            UVec4::new(1, 2, 3, 4).as_u16vec4()
+        );
         assert_eq!(IVec4::new(1, 2, 3, 4), UVec4::new(1, 2, 3, 4).as_ivec4());
         assert_eq!(
+            I64Vec4::new(1, 2, 3, 4),
+            UVec4::new(1, 2, 3, 4).as_i64vec4()
+        );
+        assert_eq!(
+            U64Vec4::new(1, 2, 3, 4),
+            UVec4::new(1, 2, 3, 4).as_u64vec4()
+        );
+
+        assert_eq!(
+            Vec4::new(-1.0, -2.0, -3.0, -4.0),
+            I64Vec4::new(-1, -2, -3, -4).as_vec4()
+        );
+        assert_eq!(
+            DVec4::new(-1.0, -2.0, -3.0, -4.0),
+            I64Vec4::new(-1, -2, -3, -4).as_dvec4()
+        );
+        assert_eq!(
+            U16Vec4::new(1, 2, 3, 4),
+            I64Vec4::new(1, 2, 3, 4).as_u16vec4()
+        );
+        assert_eq!(
+            I16Vec4::new(-1, -2, -3, -4),
+            I64Vec4::new(-1, -2, -3, -4).as_i16vec4()
+        );
+        assert_eq!(UVec4::new(1, 2, 3, 4), I64Vec4::new(1, 2, 3, 4).as_uvec4());
+        assert_eq!(
+            IVec4::new(-1, -2, -3, -4),
+            I64Vec4::new(-1, -2, -3, -4).as_ivec4()
+        );
+        assert_eq!(
+            U64Vec4::new(1, 2, 3, 4),
+            I64Vec4::new(1, 2, 3, 4).as_u64vec4()
+        );
+
+        assert_eq!(
             Vec4::new(1.0, 2.0, 3.0, 4.0),
-            UVec4::new(1, 2, 3, 4).as_vec4()
+            U64Vec4::new(1, 2, 3, 4).as_vec4()
+        );
+        assert_eq!(
+            DVec4::new(1.0, 2.0, 3.0, 4.0),
+            U64Vec4::new(1, 2, 3, 4).as_dvec4()
+        );
+        assert_eq!(
+            I16Vec4::new(1, 2, 3, 4),
+            U64Vec4::new(1, 2, 3, 4).as_i16vec4()
+        );
+        assert_eq!(
+            U16Vec4::new(1, 2, 3, 4),
+            U64Vec4::new(1, 2, 3, 4).as_u16vec4()
+        );
+        assert_eq!(IVec4::new(1, 2, 3, 4), U64Vec4::new(1, 2, 3, 4).as_ivec4());
+        assert_eq!(UVec4::new(1, 2, 3, 4), U64Vec4::new(1, 2, 3, 4).as_uvec4());
+        assert_eq!(
+            I64Vec4::new(1, 2, 3, 4),
+            U64Vec4::new(1, 2, 3, 4).as_i64vec4()
         );
     });
 
@@ -1265,21 +1560,15 @@
         );
     });
 
-    #[cfg(all(
-        any(target_feature = "sse2", target_feature = "simd128"),
-        not(feature = "scalar-math")
-    ))]
+    #[cfg(not(feature = "scalar-math"))]
     impl_vec4_float_tests!(f32, vec4, Vec4, Vec3, Vec2, BVec4A);
 
-    #[cfg(any(
-        not(any(target_feature = "sse2", target_feature = "simd128")),
-        feature = "scalar-math"
-    ))]
+    #[cfg(feature = "scalar-math")]
     impl_vec4_float_tests!(f32, vec4, Vec4, Vec3, Vec2, BVec4);
 }
 
 mod dvec4 {
-    use glam::{dvec4, BVec4, DVec2, DVec3, DVec4};
+    use glam::{dvec4, BVec4, DVec2, DVec3, DVec4, IVec4, UVec4, Vec4};
 
     glam_test!(test_align, {
         use std::mem;
@@ -1292,11 +1581,295 @@
         assert_eq!(1, mem::align_of::<BVec4>());
     });
 
+    glam_test!(test_try_from, {
+        assert_eq!(
+            DVec4::new(1.0, 2.0, 3.0, 4.0),
+            DVec4::from(Vec4::new(1.0, 2.0, 3.0, 4.0))
+        );
+        assert_eq!(
+            DVec4::new(1.0, 2.0, 3.0, 4.0),
+            DVec4::from(IVec4::new(1, 2, 3, 4))
+        );
+        assert_eq!(
+            DVec4::new(1.0, 2.0, 3.0, 4.0),
+            DVec4::from(UVec4::new(1, 2, 3, 4))
+        );
+    });
+
     impl_vec4_float_tests!(f64, dvec4, DVec4, DVec3, DVec2, BVec4);
 }
 
+mod i16vec4 {
+    use glam::{
+        i16vec4, BVec4, I16Vec2, I16Vec3, I16Vec4, I64Vec4, IVec4, U16Vec4, U64Vec4, UVec4,
+    };
+
+    glam_test!(test_align, {
+        use std::mem;
+        assert_eq!(8, mem::size_of::<I16Vec4>());
+        #[cfg(not(feature = "cuda"))]
+        assert_eq!(2, mem::align_of::<I16Vec4>());
+        #[cfg(feature = "cuda")]
+        assert_eq!(8, mem::align_of::<I16Vec4>());
+    });
+
+    glam_test!(test_try_from, {
+        assert_eq!(
+            I16Vec4::new(1, 2, 3, 4),
+            I16Vec4::try_from(U16Vec4::new(1, 2, 3, 4)).unwrap()
+        );
+        assert!(I16Vec4::try_from(U16Vec4::new(u16::MAX, 2, 3, 4)).is_err());
+        assert!(I16Vec4::try_from(U16Vec4::new(1, u16::MAX, 3, 4)).is_err());
+        assert!(I16Vec4::try_from(U16Vec4::new(1, 2, u16::MAX, 4)).is_err());
+        assert!(I16Vec4::try_from(U16Vec4::new(1, 2, 3, u16::MAX)).is_err());
+
+        assert_eq!(
+            I16Vec4::new(1, 2, 3, 4),
+            I16Vec4::try_from(IVec4::new(1, 2, 3, 4)).unwrap()
+        );
+        assert!(I16Vec4::try_from(IVec4::new(i32::MAX, 2, 3, 4)).is_err());
+        assert!(I16Vec4::try_from(IVec4::new(1, i32::MAX, 3, 4)).is_err());
+        assert!(I16Vec4::try_from(IVec4::new(1, 2, i32::MAX, 4)).is_err());
+        assert!(I16Vec4::try_from(IVec4::new(1, 2, 3, i32::MAX)).is_err());
+
+        assert_eq!(
+            I16Vec4::new(1, 2, 3, 4),
+            I16Vec4::try_from(UVec4::new(1, 2, 3, 4)).unwrap()
+        );
+        assert!(I16Vec4::try_from(UVec4::new(u32::MAX, 2, 3, 4)).is_err());
+        assert!(I16Vec4::try_from(UVec4::new(1, u32::MAX, 3, 4)).is_err());
+        assert!(I16Vec4::try_from(UVec4::new(1, 2, u32::MAX, 4)).is_err());
+        assert!(I16Vec4::try_from(UVec4::new(1, 2, 3, u32::MAX)).is_err());
+
+        assert_eq!(
+            I16Vec4::new(1, 2, 3, 4),
+            I16Vec4::try_from(I64Vec4::new(1, 2, 3, 4)).unwrap()
+        );
+        assert!(I16Vec4::try_from(I64Vec4::new(i64::MAX, 2, 3, 4)).is_err());
+        assert!(I16Vec4::try_from(I64Vec4::new(1, i64::MAX, 3, 4)).is_err());
+        assert!(I16Vec4::try_from(I64Vec4::new(1, 2, i64::MAX, 4)).is_err());
+        assert!(I16Vec4::try_from(I64Vec4::new(1, 2, 3, i64::MAX)).is_err());
+
+        assert_eq!(
+            I16Vec4::new(1, 2, 3, 4),
+            I16Vec4::try_from(U64Vec4::new(1, 2, 3, 4)).unwrap()
+        );
+        assert!(I16Vec4::try_from(U64Vec4::new(u64::MAX, 2, 3, 4)).is_err());
+        assert!(I16Vec4::try_from(U64Vec4::new(1, u64::MAX, 3, 4)).is_err());
+        assert!(I16Vec4::try_from(U64Vec4::new(1, 2, u64::MAX, 4)).is_err());
+        assert!(I16Vec4::try_from(U64Vec4::new(1, 2, 3, u64::MAX)).is_err());
+    });
+
+    glam_test!(test_wrapping_add, {
+        assert_eq!(
+            I16Vec4::new(i16::MAX, 5, i16::MIN, 0).wrapping_add(I16Vec4::new(1, 3, i16::MAX, 0)),
+            I16Vec4::new(i16::MIN, 8, -1, 0),
+        );
+    });
+
+    glam_test!(test_wrapping_sub, {
+        assert_eq!(
+            I16Vec4::new(i16::MAX, 5, i16::MIN, 0).wrapping_sub(I16Vec4::new(1, 3, i16::MAX, 0)),
+            I16Vec4::new(32766, 2, 1, 0)
+        );
+    });
+
+    glam_test!(test_wrapping_mul, {
+        assert_eq!(
+            I16Vec4::new(i16::MAX, 5, i16::MIN, 0).wrapping_mul(I16Vec4::new(3, 3, 5, 1)),
+            I16Vec4::new(32765, 15, -32768, 0)
+        );
+    });
+
+    glam_test!(test_wrapping_div, {
+        assert_eq!(
+            I16Vec4::new(i16::MAX, 5, i16::MIN, 0).wrapping_div(I16Vec4::new(3, 3, 5, 1)),
+            I16Vec4::new(10922, 1, -6553, 0)
+        );
+    });
+
+    glam_test!(test_saturating_add, {
+        assert_eq!(
+            I16Vec4::new(i16::MAX, i16::MIN, 0, 0).saturating_add(I16Vec4::new(1, -1, 2, 3)),
+            I16Vec4::new(i16::MAX, i16::MIN, 2, 3)
+        );
+    });
+
+    glam_test!(test_saturating_sub, {
+        assert_eq!(
+            I16Vec4::new(i16::MIN, i16::MAX, 0, 0).saturating_sub(I16Vec4::new(1, -1, 2, 3)),
+            I16Vec4::new(i16::MIN, i16::MAX, -2, -3)
+        );
+    });
+
+    glam_test!(test_saturating_mul, {
+        assert_eq!(
+            I16Vec4::new(i16::MAX, i16::MIN, 0, 0).saturating_mul(I16Vec4::new(2, 2, 0, 0)),
+            I16Vec4::new(i16::MAX, i16::MIN, 0, 0)
+        );
+    });
+
+    glam_test!(test_saturating_div, {
+        assert_eq!(
+            I16Vec4::new(i16::MAX, i16::MIN, 0, 0).saturating_div(I16Vec4::new(2, 2, 3, 4)),
+            I16Vec4::new(16383, -16384, 0, 0)
+        );
+    });
+
+    impl_vec4_signed_integer_tests!(i16, i16vec4, I16Vec4, I16Vec3, I16Vec2, BVec4);
+    impl_vec4_eq_hash_tests!(i16, i16vec4);
+
+    impl_vec4_scalar_shift_op_tests!(I16Vec4, -2, 2);
+    impl_vec4_shift_op_tests!(I16Vec4);
+
+    impl_vec4_scalar_bit_op_tests!(I16Vec4, -2, 2);
+    impl_vec4_bit_op_tests!(I16Vec4, -2, 2);
+}
+
+mod u16vec4 {
+    use glam::{
+        u16vec4, BVec4, I16Vec4, I64Vec4, IVec4, U16Vec2, U16Vec3, U16Vec4, U64Vec4, UVec4,
+    };
+
+    glam_test!(test_align, {
+        use std::mem;
+        assert_eq!(8, mem::size_of::<U16Vec4>());
+        #[cfg(not(feature = "cuda"))]
+        assert_eq!(2, mem::align_of::<U16Vec4>());
+        #[cfg(feature = "cuda")]
+        assert_eq!(8, mem::align_of::<U16Vec4>());
+    });
+
+    glam_test!(test_try_from, {
+        assert_eq!(
+            U16Vec4::new(1, 2, 3, 4),
+            U16Vec4::try_from(I16Vec4::new(1, 2, 3, 4)).unwrap()
+        );
+        assert!(U16Vec4::try_from(I16Vec4::new(-1, 2, 3, 4)).is_err());
+        assert!(U16Vec4::try_from(I16Vec4::new(1, -2, 3, 4)).is_err());
+        assert!(U16Vec4::try_from(I16Vec4::new(1, 2, -3, 4)).is_err());
+        assert!(U16Vec4::try_from(I16Vec4::new(1, 2, 3, -4)).is_err());
+
+        assert_eq!(
+            U16Vec4::new(1, 2, 3, 4),
+            U16Vec4::try_from(IVec4::new(1, 2, 3, 4)).unwrap()
+        );
+        assert!(U16Vec4::try_from(IVec4::new(-1, 2, 3, 4)).is_err());
+        assert!(U16Vec4::try_from(IVec4::new(1, -2, 3, 4)).is_err());
+        assert!(U16Vec4::try_from(IVec4::new(1, 2, -3, 4)).is_err());
+        assert!(U16Vec4::try_from(IVec4::new(1, 2, 3, -4)).is_err());
+
+        assert!(U16Vec4::try_from(IVec4::new(i32::MAX, 2, 3, 4)).is_err());
+        assert!(U16Vec4::try_from(IVec4::new(1, i32::MAX, 3, 4)).is_err());
+        assert!(U16Vec4::try_from(IVec4::new(1, 2, i32::MAX, 4)).is_err());
+        assert!(U16Vec4::try_from(IVec4::new(1, 2, 3, i32::MAX)).is_err());
+
+        assert_eq!(
+            U16Vec4::new(1, 2, 3, 4),
+            U16Vec4::try_from(UVec4::new(1, 2, 3, 4)).unwrap()
+        );
+        assert!(U16Vec4::try_from(UVec4::new(u32::MAX, 2, 3, 4)).is_err());
+        assert!(U16Vec4::try_from(UVec4::new(1, u32::MAX, 3, 4)).is_err());
+        assert!(U16Vec4::try_from(UVec4::new(1, 2, u32::MAX, 4)).is_err());
+        assert!(U16Vec4::try_from(UVec4::new(1, 2, 3, u32::MAX)).is_err());
+
+        assert_eq!(
+            U16Vec4::new(1, 2, 3, 4),
+            U16Vec4::try_from(I64Vec4::new(1, 2, 3, 4)).unwrap()
+        );
+        assert!(U16Vec4::try_from(I64Vec4::new(-1, 2, 3, 4)).is_err());
+        assert!(U16Vec4::try_from(I64Vec4::new(1, -2, 3, 4)).is_err());
+        assert!(U16Vec4::try_from(I64Vec4::new(1, 2, -3, 4)).is_err());
+        assert!(U16Vec4::try_from(I64Vec4::new(1, 2, 3, -4)).is_err());
+
+        assert!(U16Vec4::try_from(I64Vec4::new(i64::MAX, 2, 3, 4)).is_err());
+        assert!(U16Vec4::try_from(I64Vec4::new(1, i64::MAX, 3, 4)).is_err());
+        assert!(U16Vec4::try_from(I64Vec4::new(1, 2, i64::MAX, 4)).is_err());
+        assert!(U16Vec4::try_from(I64Vec4::new(1, 2, 3, i64::MAX)).is_err());
+
+        assert_eq!(
+            U16Vec4::new(1, 2, 3, 4),
+            U16Vec4::try_from(U64Vec4::new(1, 2, 3, 4)).unwrap()
+        );
+        assert!(U16Vec4::try_from(U64Vec4::new(u64::MAX, 2, 3, 4)).is_err());
+        assert!(U16Vec4::try_from(U64Vec4::new(1, u64::MAX, 3, 4)).is_err());
+        assert!(U16Vec4::try_from(U64Vec4::new(1, 2, u64::MAX, 4)).is_err());
+        assert!(U16Vec4::try_from(U64Vec4::new(1, 2, 3, u64::MAX)).is_err());
+    });
+
+    glam_test!(test_wrapping_add, {
+        assert_eq!(
+            U16Vec4::new(u16::MAX, 5, u16::MAX, 0).wrapping_add(U16Vec4::new(1, 3, u16::MAX, 0)),
+            U16Vec4::new(0, 8, 65534, 0),
+        );
+    });
+
+    glam_test!(test_wrapping_sub, {
+        assert_eq!(
+            U16Vec4::new(u16::MAX, 5, u16::MAX - 1, 0).wrapping_sub(U16Vec4::new(
+                1,
+                3,
+                u16::MAX,
+                0
+            )),
+            U16Vec4::new(65534, 2, 65535, 0)
+        );
+    });
+
+    glam_test!(test_wrapping_mul, {
+        assert_eq!(
+            U16Vec4::new(u16::MAX, 5, u16::MAX, 0).wrapping_mul(U16Vec4::new(3, 3, 5, 1)),
+            U16Vec4::new(65533, 15, 65531, 0)
+        );
+    });
+
+    glam_test!(test_wrapping_div, {
+        assert_eq!(
+            U16Vec4::new(u16::MAX, 5, u16::MAX, 0).wrapping_div(U16Vec4::new(3, 3, 5, 1)),
+            U16Vec4::new(21845, 1, 13107, 0)
+        );
+    });
+
+    glam_test!(test_saturating_add, {
+        assert_eq!(
+            U16Vec4::new(u16::MAX, u16::MAX, 0, 0).saturating_add(U16Vec4::new(1, u16::MAX, 2, 3)),
+            U16Vec4::new(u16::MAX, u16::MAX, 2, 3)
+        );
+    });
+
+    glam_test!(test_saturating_sub, {
+        assert_eq!(
+            U16Vec4::new(0, u16::MAX, 0, 0).saturating_sub(U16Vec4::new(1, 1, 2, 3)),
+            U16Vec4::new(0, 65534, 0, 0)
+        );
+    });
+
+    glam_test!(test_saturating_mul, {
+        assert_eq!(
+            U16Vec4::new(u16::MAX, u16::MAX, 0, 0).saturating_mul(U16Vec4::new(2, u16::MAX, 0, 0)),
+            U16Vec4::new(u16::MAX, u16::MAX, 0, 0)
+        );
+    });
+
+    glam_test!(test_saturating_div, {
+        assert_eq!(
+            U16Vec4::new(u16::MAX, u16::MAX, 0, 0).saturating_div(U16Vec4::new(2, u16::MAX, 3, 4)),
+            U16Vec4::new(32767, 1, 0, 0)
+        );
+    });
+
+    impl_vec4_tests!(u16, u16vec4, U16Vec4, U16Vec3, U16Vec2, BVec4);
+    impl_vec4_eq_hash_tests!(u16, u16vec4);
+
+    impl_vec4_scalar_shift_op_tests!(U16Vec4, 0, 2);
+    impl_vec4_shift_op_tests!(U16Vec4);
+
+    impl_vec4_scalar_bit_op_tests!(U16Vec4, 0, 2);
+    impl_vec4_bit_op_tests!(U16Vec4, 0, 2);
+}
+
 mod ivec4 {
-    use glam::{ivec4, BVec4, IVec2, IVec3, IVec4, UVec4};
+    use glam::{ivec4, BVec4, I16Vec4, I64Vec4, IVec2, IVec3, IVec4, U16Vec4, U64Vec4, UVec4};
 
     glam_test!(test_align, {
         use std::mem;
@@ -1309,7 +1882,101 @@
         assert_eq!(1, mem::align_of::<BVec4>());
     });
 
-    impl_vec4_signed_tests!(i32, ivec4, IVec4, IVec3, IVec2, BVec4);
+    glam_test!(test_try_from, {
+        assert_eq!(
+            IVec4::new(1, 2, 3, 4),
+            IVec4::from(U16Vec4::new(1, 2, 3, 4))
+        );
+        assert_eq!(
+            IVec4::new(1, 2, 3, 4),
+            IVec4::from(I16Vec4::new(1, 2, 3, 4))
+        );
+
+        assert_eq!(
+            IVec4::new(1, 2, 3, 4),
+            IVec4::try_from(UVec4::new(1, 2, 3, 4)).unwrap()
+        );
+        assert!(IVec4::try_from(UVec4::new(u32::MAX, 2, 3, 4)).is_err());
+        assert!(IVec4::try_from(UVec4::new(1, u32::MAX, 3, 4)).is_err());
+        assert!(IVec4::try_from(UVec4::new(1, 2, u32::MAX, 4)).is_err());
+        assert!(IVec4::try_from(UVec4::new(1, 2, 3, u32::MAX)).is_err());
+
+        assert_eq!(
+            IVec4::new(1, 2, 3, 4),
+            IVec4::try_from(I64Vec4::new(1, 2, 3, 4)).unwrap()
+        );
+        assert!(IVec4::try_from(I64Vec4::new(i64::MAX, 2, 3, 4)).is_err());
+        assert!(IVec4::try_from(I64Vec4::new(1, i64::MAX, 3, 4)).is_err());
+        assert!(IVec4::try_from(I64Vec4::new(1, 2, i64::MAX, 4)).is_err());
+        assert!(IVec4::try_from(I64Vec4::new(1, 2, 3, i64::MAX)).is_err());
+
+        assert_eq!(
+            IVec4::new(1, 2, 3, 4),
+            IVec4::try_from(U64Vec4::new(1, 2, 3, 4)).unwrap()
+        );
+        assert!(IVec4::try_from(U64Vec4::new(u64::MAX, 2, 3, 4)).is_err());
+        assert!(IVec4::try_from(U64Vec4::new(1, u64::MAX, 3, 4)).is_err());
+        assert!(IVec4::try_from(U64Vec4::new(1, 2, u64::MAX, 4)).is_err());
+        assert!(IVec4::try_from(U64Vec4::new(1, 2, 3, u64::MAX)).is_err());
+    });
+
+    glam_test!(test_wrapping_add, {
+        assert_eq!(
+            IVec4::new(i32::MAX, 5, i32::MIN, 0).wrapping_add(IVec4::new(1, 3, i32::MAX, 0)),
+            IVec4::new(i32::MIN, 8, -1, 0),
+        );
+    });
+
+    glam_test!(test_wrapping_sub, {
+        assert_eq!(
+            IVec4::new(i32::MAX, 5, i32::MIN, 0).wrapping_sub(IVec4::new(1, 3, i32::MAX, 0)),
+            IVec4::new(2147483646, 2, 1, 0)
+        );
+    });
+
+    glam_test!(test_wrapping_mul, {
+        assert_eq!(
+            IVec4::new(i32::MAX, 5, i32::MIN, 0).wrapping_mul(IVec4::new(3, 3, 5, 1)),
+            IVec4::new(2147483645, 15, -2147483648, 0)
+        );
+    });
+
+    glam_test!(test_wrapping_div, {
+        assert_eq!(
+            IVec4::new(i32::MAX, 5, i32::MIN, 0).wrapping_div(IVec4::new(3, 3, 5, 1)),
+            IVec4::new(715827882, 1, -429496729, 0)
+        );
+    });
+
+    glam_test!(test_saturating_add, {
+        assert_eq!(
+            IVec4::new(i32::MAX, i32::MIN, 0, 0).saturating_add(IVec4::new(1, -1, 2, 3)),
+            IVec4::new(i32::MAX, i32::MIN, 2, 3)
+        );
+    });
+
+    glam_test!(test_saturating_sub, {
+        assert_eq!(
+            IVec4::new(i32::MIN, i32::MAX, 0, 0).saturating_sub(IVec4::new(1, -1, 2, 3)),
+            IVec4::new(i32::MIN, i32::MAX, -2, -3)
+        );
+    });
+
+    glam_test!(test_saturating_mul, {
+        assert_eq!(
+            IVec4::new(i32::MAX, i32::MIN, 0, 0).saturating_mul(IVec4::new(2, 2, 0, 0)),
+            IVec4::new(i32::MAX, i32::MIN, 0, 0)
+        );
+    });
+
+    glam_test!(test_saturating_div, {
+        assert_eq!(
+            IVec4::new(i32::MAX, i32::MIN, 0, 0).saturating_div(IVec4::new(2, 2, 3, 4)),
+            IVec4::new(1073741823, -1073741824, 0, 0)
+        );
+    });
+
+    impl_vec4_signed_integer_tests!(i32, ivec4, IVec4, IVec3, IVec2, BVec4);
     impl_vec4_eq_hash_tests!(i32, ivec4);
 
     impl_vec4_scalar_shift_op_tests!(IVec4, -2, 2);
@@ -1320,7 +1987,7 @@
 }
 
 mod uvec4 {
-    use glam::{uvec4, BVec4, IVec4, UVec2, UVec3, UVec4};
+    use glam::{uvec4, BVec4, I16Vec4, I64Vec4, IVec4, U16Vec4, U64Vec4, UVec2, UVec3, UVec4};
 
     glam_test!(test_align, {
         use std::mem;
@@ -1333,6 +2000,110 @@
         assert_eq!(1, mem::align_of::<BVec4>());
     });
 
+    glam_test!(test_try_from, {
+        assert_eq!(
+            UVec4::new(1, 2, 3, 4),
+            UVec4::try_from(I16Vec4::new(1, 2, 3, 4)).unwrap()
+        );
+        assert!(UVec4::try_from(I16Vec4::new(-1, 2, 3, 4)).is_err());
+        assert!(UVec4::try_from(I16Vec4::new(1, -2, 3, 4)).is_err());
+        assert!(UVec4::try_from(I16Vec4::new(1, 2, -3, 4)).is_err());
+        assert!(UVec4::try_from(I16Vec4::new(1, 2, 3, -4)).is_err());
+
+        assert_eq!(
+            UVec4::new(1, 2, 3, 4),
+            UVec4::from(U16Vec4::new(1, 2, 3, 4))
+        );
+
+        assert_eq!(
+            UVec4::new(1, 2, 3, 4),
+            UVec4::try_from(IVec4::new(1, 2, 3, 4)).unwrap()
+        );
+        assert!(UVec4::try_from(IVec4::new(-1, 2, 3, 4)).is_err());
+        assert!(UVec4::try_from(IVec4::new(1, -2, 3, 4)).is_err());
+        assert!(UVec4::try_from(IVec4::new(1, 2, -3, 4)).is_err());
+        assert!(UVec4::try_from(IVec4::new(1, 2, 3, -4)).is_err());
+
+        assert_eq!(
+            UVec4::new(1, 2, 3, 4),
+            UVec4::try_from(I64Vec4::new(1, 2, 3, 4)).unwrap()
+        );
+        assert!(UVec4::try_from(I64Vec4::new(-1, 2, 3, 4)).is_err());
+        assert!(UVec4::try_from(I64Vec4::new(1, -2, 3, 4)).is_err());
+        assert!(UVec4::try_from(I64Vec4::new(1, 2, -3, 4)).is_err());
+        assert!(UVec4::try_from(I64Vec4::new(1, 2, 3, -4)).is_err());
+
+        assert!(UVec4::try_from(I64Vec4::new(i64::MAX, 2, 3, 4)).is_err());
+        assert!(UVec4::try_from(I64Vec4::new(1, i64::MAX, 3, 4)).is_err());
+        assert!(UVec4::try_from(I64Vec4::new(1, 2, i64::MAX, 4)).is_err());
+        assert!(UVec4::try_from(I64Vec4::new(1, 2, 3, i64::MAX)).is_err());
+
+        assert_eq!(
+            UVec4::new(1, 2, 3, 4),
+            UVec4::try_from(U64Vec4::new(1, 2, 3, 4)).unwrap()
+        );
+        assert!(UVec4::try_from(U64Vec4::new(u64::MAX, 2, 3, 4)).is_err());
+        assert!(UVec4::try_from(U64Vec4::new(1, u64::MAX, 3, 4)).is_err());
+        assert!(UVec4::try_from(U64Vec4::new(1, 2, u64::MAX, 4)).is_err());
+        assert!(UVec4::try_from(U64Vec4::new(1, 2, 3, u64::MAX)).is_err());
+    });
+
+    glam_test!(test_wrapping_add, {
+        assert_eq!(
+            UVec4::new(u32::MAX, 5, u32::MAX, 0).wrapping_add(UVec4::new(1, 3, u32::MAX, 0)),
+            UVec4::new(0, 8, 4294967294, 0),
+        );
+    });
+
+    glam_test!(test_wrapping_sub, {
+        assert_eq!(
+            UVec4::new(u32::MAX, 5, u32::MAX - 1, 0).wrapping_sub(UVec4::new(1, 3, u32::MAX, 0)),
+            UVec4::new(4294967294, 2, 4294967295, 0)
+        );
+    });
+
+    glam_test!(test_wrapping_mul, {
+        assert_eq!(
+            UVec4::new(u32::MAX, 5, u32::MAX, 0).wrapping_mul(UVec4::new(3, 3, 5, 1)),
+            UVec4::new(4294967293, 15, 4294967291, 0)
+        );
+    });
+
+    glam_test!(test_wrapping_div, {
+        assert_eq!(
+            UVec4::new(u32::MAX, 5, u32::MAX, 0).wrapping_div(UVec4::new(3, 3, 5, 1)),
+            UVec4::new(1431655765, 1, 858993459, 0)
+        );
+    });
+
+    glam_test!(test_saturating_add, {
+        assert_eq!(
+            UVec4::new(u32::MAX, u32::MAX, 0, 0).saturating_add(UVec4::new(1, u32::MAX, 2, 3)),
+            UVec4::new(u32::MAX, u32::MAX, 2, 3)
+        );
+    });
+
+    glam_test!(test_saturating_sub, {
+        assert_eq!(
+            UVec4::new(0, u32::MAX, 0, 0).saturating_sub(UVec4::new(1, 1, 2, 3)),
+            UVec4::new(0, 4294967294, 0, 0)
+        );
+    });
+
+    glam_test!(test_saturating_mul, {
+        assert_eq!(
+            UVec4::new(u32::MAX, u32::MAX, 0, 0).saturating_mul(UVec4::new(2, u32::MAX, 0, 0)),
+            UVec4::new(u32::MAX, u32::MAX, 0, 0)
+        );
+    });
+
+    glam_test!(test_saturating_div, {
+        assert_eq!(
+            UVec4::new(u32::MAX, u32::MAX, 0, 0).saturating_div(UVec4::new(2, u32::MAX, 3, 4)),
+            UVec4::new(2147483647, 1, 0, 0)
+        );
+    });
+
     impl_vec4_tests!(u32, uvec4, UVec4, UVec3, UVec2, BVec4);
     impl_vec4_eq_hash_tests!(u32, uvec4);
 
@@ -1342,3 +2113,122 @@
     impl_vec4_scalar_bit_op_tests!(UVec4, 0, 2);
     impl_vec4_bit_op_tests!(UVec4, 0, 2);
 }
+
+mod i64vec4 {
+    use glam::{
+        i64vec4, BVec4, I16Vec4, I64Vec2, I64Vec3, I64Vec4, IVec4, U16Vec4, U64Vec4, UVec4,
+    };
+
+    glam_test!(test_align, {
+        use std::mem;
+        assert_eq!(32, mem::size_of::<I64Vec4>());
+        #[cfg(not(feature = "cuda"))]
+        assert_eq!(8, mem::align_of::<I64Vec4>());
+        #[cfg(feature = "cuda")]
+        assert_eq!(16, mem::align_of::<I64Vec4>());
+        assert_eq!(4, mem::size_of::<BVec4>());
+        assert_eq!(1, mem::align_of::<BVec4>());
+    });
+
+    glam_test!(test_try_from, {
+        assert_eq!(
+            I64Vec4::new(1, 2, 3, 4),
+            I64Vec4::from(I16Vec4::new(1, 2, 3, 4))
+        );
+        assert_eq!(
+            I64Vec4::new(1, 2, 3, 4),
+            I64Vec4::from(U16Vec4::new(1, 2, 3, 4))
+        );
+        assert_eq!(
+            I64Vec4::new(1, 2, 3, 4),
+            I64Vec4::from(IVec4::new(1, 2, 3, 4))
+        );
+        assert_eq!(
+            I64Vec4::new(1, 2, 3, 4),
+            I64Vec4::from(UVec4::new(1, 2, 3, 4))
+        );
+
+        assert_eq!(
+            I64Vec4::new(1, 2, 3, 4),
+            I64Vec4::try_from(U64Vec4::new(1, 2, 3, 4)).unwrap()
+        );
+        assert!(I64Vec4::try_from(U64Vec4::new(u64::MAX, 2, 3, 4)).is_err());
+        assert!(I64Vec4::try_from(U64Vec4::new(1, u64::MAX, 3, 4)).is_err());
+        assert!(I64Vec4::try_from(U64Vec4::new(1, 2, u64::MAX, 4)).is_err());
+        assert!(I64Vec4::try_from(U64Vec4::new(1, 2, 3, u64::MAX)).is_err());
+    });
+
+    impl_vec4_signed_integer_tests!(i64, i64vec4, I64Vec4, I64Vec3, I64Vec2, BVec4);
+    impl_vec4_eq_hash_tests!(i64, i64vec4);
+
+    impl_vec4_scalar_shift_op_tests!(I64Vec4, -2, 2);
+    impl_vec4_shift_op_tests!(I64Vec4);
+
+    impl_vec4_scalar_bit_op_tests!(I64Vec4, -2, 2);
+    impl_vec4_bit_op_tests!(I64Vec4, -2, 2);
+}
+
+mod u64vec4 {
+    use glam::{
+        u64vec4, BVec4, I16Vec4, I64Vec4, IVec4, U16Vec4, U64Vec2, U64Vec3, U64Vec4, UVec4,
+    };
+
+    glam_test!(test_align, {
+        use std::mem;
+        assert_eq!(32, mem::size_of::<U64Vec4>());
+        #[cfg(not(feature = "cuda"))]
+        assert_eq!(8, mem::align_of::<U64Vec4>());
+        #[cfg(feature = "cuda")]
+        assert_eq!(16, mem::align_of::<U64Vec4>());
+        assert_eq!(4, mem::size_of::<BVec4>());
+        assert_eq!(1, mem::align_of::<BVec4>());
+    });
+
+    glam_test!(test_try_from, {
+        assert_eq!(
+            U64Vec4::new(1, 2, 3, 4),
+            U64Vec4::try_from(I16Vec4::new(1, 2, 3, 4)).unwrap()
+        );
+        assert!(U64Vec4::try_from(I16Vec4::new(-1, 2, 3, 4)).is_err());
+        assert!(U64Vec4::try_from(I16Vec4::new(1, -2, 3, 4)).is_err());
+        assert!(U64Vec4::try_from(I16Vec4::new(1, 2, -3, 4)).is_err());
+        assert!(U64Vec4::try_from(I16Vec4::new(1, 2, 3, -4)).is_err());
+
+        assert_eq!(
+            U64Vec4::new(1, 2, 3, 4),
+            U64Vec4::from(U16Vec4::new(1, 2, 3, 4))
+        );
+
+        assert_eq!(
+            U64Vec4::new(1, 2, 3, 4),
+            U64Vec4::try_from(IVec4::new(1, 2, 3, 4)).unwrap()
+        );
+        assert!(U64Vec4::try_from(IVec4::new(-1, 2, 3, 4)).is_err());
+        assert!(U64Vec4::try_from(IVec4::new(1, -2, 3, 4)).is_err());
+        assert!(U64Vec4::try_from(IVec4::new(1, 2, -3, 4)).is_err());
+        assert!(U64Vec4::try_from(IVec4::new(1, 2, 3, -4)).is_err());
+
+        assert_eq!(
+            U64Vec4::new(1, 2, 3, 4),
+            U64Vec4::from(UVec4::new(1, 2, 3, 4))
+        );
+
+        assert_eq!(
+            U64Vec4::new(1, 2, 3, 4),
+            U64Vec4::try_from(I64Vec4::new(1, 2, 3, 4)).unwrap()
+        );
+        assert!(U64Vec4::try_from(I64Vec4::new(-1, 2, 3, 4)).is_err());
+        assert!(U64Vec4::try_from(I64Vec4::new(1, -2, 3, 4)).is_err());
+        assert!(U64Vec4::try_from(I64Vec4::new(1, 2, -3, 4)).is_err());
+        assert!(U64Vec4::try_from(I64Vec4::new(1, 2, 3, -4)).is_err());
+    });
+
+    impl_vec4_tests!(u64, u64vec4, U64Vec4, U64Vec3, U64Vec2, BVec4);
+    impl_vec4_eq_hash_tests!(u64, u64vec4);
+
+    impl_vec4_scalar_shift_op_tests!(U64Vec4, 0, 2);
+    impl_vec4_shift_op_tests!(U64Vec4);
+
+    impl_vec4_scalar_bit_op_tests!(U64Vec4, 0, 2);
+    impl_vec4_bit_op_tests!(U64Vec4, 0, 2);
+}